提交 16001d9c 编写于 作者: fxy060608's avatar fxy060608

feat(mp): souremap (#3138)

上级 4bb74025
...@@ -14966,7 +14966,7 @@ var serviceContext = (function (vue) { ...@@ -14966,7 +14966,7 @@ var serviceContext = (function (vue) {
if (withArrayBuffer) { if (withArrayBuffer) {
stream.fetchWithArrayBuffer({ stream.fetchWithArrayBuffer({
'@type': 'binary', '@type': 'binary',
base64: arrayBufferToBase64(data) base64: arrayBufferToBase64(data),
}, options, callback); }, options, callback);
} }
else { else {
......
...@@ -9,7 +9,10 @@ import { ...@@ -9,7 +9,10 @@ import {
APP_SERVICE_FILENAME, APP_SERVICE_FILENAME,
} from '@dcloudio/uni-cli-shared' } from '@dcloudio/uni-cli-shared'
export function buildOptions(configEnv: ConfigEnv): UserConfig['build'] { export function buildOptions(
userConfig: UserConfig,
_: ConfigEnv
): UserConfig['build'] {
const inputDir = process.env.UNI_INPUT_DIR const inputDir = process.env.UNI_INPUT_DIR
const outputDir = process.env.UNI_OUTPUT_DIR const outputDir = process.env.UNI_OUTPUT_DIR
// 开始编译时,清空输出目录 // 开始编译时,清空输出目录
...@@ -17,7 +20,8 @@ export function buildOptions(configEnv: ConfigEnv): UserConfig['build'] { ...@@ -17,7 +20,8 @@ export function buildOptions(configEnv: ConfigEnv): UserConfig['build'] {
emptyDir(outputDir) emptyDir(outputDir)
} }
return { return {
// sourcemap: 'inline', // App 端目前仅提供 inline
sourcemap: userConfig.build?.sourcemap ? 'inline' : false,
emptyOutDir: false, // 不清空输出目录,否则会影响 webpack 的输出 emptyOutDir: false, // 不清空输出目录,否则会影响 webpack 的输出
assetsInlineLimit: 0, assetsInlineLimit: 0,
rollupOptions: { rollupOptions: {
......
...@@ -8,9 +8,9 @@ export function uniAppPlugin(): UniVitePlugin { ...@@ -8,9 +8,9 @@ export function uniAppPlugin(): UniVitePlugin {
return { return {
name: 'vite:uni-app', name: 'vite:uni-app',
uni: uniOptions(), uni: uniOptions(),
config(_, env) { config(config, env) {
return { return {
build: buildOptions(env), build: buildOptions(config, env),
} }
}, },
configResolved, configResolved,
......
...@@ -52,7 +52,9 @@ export function createApp() { ...@@ -52,7 +52,9 @@ export function createApp() {
'component-b': '/components/component-b', 'component-b': '/components/component-b',
}) })
expect(imports.length).toBe(2) expect(imports.length).toBe(2)
const code = await transformDynamicImports(source, imports, dynamicImport) const { code } = await transformDynamicImports(source, imports, {
dynamicImport,
})
expect(code).toContain(`import App from './App.vue'`) expect(code).toContain(`import App from './App.vue'`)
expect(code).toContain( expect(code).toContain(
`const ComponentA = ()=>import('${inputDir}/components/component-a.vue')` `const ComponentA = ()=>import('${inputDir}/components/component-a.vue')`
...@@ -94,7 +96,9 @@ export function createApp() { ...@@ -94,7 +96,9 @@ export function createApp() {
'component-b': '/components/component-b', 'component-b': '/components/component-b',
}) })
expect(imports.length).toBe(2) expect(imports.length).toBe(2)
const code = await transformDynamicImports(source, imports, dynamicImport) const { code } = await transformDynamicImports(source, imports, {
dynamicImport,
})
expect(code).toContain(`import App from './App.vue'`) expect(code).toContain(`import App from './App.vue'`)
expect(code).toContain( expect(code).toContain(
`const ComponentA = ()=>import('${inputDir}/components/component-a.vue')` `const ComponentA = ()=>import('${inputDir}/components/component-a.vue')`
...@@ -119,7 +123,7 @@ export function createApp() { ...@@ -119,7 +123,7 @@ export function createApp() {
usingComponents usingComponents
) )
expect( expect(
await transformDynamicImports(source, imports, dynamicImport) (await transformDynamicImports(source, imports, { dynamicImport })).code
).toContain(code) ).toContain(code)
} }
......
...@@ -567,10 +567,21 @@ async function parseVueComponentImports( ...@@ -567,10 +567,21 @@ async function parseVueComponentImports(
export async function transformDynamicImports( export async function transformDynamicImports(
code: string, code: string,
imports: ImportDeclaration[], imports: ImportDeclaration[],
dynamicImport: (name: string, source: string) => string {
id,
sourceMap,
dynamicImport,
}: {
id?: string
sourceMap?: boolean
dynamicImport: (name: string, source: string) => string
}
) { ) {
if (!imports.length) { if (!imports.length) {
return code return {
code,
map: null,
}
} }
const s = new MagicString(code) const s = new MagicString(code)
for (let i = 0; i < imports.length; i++) { for (let i = 0; i < imports.length; i++) {
...@@ -586,5 +597,8 @@ export async function transformDynamicImports( ...@@ -586,5 +597,8 @@ export async function transformDynamicImports(
dynamicImport(specifier.local.name, source.value) + ';' dynamicImport(specifier.local.name, source.value) + ';'
) )
} }
return s.toString() return {
code: s.toString(),
map: null,
}
} }
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
"estree-walker": "^2.0.2" "estree-walker": "^2.0.2"
}, },
"devDependencies": { "devDependencies": {
"@vue/compiler-sfc": "3.2.26" "@vue/compiler-sfc": "3.2.26",
"source-map": "^0.6.1"
} }
} }
import { isString, isSymbol, hasOwn } from '@vue/shared' import { isString, isSymbol, hasOwn } from '@vue/shared'
import { import {
advancePositionWithMutation,
CodegenResult, CodegenResult,
CompoundExpressionNode, CompoundExpressionNode,
helperNameMap, helperNameMap,
InterpolationNode, InterpolationNode,
isSimpleIdentifier,
locStub,
NodeTypes, NodeTypes,
Position,
RESOLVE_COMPONENT, RESOLVE_COMPONENT,
RootNode, RootNode,
SimpleExpressionNode, SimpleExpressionNode,
...@@ -14,6 +18,7 @@ import { ...@@ -14,6 +18,7 @@ import {
import { Expression } from '@babel/types' import { Expression } from '@babel/types'
import { default as babelGenerate, GeneratorOptions } from '@babel/generator' import { default as babelGenerate, GeneratorOptions } from '@babel/generator'
import { addImportDeclaration, matchEasycom } from '@dcloudio/uni-cli-shared' import { addImportDeclaration, matchEasycom } from '@dcloudio/uni-cli-shared'
import { SourceMapGenerator } from 'source-map'
import { CodegenOptions, CodegenRootNode } from './options' import { CodegenOptions, CodegenRootNode } from './options'
import { import {
...@@ -24,8 +29,13 @@ import { ...@@ -24,8 +29,13 @@ import {
interface CodegenContext extends Omit<CodegenOptions, 'renderDataExpr'> { interface CodegenContext extends Omit<CodegenOptions, 'renderDataExpr'> {
code: string code: string
source: string
line: number
column: number
offset: number
bindingComponents: TransformContext['bindingComponents'] bindingComponents: TransformContext['bindingComponents']
indentLevel: number indentLevel: number
map?: SourceMapGenerator
push(code: string, node?: CodegenNode): void push(code: string, node?: CodegenNode): void
indent(): void indent(): void
deindent(withoutNewLine?: boolean): void deindent(withoutNewLine?: boolean): void
...@@ -99,6 +109,8 @@ export function generate( ...@@ -99,6 +109,8 @@ export function generate(
return { return {
code: context.code, code: context.code,
preamble: isSetupInlined ? preambleContext.code : ``, preamble: isSetupInlined ? preambleContext.code : ``,
// SourceMapGenerator does have toJSON() method but it's not in the types
map: context.map ? (context.map as any).toJSON() : undefined,
} }
} }
...@@ -112,6 +124,7 @@ function createCodegenContext( ...@@ -112,6 +124,7 @@ function createCodegenContext(
runtimeGlobalName = `Vue`, runtimeGlobalName = `Vue`,
runtimeModuleName = `vue`, runtimeModuleName = `vue`,
isTS = false, isTS = false,
sourceMap = false,
}: CodegenOptions }: CodegenOptions
): CodegenContext { ): CodegenContext {
const context: CodegenContext = { const context: CodegenContext = {
...@@ -123,10 +136,30 @@ function createCodegenContext( ...@@ -123,10 +136,30 @@ function createCodegenContext(
runtimeModuleName, runtimeModuleName,
bindingComponents: ast.bindingComponents, bindingComponents: ast.bindingComponents,
isTS, isTS,
source: ast.loc.source,
code: ``, code: ``,
column: 1,
line: 1,
offset: 0,
indentLevel: 0, indentLevel: 0,
push(code, node) { push(code, node) {
context.code += code context.code += code
if (context.map) {
if (node) {
let name
if (node.type === NodeTypes.SIMPLE_EXPRESSION && !node.isStatic) {
const content = node.content.replace(/^_ctx\./, '')
if (content !== node.content && isSimpleIdentifier(content)) {
name = content
}
}
addMapping(node.loc.start, name)
}
advancePositionWithMutation(context, code)
if (node && node.loc !== locStub) {
addMapping(node.loc.end)
}
}
}, },
indent() { indent() {
newline(++context.indentLevel) newline(++context.indentLevel)
...@@ -147,6 +180,27 @@ function createCodegenContext( ...@@ -147,6 +180,27 @@ function createCodegenContext(
context.push('\n' + ` `.repeat(n)) context.push('\n' + ` `.repeat(n))
} }
function addMapping(loc: Position, name?: string) {
context.map!.addMapping({
name,
source: context.filename || '',
original: {
line: loc.line,
column: loc.column - 1, // source-map column is 0 based
},
generated: {
line: context.line,
column: context.column - 1,
},
})
}
// 暂时无需提供 sourcemap 支持
// if (sourceMap) {
// // lazy require source-map implementation
// context.map = new SourceMapGenerator()
// context.map!.setSourceContent(filename, context.source)
// }
return context return context
} }
...@@ -282,8 +336,6 @@ type CodegenNode = ...@@ -282,8 +336,6 @@ type CodegenNode =
| CompoundExpressionNode | CompoundExpressionNode
| InterpolationNode | InterpolationNode
| TextNode | TextNode
| string
| symbol
interface GenNodeContext { interface GenNodeContext {
code: string code: string
......
...@@ -92,6 +92,7 @@ export type CodegenScope = CodegenRootScope | CodegenVIfScope | CodegenVForScope ...@@ -92,6 +92,7 @@ export type CodegenScope = CodegenRootScope | CodegenVIfScope | CodegenVForScope
export interface CodegenOptions extends SharedTransformCodegenOptions { export interface CodegenOptions extends SharedTransformCodegenOptions {
mode?: 'module' | 'function' mode?: 'module' | 'function'
scopeId?: string | null scopeId?: string | null
sourceMap?: boolean
runtimeModuleName?: string runtimeModuleName?: string
runtimeGlobalName?: string runtimeGlobalName?: string
generatorOpts?: GeneratorOptions generatorOpts?: GeneratorOptions
......
...@@ -31,11 +31,16 @@ export function uniMainJsPlugin( ...@@ -31,11 +31,16 @@ export function uniMainJsPlugin(
resolve: this.resolve, resolve: this.resolve,
} }
) )
const { code, map } = await transformDynamicImports(source, imports, {
id,
sourceMap: !!opts.resolvedConfig.build.sourcemap,
dynamicImport,
})
return { return {
code: code:
`import 'plugin-vue:export-helper';import 'uni-mp-runtime';import './pages.json.js';` + `import 'plugin-vue:export-helper';import 'uni-mp-runtime';import './pages.json.js';` +
(await transformDynamicImports(source, imports, dynamicImport)), code,
map: this.getCombinedSourcemap(), map,
} }
} }
}, },
......
...@@ -54,7 +54,7 @@ export function uniManifestJsonPlugin( ...@@ -54,7 +54,7 @@ export function uniManifestJsonPlugin(
return { return {
code: '', code: '',
map: this.getCombinedSourcemap(), map: { mappings: '' },
} }
}, },
generateBundle() { generateBundle() {
......
...@@ -37,7 +37,7 @@ export function uniPagesJsonPlugin( ...@@ -37,7 +37,7 @@ export function uniPagesJsonPlugin(
}, },
transform(code, id) { transform(code, id) {
if (!opts.filter(id)) { if (!opts.filter(id)) {
return return null
} }
const inputDir = process.env.UNI_INPUT_DIR const inputDir = process.env.UNI_INPUT_DIR
this.addWatchFile(path.resolve(inputDir, 'pages.json')) this.addWatchFile(path.resolve(inputDir, 'pages.json'))
...@@ -74,7 +74,7 @@ export function uniPagesJsonPlugin( ...@@ -74,7 +74,7 @@ export function uniPagesJsonPlugin(
}) })
return { return {
code: `import './manifest.json.js'\n` + importPagesCode(appJson), code: `import './manifest.json.js'\n` + importPagesCode(appJson),
map: this.getCombinedSourcemap(), map: { mappings: '' },
} }
}, },
generateBundle() { generateBundle() {
......
...@@ -16,10 +16,6 @@ export function getFiltersCache(resolvedConfig: ResolvedConfig) { ...@@ -16,10 +16,6 @@ export function getFiltersCache(resolvedConfig: ResolvedConfig) {
return filtersCache.get(resolvedConfig) || [] return filtersCache.get(resolvedConfig) || []
} }
const defaultCode = {
code: 'export default {}',
}
export function uniRenderjsPlugin({ lang }: { lang?: string }): Plugin { export function uniRenderjsPlugin({ lang }: { lang?: string }): Plugin {
let resolvedConfig: ResolvedConfig let resolvedConfig: ResolvedConfig
return { return {
...@@ -33,11 +29,14 @@ export function uniRenderjsPlugin({ lang }: { lang?: string }): Plugin { ...@@ -33,11 +29,14 @@ export function uniRenderjsPlugin({ lang }: { lang?: string }): Plugin {
transform(code, id) { transform(code, id) {
const { type, name } = parseRenderjs(id) const { type, name } = parseRenderjs(id)
if (!type) { if (!type) {
return return null
} }
debugRenderjs(id) debugRenderjs(id)
if (type !== lang) { if (type !== lang) {
return defaultCode return {
code: 'export default {}',
map: { mappings: '' },
}
} }
this.addWatchFile(cleanUrl(id)) this.addWatchFile(cleanUrl(id))
if (!name) { if (!name) {
...@@ -50,7 +49,10 @@ export function uniRenderjsPlugin({ lang }: { lang?: string }): Plugin { ...@@ -50,7 +49,10 @@ export function uniRenderjsPlugin({ lang }: { lang?: string }): Plugin {
code, code,
}) })
} }
return defaultCode return {
code: 'export default {}',
map: { mappings: '' },
}
}, },
} }
} }
...@@ -33,7 +33,10 @@ export function uniRuntimeHooksPlugin(): Plugin { ...@@ -33,7 +33,10 @@ export function uniRuntimeHooksPlugin(): Plugin {
for (const hook of hooks) { for (const hook of hooks) {
flag |= MINI_PROGRAM_PAGE_RUNTIME_HOOKS[hook] flag |= MINI_PROGRAM_PAGE_RUNTIME_HOOKS[hook]
} }
return source + `;_sfc_main.__runtimeHooks = ${flag};` return {
code: source + `;_sfc_main.__runtimeHooks = ${flag};`,
map: { mappings: '' },
}
}, },
} }
} }
import path from 'path' import path from 'path'
import type { Plugin } from 'vite' import type { Plugin, ResolvedConfig } from 'vite'
import type { SFCScriptCompileOptions } from '@vue/compiler-sfc' import type { SFCScriptCompileOptions } from '@vue/compiler-sfc'
import { import {
EXTNAME_VUE, EXTNAME_VUE,
...@@ -25,14 +25,24 @@ export function uniUsingComponentsPlugin( ...@@ -25,14 +25,24 @@ export function uniUsingComponentsPlugin(
}) })
} }
const inputDir = process.env.UNI_INPUT_DIR const inputDir = process.env.UNI_INPUT_DIR
let resolvedConfig: ResolvedConfig
return { return {
name: 'vite:uni-mp-using-component', name: 'vite:uni-mp-using-component',
enforce: 'post', enforce: 'post',
configResolved(config) {
resolvedConfig = config
},
async transform(source, id) { async transform(source, id) {
const { filename, query } = parseVueRequest(id) const { filename, query } = parseVueRequest(id)
if (filename.endsWith('App.vue')) { if (filename.endsWith('App.vue')) {
return null return null
} }
const sourceMap = !!resolvedConfig.build.sourcemap
const dynamicImportOptions = {
id,
sourceMap,
dynamicImport,
}
if (query.vue) { if (query.vue) {
if (query.type === 'script') { if (query.type === 'script') {
// 需要主动监听 // 需要主动监听
...@@ -49,7 +59,7 @@ export function uniUsingComponentsPlugin( ...@@ -49,7 +59,7 @@ export function uniUsingComponentsPlugin(
return transformDynamicImports( return transformDynamicImports(
source, source,
descriptor.imports, descriptor.imports,
dynamicImport dynamicImportOptions
) )
} else if (query.type === 'template') { } else if (query.type === 'template') {
// 需要主动监听 // 需要主动监听
...@@ -66,7 +76,7 @@ export function uniUsingComponentsPlugin( ...@@ -66,7 +76,7 @@ export function uniUsingComponentsPlugin(
return transformDynamicImports( return transformDynamicImports(
source, source,
descriptor.imports, descriptor.imports,
dynamicImport dynamicImportOptions
) )
} }
return null return null
...@@ -81,7 +91,11 @@ export function uniUsingComponentsPlugin( ...@@ -81,7 +91,11 @@ export function uniUsingComponentsPlugin(
updateMiniProgramComponentsByMainFilename(filename, inputDir) updateMiniProgramComponentsByMainFilename(filename, inputDir)
return transformDynamicImports(source, descriptor.imports, dynamicImport) return transformDynamicImports(
source,
descriptor.imports,
dynamicImportOptions
)
}, },
} }
} }
......
...@@ -597,6 +597,7 @@ importers: ...@@ -597,6 +597,7 @@ importers:
'@vue/compiler-sfc': 3.2.26 '@vue/compiler-sfc': 3.2.26
'@vue/shared': 3.2.26 '@vue/shared': 3.2.26
estree-walker: ^2.0.2 estree-walker: ^2.0.2
source-map: ^0.6.1
dependencies: dependencies:
'@babel/generator': 7.16.0 '@babel/generator': 7.16.0
'@babel/parser': 7.16.4 '@babel/parser': 7.16.4
...@@ -609,6 +610,7 @@ importers: ...@@ -609,6 +610,7 @@ importers:
estree-walker: 2.0.2 estree-walker: 2.0.2
devDependencies: devDependencies:
'@vue/compiler-sfc': 3.2.26 '@vue/compiler-sfc': 3.2.26
source-map: 0.6.1
packages/uni-mp-core: packages/uni-mp-core:
specifiers: {} specifiers: {}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册