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

feat(mp): souremap (#3138)

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