Skip to content

Commit

Permalink
perf(plugin-vue): inline main script for build + avoid sourcemap gene…
Browse files Browse the repository at this point in the history
…ration when possible

improve production build performance.
  • Loading branch information
yyx990803 committed Sep 18, 2021
1 parent bef4608 commit 7c26da7
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 51 deletions.
20 changes: 7 additions & 13 deletions packages/plugin-vue/src/handleHotUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,18 @@ import {
} from './utils/descriptorCache'
import { getResolvedScript, setResolvedScript } from './script'
import { ModuleNode, HmrContext } from 'vite'
import { ResolvedOptions } from '.'

const debug = _debug('vite:hmr')

/**
* Vite-specific HMR handling
*/
export async function handleHotUpdate({
file,
modules,
read,
server
}: HmrContext): Promise<ModuleNode[] | void> {
const prevDescriptor = getDescriptor(file, server.config.root, false, false)
export async function handleHotUpdate(
{ file, modules, read, server }: HmrContext,
options: ResolvedOptions
): Promise<ModuleNode[] | void> {
const prevDescriptor = getDescriptor(file, options, false)
if (!prevDescriptor) {
// file hasn't been requested yet (e.g. async component)
return
Expand All @@ -28,12 +27,7 @@ export async function handleHotUpdate({
setPrevDescriptor(file, prevDescriptor)

const content = await read()
const { descriptor } = createDescriptor(
file,
content,
server.config.root,
false
)
const { descriptor } = createDescriptor(file, content, options)

let needRerender = false
const affectedModules = new Set<ModuleNode | undefined>()
Expand Down
19 changes: 7 additions & 12 deletions packages/plugin-vue/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export interface Options {

export interface ResolvedOptions extends Options {
root: string
sourceMap: boolean
devServer?: ViteDevServer
}

Expand Down Expand Up @@ -115,7 +116,8 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
exclude,
customElement,
refTransform,
root: process.cwd()
root: process.cwd(),
sourceMap: true
}

return {
Expand All @@ -125,7 +127,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
if (!filter(ctx.file)) {
return
}
return handleHotUpdate(ctx)
return handleHotUpdate(ctx, options)
},

config(config) {
Expand All @@ -145,6 +147,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
options = {
...options,
root: config.root,
sourceMap: config.command === 'build' ? !!config.build.sourcemap : true,
isProduction: config.isProduction
}
},
Expand All @@ -167,11 +170,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
if (query.src) {
return fs.readFileSync(filename, 'utf-8')
}
const descriptor = getDescriptor(
filename,
options.root,
options.isProduction
)!
const descriptor = getDescriptor(filename, options)!
let block: SFCBlock | null | undefined
if (query.type === 'script') {
// handle <scrip> + <script setup> merge via compileScript()
Expand Down Expand Up @@ -223,11 +222,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin {
)
} else {
// sub block request
const descriptor = getDescriptor(
filename,
options.root,
options.isProduction
)!
const descriptor = getDescriptor(filename, options)!
if (query.type === 'template') {
return transformTemplateAsModule(code, descriptor, options, this, ssr)
} else if (query.type === 'style') {
Expand Down
27 changes: 10 additions & 17 deletions packages/plugin-vue/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,11 @@ export async function transformMain(
ssr: boolean,
asCustomElement: boolean
) {
const { root, devServer, isProduction } = options
const { devServer, isProduction } = options

// prev descriptor is only set and used for hmr
const prevDescriptor = getPrevDescriptor(filename)
const { descriptor, errors } = createDescriptor(
filename,
code,
root,
isProduction
)
const { descriptor, errors } = createDescriptor(filename, code, options)

if (errors.length) {
errors.forEach((error) =>
Expand Down Expand Up @@ -167,8 +162,8 @@ export async function transformMain(

// if the template is inlined into the main module (indicated by the presence
// of templateMap, we need to concatenate the two source maps.
let resolvedMap = map
if (map && templateMap) {
let resolvedMap = options.sourceMap ? map : undefined
if (resolvedMap && templateMap) {
const generator = SourceMapGenerator.fromSourceMap(
new SourceMapConsumer(map)
)
Expand All @@ -184,7 +179,7 @@ export async function transformMain(
}
})
})
resolvedMap = (generator as any).toJSON()
resolvedMap = (generator as any).toJSON() as RawSourceMap
// if this is a template only update, we will be reusing a cached version
// of the main module compile result, which has outdated sourcesContent.
resolvedMap.sourcesContent = templateMap.sourcesContent
Expand All @@ -195,13 +190,14 @@ export async function transformMain(
// handle TS transpilation
let resolvedCode = output.join('\n')
if (
descriptor.script?.lang === 'ts' ||
descriptor.scriptSetup?.lang === 'ts'
(descriptor.script?.lang === 'ts' ||
descriptor.scriptSetup?.lang === 'ts') &&
!descriptor.script?.src // only normal script can have src
) {
const { code, map } = await transformWithEsbuild(
resolvedCode,
filename,
{ loader: 'ts' },
{ loader: 'ts', sourcemap: options.sourceMap },
resolvedMap
)
resolvedCode = code
Expand Down Expand Up @@ -268,10 +264,7 @@ async function genScriptCode(
if (script) {
// If the script is js/ts and has no external src, it can be directly placed
// in the main module.
if (
(!script.lang || (script.lang === 'ts' && options.devServer)) &&
!script.src
) {
if ((!script.lang || script.lang === 'ts') && !script.src) {
scriptCode = rewriteDefault(script.content, '_sfc_main')
map = script.map
} else {
Expand Down
4 changes: 3 additions & 1 deletion packages/plugin-vue/src/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export function resolveScript(
isProd: options.isProduction,
inlineTemplate: !options.devServer,
refTransform: options.refTransform !== false,
templateOptions: resolveTemplateCompilerOptions(descriptor, options, ssr)
templateOptions: resolveTemplateCompilerOptions(descriptor, options, ssr),
// @ts-ignore TODO remove ignore when we support this in @vue/compiler-sfc
sourceMap: options.sourceMap
})

cacheToUse.set(descriptor, resolved)
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-vue/src/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ export function resolveTemplateCompilerOptions(
...options.template?.compilerOptions,
scopeId: hasScoped ? `data-v-${id}` : undefined,
bindingMetadata: resolvedScript ? resolvedScript.bindings : undefined,
expressionPlugins
expressionPlugins,
sourceMap: options.sourceMap
}
}
}
12 changes: 5 additions & 7 deletions packages/plugin-vue/src/utils/descriptorCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'path'
import slash from 'slash'
import hash from 'hash-sum'
import { CompilerError, parse, SFCDescriptor } from '@vue/compiler-sfc'
import { ResolvedOptions } from '..'

// node_modules/@vue/compiler-sfc/dist/compiler-sfc.d.ts SFCParseResult should be exported so it can be re-used
export interface SFCParseResult {
Expand All @@ -16,12 +17,11 @@ const prevCache = new Map<string, SFCDescriptor | undefined>()
export function createDescriptor(
filename: string,
source: string,
root: string,
isProduction: boolean | undefined
{ root, isProduction, sourceMap }: ResolvedOptions
): SFCParseResult {
const { descriptor, errors } = parse(source, {
filename,
sourceMap: true
sourceMap
})

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

export function getDescriptor(
filename: string,
root: string,
isProduction: boolean | undefined,
options: ResolvedOptions,
createIfNotFound = true
): SFCDescriptor | undefined {
if (cache.has(filename)) {
Expand All @@ -57,8 +56,7 @@ export function getDescriptor(
const { descriptor, errors } = createDescriptor(
filename,
fs.readFileSync(filename, 'utf-8'),
root,
isProduction
options
)
if (errors) {
throw errors[0]
Expand Down

0 comments on commit 7c26da7

Please sign in to comment.