-
Notifications
You must be signed in to change notification settings - Fork 3
Skip transpilation of CommonJS modules #8
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) { | |
|
|
||
| export async function load(url, context, defaultLoad) { | ||
| if (useLoader(url)) { | ||
| const { source } = await defaultLoad(url, context, defaultLoad); | ||
| const { source, format } = await defaultLoad(url, context, defaultLoad); | ||
|
|
||
| // Skip transpilation of CommonJS modules. | ||
| // These modules are already preprocessed by Node.js, | ||
| // so we cannot parse the non-standard syntaxes like JSX and TypeScript. | ||
| // Their transpilation is better handled separately by @babel/register or @babel/node. | ||
| if (format !== "module") { | ||
| return { source, format }; | ||
| } | ||
|
|
||
| const filename = urlModule.fileURLToPath(url); | ||
| // Babel config files can themselves be ES modules, | ||
| // but we cannot transform those since doing so would cause an infinite loop. | ||
| if (isBabelConfigFile(filename)) { | ||
| return { | ||
| source, | ||
| format: /\.(c|m)?js$/.test(filename) ? "module" : "json", | ||
| format, | ||
| }; | ||
| } | ||
|
|
||
|
|
@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) { | |
|
|
||
| return { | ||
| source: transformed.code, | ||
| // Maybe a shaky assumption | ||
| // TODO: look at babel config to see whether it will output ESM/CJS or other formats | ||
| format: "module", | ||
| // NOTE: transform-modules-commonjs doesn't work properly. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Which bug in transform-modules-commonjs you're referring to? I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config. |
||
| // We put a branch here just for consistency. | ||
| format: transformed.sourceType === "module" ? "module" : "commonjs", | ||
|
Comment on lines
+54
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I do not know, I am just confused as to whether |
||
| }; | ||
| } else { | ||
| return defaultLoad(url, context, defaultLoad); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => { | |
| }); | ||
| }); | ||
|
|
||
| it(`allows loading CJS modules`, async () => { | ||
| const example = await import("./fixtures/basic/cjs.cjs"); | ||
| assert.deepEqual(example.default, { | ||
| cjs: "cjs", | ||
| }); | ||
| }); | ||
|
Comment on lines
+13
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is neat! |
||
|
|
||
| it(`supports ES module babel config files`, async () => { | ||
| const mjsConfig = await import("./fixtures/mjs-config/main.js"); | ||
| assert.deepEqual(mjsConfig.default, { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| exports.cjs = "cjs"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am nitpicking here but other formats include
builtin,json, andwasm(see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.
As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking forward what you say makes sense. It may be that one day node loader handles the
sourcekey for{format: 'commonjs'}. But insisting oncommonjsbeing transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will haveconst {format, source} = await defaultLoad(...);such thatformat = 'commonjs'andsource = null. Babel gracefully handlesnullby producingnullwith little overhead. If one daysourceis non-null and has meaning forformat = 'commonjs'suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".I agree this behavior could be configurable by the user of
node-loader-babel. I just think the default should be to only process'module'input.Note that without this PR, when input format is
commonjs, input and output source arenulland output format ismodulewhich is the reason of the bug described in #7.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this REPL, enabling
@babel/preset-envdoes transform ESM input into CJS output. How do you configure it so that it does not change format?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set babel preset env's
modulesoption tofalse. The"auto"value also should work if we have called babel with the proper optionshttps://babeljs.io/docs/en/babel-preset-env#modules
I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.
Why would
sourcebenull? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. I cannot find how to do this in the REPL, maybe it is not possible.