Skip to content

Commit fb6ff3e

Browse files
committedJan 20, 2023
fix(build): ensure cjs re-exports can be properly detected when imported from esm
1 parent bef85e7 commit fb6ff3e

File tree

3 files changed

+83
-36
lines changed

3 files changed

+83
-36
lines changed
 

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
"prettier": "^2.7.1",
9090
"pug": "^3.0.1",
9191
"puppeteer": "^19.2.2",
92-
"rollup": "~3.2.3",
92+
"rollup": "~3.10.0",
9393
"rollup-plugin-node-builtins": "^2.1.2",
9494
"rollup-plugin-node-globals": "^1.4.0",
9595
"rollup-plugin-polyfill-node": "^0.11.0",

‎pnpm-lock.yaml

+35-35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎rollup.config.mjs

+47
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ function createConfig(format, output, plugins = []) {
195195
]
196196
: []
197197

198+
if (format === 'cjs') {
199+
nodePlugins.push(cjsReExportsPatchPlugin())
200+
}
201+
198202
return {
199203
input: resolve(entryFile),
200204
// Global and Browser ESM builds inlines everything so that they can be
@@ -329,3 +333,46 @@ function createMinifiedConfig(format) {
329333
]
330334
)
331335
}
336+
337+
// temporary patch for https://github.com/nodejs/cjs-module-lexer/issues/79
338+
//
339+
// When importing a cjs module from esm, Node.js uses cjs-module-lexer to
340+
// detect * re-exports from other packages. However, the detection logic is
341+
// fragile and breaks when Rollup generates different code for the re-exports.
342+
// We were locked on an old version of Rollup because of this.
343+
//
344+
// The latest versions of Node ships an updated version of cjs-module-lexer that
345+
// has fixed https://github.com/nodejs/cjs-module-lexer/issues/38, however we
346+
// still need to support older versions of Node that does not have the latest
347+
// version of cjs-module-lexer (Node < 14.18)
348+
//
349+
// At the same time, we want to upgrade to Rollup 3 so we are not forever locked
350+
// on an old version of Rollup.
351+
//
352+
// What this patch does:
353+
// 1. Rewrite the for...in loop to Object.keys() so cjs-module-lexer can find it
354+
// The for...in loop is only used when output.externalLiveBindings is set to
355+
// false, and we do want to set it to false to avoid perf costs during SSR.
356+
// 2. Also remove exports.hasOwnProperty check, which breaks the detection in
357+
// Node.js versions that
358+
//
359+
// TODO in the future, we should no longer rely on this if we inline all deps
360+
// in the main `vue` package.
361+
function cjsReExportsPatchPlugin() {
362+
const matcher =
363+
/for \(var k in (\w+)\) {(\s+if \(k !== 'default') && !exports.hasOwnProperty\(k\)(\) exports\[k\] = (?:\w+)\[k\];\s+)}/
364+
return {
365+
name: 'patch-cjs-re-exports',
366+
renderChunk(code, _, options) {
367+
if (matcher.test(code)) {
368+
return code.replace(matcher, (_, r1, r2, r3) => {
369+
return `Object.keys(${r1}).forEach(function(k) {${r2}${r3}});`
370+
})
371+
} else if (options.file.endsWith('/vue.cjs.js')) {
372+
// make sure we don't accidentally miss the rewrite in case Rollup
373+
// changes the output again.
374+
throw new Error('cjs build re-exports rewrite failed.')
375+
}
376+
}
377+
}
378+
}

0 commit comments

Comments
 (0)
Please sign in to comment.