Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpack5: Make export-order-loader compatible with both esm and cjs #25540

Merged
merged 3 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/builders/builder-webpack5/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"@types/semver": "^7.3.4",
"browser-assert": "^1.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"cjs-module-lexer": "^1.2.3",
"constants-browserify": "^1.0.0",
"css-loader": "^6.7.1",
"es-module-lexer": "^1.4.1",
Expand Down
66 changes: 45 additions & 21 deletions code/builders/builder-webpack5/src/loaders/export-order-loader.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,58 @@
import { parse } from 'es-module-lexer';
import assert from 'assert';
import { parse as parseCjs, init as initCjsParser } from 'cjs-module-lexer';
import { parse as parseEs } from 'es-module-lexer';
import MagicString from 'magic-string';
import type { LoaderContext } from 'webpack';

export default async function loader(this: LoaderContext<any>, source: string) {
export default async function loader(
this: LoaderContext<any>,
source: string,
map: any,
meta: any
) {
const callback = this.async();

try {
// Do NOT remove await here. The types are wrong! It has to be awaited,
// otherwise it will return a Promise<Promise<...>> when wasm isn't loaded.
const [, exports = []] = await parse(source);
const magicString = new MagicString(source);

// Trying to parse as ES module
try {
// Do NOT remove await here. The types are wrong! It has to be awaited,
// otherwise it will return a Promise<Promise<...>> when wasm isn't loaded.
const parseResult = await parseEs(source);
const namedExportsOrder = (parseResult[1] || [])
.map((e) => source.substring(e.s, e.e))
.filter((e) => e !== 'default');

assert(
namedExportsOrder.length > 0,
'No named exports found. Very likely that this is not a ES module.'
);

const namedExportsOrder = exports.some(
(e) => source.substring(e.s, e.e) === '__namedExportsOrder'
);
magicString.append(
`;export const __namedExportsOrder = ${JSON.stringify(namedExportsOrder)};`
);
// Try to parse as CJS module
} catch {
await initCjsParser();
const namedExportsOrder = (parseCjs(source).exports || []).filter(
(e: string) => e !== 'default' && e !== '__esModule'
);

if (namedExportsOrder) {
return callback(null, source);
assert(
namedExportsOrder.length > 0,
'No named exports found. Very likely that this is not a CJS module.'
);

magicString.append(
`;module.exports.__namedExportsOrder = ${JSON.stringify(namedExportsOrder)};`
);
}

const magicString = new MagicString(source);
const orderedExports = exports.filter((e) => source.substring(e.s, e.e) !== 'default');
magicString.append(
`;export const __namedExportsOrder = ${JSON.stringify(
orderedExports.map((e) => source.substring(e.s, e.e))
)};`
);

const map = magicString.generateMap({ hires: true });
return callback(null, magicString.toString(), map);
const generatedMap = magicString.generateMap({ hires: true });

return callback(null, magicString.toString(), generatedMap, meta);
} catch (err) {
return callback(err as any);
return callback(null, source, map, meta);
}
}
8 changes: 8 additions & 0 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5228,6 +5228,7 @@ __metadata:
"@types/webpack-virtual-modules": "npm:^0.1.1"
browser-assert: "npm:^1.2.1"
case-sensitive-paths-webpack-plugin: "npm:^2.4.0"
cjs-module-lexer: "npm:^1.2.3"
constants-browserify: "npm:^1.0.0"
css-loader: "npm:^6.7.1"
es-module-lexer: "npm:^1.4.1"
Expand Down Expand Up @@ -11217,6 +11218,13 @@ __metadata:
languageName: node
linkType: hard

"cjs-module-lexer@npm:^1.2.3":
version: 1.2.3
resolution: "cjs-module-lexer@npm:1.2.3"
checksum: 0de9a9c3fad03a46804c0d38e7b712fb282584a9c7ef1ed44cae22fb71d9bb600309d66a9711ac36a596fd03422f5bb03e021e8f369c12a39fa1786ae531baab
languageName: node
linkType: hard

"class-utils@npm:^0.3.5":
version: 0.3.6
resolution: "class-utils@npm:0.3.6"
Expand Down