Skip to content

Commit

Permalink
fix(build): ensure cjs re-exports can be properly detected when impor…
Browse files Browse the repository at this point in the history
…ted from esm
  • Loading branch information
yyx990803 committed Jan 20, 2023
1 parent bef85e7 commit fb6ff3e
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -89,7 +89,7 @@
"prettier": "^2.7.1",
"pug": "^3.0.1",
"puppeteer": "^19.2.2",
"rollup": "~3.2.3",
"rollup": "~3.10.0",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-polyfill-node": "^0.11.0",
Expand Down
70 changes: 35 additions & 35 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions rollup.config.mjs
Expand Up @@ -195,6 +195,10 @@ function createConfig(format, output, plugins = []) {
]
: []

if (format === 'cjs') {
nodePlugins.push(cjsReExportsPatchPlugin())
}

return {
input: resolve(entryFile),
// Global and Browser ESM builds inlines everything so that they can be
Expand Down Expand Up @@ -329,3 +333,46 @@ function createMinifiedConfig(format) {
]
)
}

// temporary patch for https://github.com/nodejs/cjs-module-lexer/issues/79
//
// When importing a cjs module from esm, Node.js uses cjs-module-lexer to
// detect * re-exports from other packages. However, the detection logic is
// fragile and breaks when Rollup generates different code for the re-exports.
// We were locked on an old version of Rollup because of this.
//
// The latest versions of Node ships an updated version of cjs-module-lexer that
// has fixed https://github.com/nodejs/cjs-module-lexer/issues/38, however we
// still need to support older versions of Node that does not have the latest
// version of cjs-module-lexer (Node < 14.18)
//
// At the same time, we want to upgrade to Rollup 3 so we are not forever locked
// on an old version of Rollup.
//
// What this patch does:
// 1. Rewrite the for...in loop to Object.keys() so cjs-module-lexer can find it
// The for...in loop is only used when output.externalLiveBindings is set to
// false, and we do want to set it to false to avoid perf costs during SSR.
// 2. Also remove exports.hasOwnProperty check, which breaks the detection in
// Node.js versions that
//
// TODO in the future, we should no longer rely on this if we inline all deps
// in the main `vue` package.
function cjsReExportsPatchPlugin() {
const matcher =
/for \(var k in (\w+)\) {(\s+if \(k !== 'default') && !exports.hasOwnProperty\(k\)(\) exports\[k\] = (?:\w+)\[k\];\s+)}/
return {
name: 'patch-cjs-re-exports',
renderChunk(code, _, options) {
if (matcher.test(code)) {
return code.replace(matcher, (_, r1, r2, r3) => {
return `Object.keys(${r1}).forEach(function(k) {${r2}${r3}});`
})
} else if (options.file.endsWith('/vue.cjs.js')) {
// make sure we don't accidentally miss the rewrite in case Rollup
// changes the output again.
throw new Error('cjs build re-exports rewrite failed.')
}
}
}
}

0 comments on commit fb6ff3e

Please sign in to comment.