Skip to content

Commit bd0f7da

Browse files
committed
build: add browser builds for @vue/compiler-sfc
1 parent 0bb1f67 commit bd0f7da

File tree

13 files changed

+745
-86
lines changed

13 files changed

+745
-86
lines changed

package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"node": ">=10.0.0"
4141
},
4242
"devDependencies": {
43+
"@ls-lint/ls-lint": "^1.8.0",
4344
"@microsoft/api-extractor": "^7.3.9",
4445
"@rollup/plugin-commonjs": "^11.0.2",
4546
"@rollup/plugin-json": "^4.0.0",
@@ -62,14 +63,15 @@
6263
"prettier": "~1.14.0",
6364
"puppeteer": "^2.0.0",
6465
"rollup": "^2.2.0",
66+
"rollup-plugin-node-builtins": "^2.1.2",
67+
"rollup-plugin-node-globals": "^1.4.0",
6568
"rollup-plugin-terser": "^5.3.0",
6669
"rollup-plugin-typescript2": "^0.27.0",
6770
"semver": "^6.3.0",
6871
"serve": "^11.3.0",
6972
"ts-jest": "^25.2.1",
7073
"tsd": "^0.11.0",
7174
"typescript": "^3.8.3",
72-
"yorkie": "^2.0.0",
73-
"@ls-lint/ls-lint": "^1.8.0"
75+
"yorkie": "^2.0.0"
7476
}
7577
}

packages/compiler-core/src/codegen.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
advancePositionWithMutation,
3232
assert,
3333
isSimpleIdentifier,
34-
loadDep,
3534
toValidAssetId
3635
} from './utils'
3736
import { isString, isArray, isSymbol } from '@vue/shared'
@@ -167,7 +166,7 @@ function createCodegenContext(
167166

168167
if (!__BROWSER__ && sourceMap) {
169168
// lazy require source-map implementation, only in non-browser builds
170-
context.map = new (loadDep('source-map')).SourceMapGenerator()
169+
context.map = new SourceMapGenerator()
171170
context.map!.setSourceContent(filename, context.source)
172171
}
173172

packages/compiler-core/src/utils.ts

+19-30
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ import {
3030
KEEP_ALIVE,
3131
BASE_TRANSITION
3232
} from './runtimeHelpers'
33-
import { isString, isFunction, isObject, hyphenate } from '@vue/shared'
33+
import { isString, isObject, hyphenate } from '@vue/shared'
3434
import { parse } from '@babel/parser'
35+
import { walk } from 'estree-walker'
3536
import { Node } from '@babel/types'
3637

3738
export const isBuiltInType = (tag: string, expected: string): boolean =>
@@ -49,31 +50,16 @@ export function isCoreComponent(tag: string): symbol | void {
4950
}
5051
}
5152

52-
// cache node requires
53-
// lazy require dependencies so that they don't end up in rollup's dep graph
54-
// and thus can be tree-shaken in browser builds.
55-
let _parse: typeof parse
56-
let _walk: any
57-
58-
export function loadDep(name: string) {
59-
if (!__BROWSER__ && typeof process !== 'undefined' && isFunction(require)) {
60-
return require(name)
61-
} else {
62-
// This is only used when we are building a dev-only build of the compiler
63-
// which runs in the browser but also uses Node deps.
64-
return (window as any)._deps[name]
65-
}
66-
}
67-
6853
export const parseJS: typeof parse = (code, options) => {
69-
assert(
70-
!__BROWSER__,
71-
`Expression AST analysis can only be performed in non-browser builds.`
72-
)
73-
if (!_parse) {
74-
_parse = loadDep('@babel/parser').parse
54+
if (__BROWSER__) {
55+
assert(
56+
!__BROWSER__,
57+
`Expression AST analysis can only be performed in non-browser builds.`
58+
)
59+
return null as any
60+
} else {
61+
return parse(code, options)
7562
}
76-
return _parse(code, options)
7763
}
7864

7965
interface Walker {
@@ -82,12 +68,15 @@ interface Walker {
8268
}
8369

8470
export const walkJS = (ast: Node, walker: Walker) => {
85-
assert(
86-
!__BROWSER__,
87-
`Expression AST analysis can only be performed in non-browser builds.`
88-
)
89-
const walk = _walk || (_walk = loadDep('estree-walker').walk)
90-
return walk(ast, walker)
71+
if (__BROWSER__) {
72+
assert(
73+
!__BROWSER__,
74+
`Expression AST analysis can only be performed in non-browser builds.`
75+
)
76+
return null as any
77+
} else {
78+
return (walk as any)(ast, walker)
79+
}
9180
}
9281

9382
const nonIdentifierRE = /^\d|[^\$\w]/

packages/compiler-sfc/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ This package contains lower level utilities that you can use if you are writing
66

77
The API surface is intentionally minimal - the goal is to reuse as much as possible while being as flexible as possible.
88

9+
## Browser Build Usage
10+
11+
This package relies on `postcss`, `postcss-selector-parser` and `postcss-modules`
12+
913
## API
1014

1115
TODO

packages/compiler-sfc/package.json

+7-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@
88
"dist"
99
],
1010
"buildOptions": {
11-
"prod": false,
11+
"name": "VueCompilerSFC",
1212
"formats": [
13-
"cjs"
14-
]
13+
"cjs",
14+
"global",
15+
"esm-browser"
16+
],
17+
"prod": false,
18+
"enableNonBrowserBranches": true
1519
},
1620
"repository": {
1721
"type": "git",

packages/compiler-sfc/src/compileStyle.ts

+22-10
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,24 @@ export function doCompileStyle(
9494
}
9595
let cssModules: Record<string, string> | undefined
9696
if (modules) {
97-
if (options.isAsync) {
98-
plugins.push(
99-
require('postcss-modules')({
100-
...modulesOptions,
101-
getJSON: (cssFileName: string, json: Record<string, string>) => {
102-
cssModules = json
103-
}
104-
})
97+
if (__GLOBAL__ || __ESM_BROWSER__) {
98+
throw new Error(
99+
'[@vue/compiler-sfc] `modules` option is not supported in the browser build.'
105100
)
106-
} else {
101+
}
102+
if (!options.isAsync) {
107103
throw new Error(
108-
'`modules` option can only be used with compileStyleAsync().'
104+
'[@vue/compiler-sfc] `modules` option can only be used with compileStyleAsync().'
109105
)
110106
}
107+
plugins.push(
108+
require('postcss-modules')({
109+
...modulesOptions,
110+
getJSON: (_cssFileName: string, json: Record<string, string>) => {
111+
cssModules = json
112+
}
113+
})
114+
)
111115
}
112116

113117
const postCSSOptions: ProcessOptions = {
@@ -172,6 +176,14 @@ function preprocess(
172176
options: SFCStyleCompileOptions,
173177
preprocessor: StylePreprocessor
174178
): StylePreprocessorResults {
179+
if ((__ESM_BROWSER__ || __GLOBAL__) && !options.preprocessCustomRequire) {
180+
throw new Error(
181+
`[@vue/compiler-sfc] Style preprocessing in the browser build must ` +
182+
`provide the \`preprocessCustomRequire\` option to return the in-browser ` +
183+
`version of the preprocessor.`
184+
)
185+
}
186+
175187
return preprocessor.render(
176188
options.source,
177189
options.map,

packages/compiler-sfc/src/compileTemplate.ts

+23-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
} from './templateTransformAssetUrl'
1515
import { transformSrcset } from './templateTransformSrcset'
1616
import { isObject } from '@vue/shared'
17+
import * as CompilerDOM from '@vue/compiler-dom'
18+
import * as CompilerSSR from '@vue/compiler-ssr'
1719
import consolidate from 'consolidate'
1820

1921
export interface TemplateCompiler {
@@ -38,6 +40,7 @@ export interface SFCTemplateCompileOptions {
3840
compilerOptions?: CompilerOptions
3941
preprocessLang?: string
4042
preprocessOptions?: any
43+
preprocessCustomRequire?: (id: string) => any
4144
transformAssetUrls?: AssetURLOptions | boolean
4245
}
4346

@@ -66,9 +69,25 @@ function preprocess(
6669
export function compileTemplate(
6770
options: SFCTemplateCompileOptions
6871
): SFCTemplateCompileResults {
69-
const { preprocessLang } = options
70-
const preprocessor =
71-
preprocessLang && consolidate[preprocessLang as keyof typeof consolidate]
72+
const { preprocessLang, preprocessCustomRequire } = options
73+
74+
if (
75+
(__ESM_BROWSER__ || __GLOBAL__) &&
76+
preprocessLang &&
77+
!preprocessCustomRequire
78+
) {
79+
throw new Error(
80+
`[@vue/compiler-sfc] Template preprocessing in the browser build must ` +
81+
`provide the \`preprocessCustomRequire\` option to return the in-browser ` +
82+
`version of the preprocessor in the shape of { render(): string }.`
83+
)
84+
}
85+
86+
const preprocessor = preprocessLang
87+
? preprocessCustomRequire
88+
? preprocessCustomRequire(preprocessLang)
89+
: require('consolidate')[preprocessLang as keyof typeof consolidate]
90+
: false
7291
if (preprocessor) {
7392
try {
7493
return doCompileTemplate({
@@ -108,7 +127,7 @@ function doCompileTemplate({
108127
inMap,
109128
source,
110129
ssr = false,
111-
compiler = ssr ? require('@vue/compiler-ssr') : require('@vue/compiler-dom'),
130+
compiler = ssr ? (CompilerSSR as TemplateCompiler) : CompilerDOM,
112131
compilerOptions = {},
113132
transformAssetUrls
114133
}: SFCTemplateCompileOptions): SFCTemplateCompileResults {

packages/compiler-sfc/src/parse.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import {
66
TextModes
77
} from '@vue/compiler-core'
88
import { RawSourceMap, SourceMapGenerator } from 'source-map'
9-
import LRUCache from 'lru-cache'
109
import { generateCodeFrame } from '@vue/shared'
1110
import { TemplateCompiler } from './compileTemplate'
11+
import * as CompilerDOM from '@vue/compiler-dom'
1212

1313
export interface SFCParseOptions {
1414
filename?: string
@@ -57,7 +57,13 @@ export interface SFCParseResult {
5757
}
5858

5959
const SFC_CACHE_MAX_SIZE = 500
60-
const sourceToSFC = new LRUCache<string, SFCParseResult>(SFC_CACHE_MAX_SIZE)
60+
const sourceToSFC =
61+
__GLOBAL__ || __ESM_BROWSER__
62+
? new Map<string, SFCParseResult>()
63+
: (new (require('lru-cache'))(SFC_CACHE_MAX_SIZE) as Map<
64+
string,
65+
SFCParseResult
66+
>)
6167

6268
export function parse(
6369
source: string,
@@ -66,7 +72,7 @@ export function parse(
6672
filename = 'component.vue',
6773
sourceRoot = '',
6874
pad = false,
69-
compiler = require('@vue/compiler-dom')
75+
compiler = CompilerDOM
7076
}: SFCParseOptions = {}
7177
): SFCParseResult {
7278
const sourceKey =

packages/template-explorer/index.html

-7
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,8 @@
66
<div id="source" class="editor"></div>
77
<div id="output" class="editor"></div>
88

9-
<script src="https://unpkg.com/[email protected]/dist/estree-walker.umd.js"></script>
10-
<script src="https://unpkg.com/[email protected]/dist/source-map.js"></script>
119
<script src="https://unpkg.com/[email protected]/min/vs/loader.js"></script>
1210
<script>
13-
window._deps = {
14-
'estree-walker': estreeWalker,
15-
'source-map': sourceMap
16-
}
17-
1811
require.config({
1912
paths: {
2013
'vs': 'https://unpkg.com/[email protected]/min/vs'

packages/template-explorer/local.html

-8
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,8 @@
66
<div id="source" class="editor"></div>
77
<div id="output" class="editor"></div>
88

9-
<script src="../../node_modules/estree-walker/dist/estree-walker.umd.js"></script>
10-
<script src="../../node_modules/source-map/dist/source-map.js"></script>
119
<script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
1210
<script>
13-
window._deps = {
14-
// @babel/parser is injected by the bundle
15-
'estree-walker': estreeWalker,
16-
'source-map': sourceMap
17-
}
18-
1911
require.config({
2012
paths: {
2113
'vs': '../../node_modules/monaco-editor/min/vs'

packages/template-explorer/src/index.ts

+1-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ import { compile as ssrCompile } from '@vue/compiler-ssr'
44
import { compilerOptions, initOptions, ssrMode } from './options'
55
import { watchEffect } from '@vue/runtime-dom'
66
import { SourceMapConsumer } from 'source-map'
7-
import { parse } from '@babel/parser'
8-
9-
window._deps['@babel/parser'] = { parse }
107

118
declare global {
129
interface Window {
@@ -57,7 +54,7 @@ window.init = () => {
5754
)
5855
console.log(`AST: `, ast)
5956
lastSuccessfulCode = code + `\n\n// Check the console for the AST`
60-
lastSuccessfulMap = new window._deps['source-map'].SourceMapConsumer(map)
57+
lastSuccessfulMap = new SourceMapConsumer(map!)
6158
lastSuccessfulMap!.computeColumnSpans()
6259
} catch (e) {
6360
lastSuccessfulCode = `/* ERROR: ${

0 commit comments

Comments
 (0)