Skip to content

Commit 7c26da7

Browse files
committed
perf(plugin-vue): inline main script for build + avoid sourcemap generation when possible
improve production build performance.
1 parent bef4608 commit 7c26da7

File tree

6 files changed

+34
-51
lines changed

6 files changed

+34
-51
lines changed

packages/plugin-vue/src/handleHotUpdate.ts

+7-13
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@ import {
77
} from './utils/descriptorCache'
88
import { getResolvedScript, setResolvedScript } from './script'
99
import { ModuleNode, HmrContext } from 'vite'
10+
import { ResolvedOptions } from '.'
1011

1112
const debug = _debug('vite:hmr')
1213

1314
/**
1415
* Vite-specific HMR handling
1516
*/
16-
export async function handleHotUpdate({
17-
file,
18-
modules,
19-
read,
20-
server
21-
}: HmrContext): Promise<ModuleNode[] | void> {
22-
const prevDescriptor = getDescriptor(file, server.config.root, false, false)
17+
export async function handleHotUpdate(
18+
{ file, modules, read, server }: HmrContext,
19+
options: ResolvedOptions
20+
): Promise<ModuleNode[] | void> {
21+
const prevDescriptor = getDescriptor(file, options, false)
2322
if (!prevDescriptor) {
2423
// file hasn't been requested yet (e.g. async component)
2524
return
@@ -28,12 +27,7 @@ export async function handleHotUpdate({
2827
setPrevDescriptor(file, prevDescriptor)
2928

3029
const content = await read()
31-
const { descriptor } = createDescriptor(
32-
file,
33-
content,
34-
server.config.root,
35-
false
36-
)
30+
const { descriptor } = createDescriptor(file, content, options)
3731

3832
let needRerender = false
3933
const affectedModules = new Set<ModuleNode | undefined>()

packages/plugin-vue/src/index.ts

+7-12
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export interface Options {
8080

8181
export interface ResolvedOptions extends Options {
8282
root: string
83+
sourceMap: boolean
8384
devServer?: ViteDevServer
8485
}
8586

@@ -115,7 +116,8 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
115116
exclude,
116117
customElement,
117118
refTransform,
118-
root: process.cwd()
119+
root: process.cwd(),
120+
sourceMap: true
119121
}
120122

121123
return {
@@ -125,7 +127,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
125127
if (!filter(ctx.file)) {
126128
return
127129
}
128-
return handleHotUpdate(ctx)
130+
return handleHotUpdate(ctx, options)
129131
},
130132

131133
config(config) {
@@ -145,6 +147,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
145147
options = {
146148
...options,
147149
root: config.root,
150+
sourceMap: config.command === 'build' ? !!config.build.sourcemap : true,
148151
isProduction: config.isProduction
149152
}
150153
},
@@ -167,11 +170,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
167170
if (query.src) {
168171
return fs.readFileSync(filename, 'utf-8')
169172
}
170-
const descriptor = getDescriptor(
171-
filename,
172-
options.root,
173-
options.isProduction
174-
)!
173+
const descriptor = getDescriptor(filename, options)!
175174
let block: SFCBlock | null | undefined
176175
if (query.type === 'script') {
177176
// handle <scrip> + <script setup> merge via compileScript()
@@ -223,11 +222,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
223222
)
224223
} else {
225224
// sub block request
226-
const descriptor = getDescriptor(
227-
filename,
228-
options.root,
229-
options.isProduction
230-
)!
225+
const descriptor = getDescriptor(filename, options)!
231226
if (query.type === 'template') {
232227
return transformTemplateAsModule(code, descriptor, options, this, ssr)
233228
} else if (query.type === 'style') {

packages/plugin-vue/src/main.ts

+10-17
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,11 @@ export async function transformMain(
2525
ssr: boolean,
2626
asCustomElement: boolean
2727
) {
28-
const { root, devServer, isProduction } = options
28+
const { devServer, isProduction } = options
2929

3030
// prev descriptor is only set and used for hmr
3131
const prevDescriptor = getPrevDescriptor(filename)
32-
const { descriptor, errors } = createDescriptor(
33-
filename,
34-
code,
35-
root,
36-
isProduction
37-
)
32+
const { descriptor, errors } = createDescriptor(filename, code, options)
3833

3934
if (errors.length) {
4035
errors.forEach((error) =>
@@ -167,8 +162,8 @@ export async function transformMain(
167162

168163
// if the template is inlined into the main module (indicated by the presence
169164
// of templateMap, we need to concatenate the two source maps.
170-
let resolvedMap = map
171-
if (map && templateMap) {
165+
let resolvedMap = options.sourceMap ? map : undefined
166+
if (resolvedMap && templateMap) {
172167
const generator = SourceMapGenerator.fromSourceMap(
173168
new SourceMapConsumer(map)
174169
)
@@ -184,7 +179,7 @@ export async function transformMain(
184179
}
185180
})
186181
})
187-
resolvedMap = (generator as any).toJSON()
182+
resolvedMap = (generator as any).toJSON() as RawSourceMap
188183
// if this is a template only update, we will be reusing a cached version
189184
// of the main module compile result, which has outdated sourcesContent.
190185
resolvedMap.sourcesContent = templateMap.sourcesContent
@@ -195,13 +190,14 @@ export async function transformMain(
195190
// handle TS transpilation
196191
let resolvedCode = output.join('\n')
197192
if (
198-
descriptor.script?.lang === 'ts' ||
199-
descriptor.scriptSetup?.lang === 'ts'
193+
(descriptor.script?.lang === 'ts' ||
194+
descriptor.scriptSetup?.lang === 'ts') &&
195+
!descriptor.script?.src // only normal script can have src
200196
) {
201197
const { code, map } = await transformWithEsbuild(
202198
resolvedCode,
203199
filename,
204-
{ loader: 'ts' },
200+
{ loader: 'ts', sourcemap: options.sourceMap },
205201
resolvedMap
206202
)
207203
resolvedCode = code
@@ -268,10 +264,7 @@ async function genScriptCode(
268264
if (script) {
269265
// If the script is js/ts and has no external src, it can be directly placed
270266
// in the main module.
271-
if (
272-
(!script.lang || (script.lang === 'ts' && options.devServer)) &&
273-
!script.src
274-
) {
267+
if ((!script.lang || script.lang === 'ts') && !script.src) {
275268
scriptCode = rewriteDefault(script.content, '_sfc_main')
276269
map = script.map
277270
} else {

packages/plugin-vue/src/script.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export function resolveScript(
4444
isProd: options.isProduction,
4545
inlineTemplate: !options.devServer,
4646
refTransform: options.refTransform !== false,
47-
templateOptions: resolveTemplateCompilerOptions(descriptor, options, ssr)
47+
templateOptions: resolveTemplateCompilerOptions(descriptor, options, ssr),
48+
// @ts-ignore TODO remove ignore when we support this in @vue/compiler-sfc
49+
sourceMap: options.sourceMap
4850
})
4951

5052
cacheToUse.set(descriptor, resolved)

packages/plugin-vue/src/template.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ export function resolveTemplateCompilerOptions(
185185
...options.template?.compilerOptions,
186186
scopeId: hasScoped ? `data-v-${id}` : undefined,
187187
bindingMetadata: resolvedScript ? resolvedScript.bindings : undefined,
188-
expressionPlugins
188+
expressionPlugins,
189+
sourceMap: options.sourceMap
189190
}
190191
}
191192
}

packages/plugin-vue/src/utils/descriptorCache.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import path from 'path'
33
import slash from 'slash'
44
import hash from 'hash-sum'
55
import { CompilerError, parse, SFCDescriptor } from '@vue/compiler-sfc'
6+
import { ResolvedOptions } from '..'
67

78
// node_modules/@vue/compiler-sfc/dist/compiler-sfc.d.ts SFCParseResult should be exported so it can be re-used
89
export interface SFCParseResult {
@@ -16,12 +17,11 @@ const prevCache = new Map<string, SFCDescriptor | undefined>()
1617
export function createDescriptor(
1718
filename: string,
1819
source: string,
19-
root: string,
20-
isProduction: boolean | undefined
20+
{ root, isProduction, sourceMap }: ResolvedOptions
2121
): SFCParseResult {
2222
const { descriptor, errors } = parse(source, {
2323
filename,
24-
sourceMap: true
24+
sourceMap
2525
})
2626

2727
// ensure the path is normalized in a way that is consistent inside
@@ -46,8 +46,7 @@ export function setPrevDescriptor(
4646

4747
export function getDescriptor(
4848
filename: string,
49-
root: string,
50-
isProduction: boolean | undefined,
49+
options: ResolvedOptions,
5150
createIfNotFound = true
5251
): SFCDescriptor | undefined {
5352
if (cache.has(filename)) {
@@ -57,8 +56,7 @@ export function getDescriptor(
5756
const { descriptor, errors } = createDescriptor(
5857
filename,
5958
fs.readFileSync(filename, 'utf-8'),
60-
root,
61-
isProduction
59+
options
6260
)
6361
if (errors) {
6462
throw errors[0]

0 commit comments

Comments
 (0)