Skip to content
This repository was archived by the owner on Jan 18, 2022. It is now read-only.

Commit 4f5e698

Browse files
committed
wip: improve source map integration w/ vite
1 parent 90209a7 commit 4f5e698

7 files changed

+286
-38
lines changed

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 2"
1919
},
2020
"dependencies": {
21+
"@rollup/pluginutils": "^4.1.0",
2122
"debug": "^4.1.1",
2223
"hash-sum": "^2.0.0",
23-
"@rollup/pluginutils": "^4.1.0"
24+
"source-map": "^0.6.1"
2425
},
2526
"peerDependencies": {
2627
"@vue/compiler-sfc": "*"
@@ -38,6 +39,7 @@
3839
"lint-staged": "^10.1.7",
3940
"npm-run-all": "^4.1.5",
4041
"prettier": "^2.0.5",
42+
"pug": "^3.0.0",
4143
"rollup": "^2.7.2",
4244
"rollup-plugin-postcss": "^3.1.8",
4345
"ts-jest": "^26.0.0",
@@ -55,7 +57,6 @@
5557
},
5658
"prettier": {
5759
"printWidth": 80,
58-
"trailingComma": "es5",
5960
"semi": false,
6061
"singleQuote": true
6162
}

src/handleHotUpdate.ts

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ export async function handleHotUpdate(file: string, modules: any[]) {
3333
const { descriptor } = parse(content, {
3434
filename: file,
3535
sourceMap: true,
36-
sourceRoot: process.cwd(),
3736
})
3837
setDescriptor(file, descriptor)
3938
setPrevDescriptor(file, prevDescriptor)

src/index.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import { transformStyle } from './style'
2121
import { createCustomBlockFilter } from './utils/customBlockFilter'
2222
import { getDescriptor, setDescriptor } from './utils/descriptorCache'
2323
import { parseVuePartRequest } from './utils/query'
24-
import { normalizeSourceMap } from './utils/sourceMap'
2524
import { getResolvedScript } from './script'
2625
import { handleHotUpdate } from './handleHotUpdate'
2726

@@ -131,7 +130,7 @@ export default function PluginVue(userOptions: Partial<Options> = {}): Plugin {
131130
if (block) {
132131
return {
133132
code: block.content,
134-
map: normalizeSourceMap(block.map, id),
133+
map: block.map as any,
135134
}
136135
}
137136
}
@@ -171,10 +170,10 @@ export default function PluginVue(userOptions: Partial<Options> = {}): Plugin {
171170
}
172171
if (query.type === 'template') {
173172
debug(`transform template (${id})`)
174-
return transformTemplateAsModule(code, id, options, query, this)
173+
return transformTemplateAsModule(code, options, query, this)
175174
} else if (query.type === 'style') {
176175
debug(`transform style (${id})`)
177-
return transformStyle(code, id, options, query, isProduction, this)
176+
return transformStyle(code, options, query, isProduction, this)
178177
}
179178
}
180179
return null

src/sfcFacade.ts

+53-10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { createRollupError } from './utils/error'
1414
import { resolveScript } from './script'
1515
import { transformTemplateInMain } from './template'
1616
import { isOnlyTemplateChanged } from './handleHotUpdate'
17+
import { RawSourceMap, SourceMapConsumer, SourceMapGenerator } from 'source-map'
1718

1819
export async function genSfcFacade(
1920
code: string,
@@ -30,7 +31,6 @@ export async function genSfcFacade(
3031
const { descriptor, errors } = parse(code, {
3132
sourceMap: true,
3233
filename,
33-
sourceRoot,
3434
})
3535
setDescriptor(filename, descriptor)
3636

@@ -68,9 +68,17 @@ export async function genSfcFacade(
6868
!(descriptor.template && descriptor.template.src)
6969
const hasTemplateImport = descriptor.template && !useInlineTemplate
7070

71-
const templateCode = hasTemplateImport
72-
? genTemplateCode(descriptor, scopeId, options, isServer, pluginContext)
73-
: ''
71+
let templateCode = ''
72+
let templateMap
73+
if (hasTemplateImport) {
74+
;({ code: templateCode, map: templateMap } = genTemplateCode(
75+
descriptor,
76+
scopeId,
77+
options,
78+
isServer,
79+
pluginContext
80+
))
81+
}
7482

7583
const renderReplace = hasTemplateImport
7684
? isServer
@@ -128,9 +136,34 @@ export async function genSfcFacade(
128136
)
129137
}
130138

139+
// if the template is inlined into the main module (indicated by the presence
140+
// of templateMap, we need to concatenate the two source maps.
141+
let resolvedMap = map
142+
if (map && templateMap) {
143+
const generator = SourceMapGenerator.fromSourceMap(
144+
new SourceMapConsumer(map)
145+
)
146+
const offset = scriptCode.match(/\r?\n/g)?.length || 1
147+
const templateMapConsumer = new SourceMapConsumer(templateMap)
148+
templateMapConsumer.eachMapping((m) => {
149+
generator.addMapping({
150+
source: m.source,
151+
original: { line: m.originalLine, column: m.originalColumn },
152+
generated: {
153+
line: m.generatedLine + offset,
154+
column: m.generatedColumn,
155+
},
156+
})
157+
})
158+
resolvedMap = (generator as any).toJSON()
159+
// if this is a template only update, we will be reusing a cached version
160+
// of the main module compile result, which has outdated sourcesContent.
161+
resolvedMap.sourcesContent = templateMap.sourcesContent
162+
}
163+
131164
return {
132165
code: output.join('\n'),
133-
map: map || {
166+
map: resolvedMap || {
134167
mappings: '',
135168
},
136169
}
@@ -146,6 +179,9 @@ function genTemplateCode(
146179
const renderFnName = isServer ? 'ssrRender' : 'render'
147180
const template = descriptor.template!
148181

182+
// If the template is not using pre-processor AND is not using external src,
183+
// compile and inline it directly in the main module. When served in vite this
184+
// saves an extra request per SFC which can improve load performance.
149185
if (!template.lang && !template.src) {
150186
return transformTemplateInMain(
151187
template.content,
@@ -160,9 +196,12 @@ function genTemplateCode(
160196
const srcQuery = template.src ? `&src` : ``
161197
const attrsQuery = attrsToQuery(template.attrs, 'js', true)
162198
const query = `?vue&type=template${idQuery}${srcQuery}${attrsQuery}`
163-
return `import { ${renderFnName} as _sfc_${renderFnName} } from ${JSON.stringify(
164-
src + query
165-
)}`
199+
return {
200+
code: `import { ${renderFnName} as _sfc_${renderFnName} } from ${JSON.stringify(
201+
src + query
202+
)}`,
203+
map: undefined,
204+
}
166205
}
167206
}
168207

@@ -173,7 +212,10 @@ async function genScriptCode(
173212
isServer: boolean,
174213
options: Options,
175214
pluginContext: TransformPluginContext
176-
) {
215+
): Promise<{
216+
code: string
217+
map: RawSourceMap
218+
}> {
177219
let scriptCode = `const _sfc_main = {}`
178220
let map
179221
const script = resolveScript(
@@ -185,7 +227,8 @@ async function genScriptCode(
185227
pluginContext
186228
)
187229
if (script) {
188-
// js or ts can be directly placed in the main module
230+
// If the script is js/ts and has no external src, it can be directly placed
231+
// in the main module.
189232
if (
190233
(!script.lang ||
191234
(script.lang === 'ts' && (pluginContext as any).server)) &&

src/style.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@ import { TransformPluginContext } from 'rollup'
66
import { Options } from '.'
77
import { getDescriptor } from './utils/descriptorCache'
88
import { StyleBlockQuery } from './utils/query'
9-
import { normalizeSourceMap } from './utils/sourceMap'
109

1110
export async function transformStyle(
1211
code: string,
13-
request: string,
1412
options: Options,
1513
query: StyleBlockQuery,
1614
isProduction: boolean,
@@ -85,7 +83,7 @@ export async function transformStyle(
8583
} else {
8684
return {
8785
code: result.code,
88-
map: normalizeSourceMap(result.map!, request),
86+
map: result.map as any,
8987
}
9088
}
9189
}

src/template.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ import { getResolvedScript } from './script'
99
import { getDescriptor } from './utils/descriptorCache'
1010
import { createRollupError } from './utils/error'
1111
import { TemplateBlockQuery } from './utils/query'
12-
import { normalizeSourceMap } from './utils/sourceMap'
1312

1413
export function transformTemplateAsModule(
1514
code: string,
16-
request: string,
1715
options: Options,
1816
query: TemplateBlockQuery,
1917
pluginContext: TransformPluginContext
@@ -37,7 +35,7 @@ export function transformTemplateAsModule(
3735

3836
return {
3937
code: returnCode,
40-
map: normalizeSourceMap(result.map!, request),
38+
map: result.map as any,
4139
}
4240
}
4341

@@ -52,11 +50,13 @@ export function transformTemplateInMain(
5250
pluginContext: PluginContext
5351
) {
5452
const result = compileTemplate(code, descriptor, id, options, pluginContext)
55-
// TODO figure out how to merge the source map with the script map
56-
return result.code.replace(
57-
/\nexport (function|const) (render|ssrRender)/,
58-
'\n$1 _sfc_$2'
59-
)
53+
return {
54+
...result,
55+
code: result.code.replace(
56+
/\nexport (function|const) (render|ssrRender)/,
57+
'\n$1 _sfc_$2'
58+
),
59+
}
6060
}
6161

6262
export function compileTemplate(
@@ -67,8 +67,9 @@ export function compileTemplate(
6767
pluginContext: PluginContext
6868
) {
6969
const filename = descriptor.filename
70+
const compileOptions = getTemplateCompilerOptions(options, descriptor, id)
7071
const result = compile({
71-
...getTemplateCompilerOptions(options, descriptor, id),
72+
...compileOptions,
7273
id,
7374
source: code,
7475
filename,

0 commit comments

Comments
 (0)