tbranyen / babel-plugin-transform-commonjs Goto Github PK
View Code? Open in Web Editor NEWA Babel 7 plugin transform to convert CommonJS into ES Modules
A Babel 7 plugin transform to convert CommonJS into ES Modules
Thank you for creating this transform. It's helpful on a project where we're using Relay Modern (11). Relay generates TypeScript modules that for some reason occasionally include require
statements. We're using this transform to make these modules pure ES6 modules.
In our case, we're finding the export feature to be unhelpful because it creates multiple default exports. We get something that looks like this,
export default node;
export default module.exports;
export default module.exports
is added by this transform but unnecessary.
It would be very helpful if it was possible to only change the import statements but not add the exports.
Modules like React DOM have conditional exports based on if
statements in the source. This is similar, but distinct from how React loads itself.
We need to support:
if (hasNativePerformanceNow) {
var Performance = performance;
exports.unstable_now = function () {
return Performance.now();
};
} else {
exports.unstable_now = function () {
return localDate.now();
};
}
We can do this by making the binding mutable with export let
and then reassigning the export inside the source.
export let unstable_now = null;
if (hasNativePerformanceNow) {
var Performance = performance;
unstable_now = function () {
return Performance.now();
};
} else {
unstable_now = function () {
return localDate.now();
};
}
Some modules wrap their CJS with an IIFE and this module currently rewrites exports within them, which is invalid.
(() => {
export let UAParser = exports.UAParser;
}).call(module.exports);
export default module.exports;
IN example:
module.exports = require('./lib/index.js');
OUT actual:
import _libIndexJs from "./lib/index.js";
var module = {
exports: {}
};
var exports = module.exports;
module.exports = _libIndexJs;
export default module.exports;
OUT expected:
export * from "./lib/index.js";
Source Code: https://unpkg.com/[email protected]/index.js
import { graphql } from 'react-relay'
// Uncaught SyntaxError: The requested module 'node_modules/react-relay/index.js' does not provide an export named 'graphql'
IIFE transformed modules are incompatible with babel plugins which transform es modules.
Sort of a mouthful but I'll try to explain what's happening below.
Consider this CJS module
this.name = 'true';
Running this through transform-commonjs
wraps it in a IIFE to preserve the this
module context.
var module = {
exports: {}
};
var exports = module.exports;
(function () {
this.name = 'true';
}).call(module.exports);
export default module.exports;
If we use another ESM babel transform (such as transform-modules-systemjs
) it causes nested duplication of code
System.register([], function (_export2, _context) {
"use strict";
return {
setters: [],
execute: function () {
System.register([], function (_export, _context) {
"use strict";
var module, exports;
return {
setters: [],
execute: function () {
module = {
exports: {}
};
exports = module.exports;
(function () {
this.name = 'true';
}).call(module.exports);
_export("default", module.exports);
}
};
});
}
};
});
The issue seems to be coming from this line in the ThisExpression
branch:
I'm not too familiar with babel's helper functions. What's your thoughts on this? Is there another method which will prevent duplication of the program?
https://github.com/tc39/proposal-top-level-await
Once if babel implements this proposal. This plugin can replace require
to await import
to support require non-string-literal module ids?
Some modules do early return when working with something like the cluster module. Since ES Modules do not have a wrapping function scope, this is an invalid transformation. We should search for all top-level returns and either remove everything in the body past them or wrap with an else block.
const { isMaster, fork } = require('cluster');
if (isMaster) {
fork();
return;
}
console.log('forked', process.pid);
Should be converted into:
import { isMaster, fork } from 'cluster';
if (isMaster) {
fork();
}
else {
console.log('forked', process.pid);
}
Can anyone think of a better way of handling this?
I have exports.super
and it's converting to export let super
which doesn't compile. Example here.
Any chance that rather then declaring each variable there can be one export?
export {
super: 'something'
}
Also I would love the ability to ignore throwing this error and keeping in those requires I can do something with them with another plugin after. This isn't a big deal as I can patch-package to stop it from throwing.
throw new Error(`Invalid require signature: ${path.toString()}`);
Hey man, thanks for this plugin
Is there a way to emit export statements only when necessary? My use case: I have a babel transform that returns the last expression which breaks because of the export statements that are always inserted by this plugin
I'm writing a web application that is using ES modules. I use fastify-babel in my development server to perform live translations on sources, for example converting bare imports to fully resolved URL's. I've added this babel plugin to translate https://github.com/sindresorhus/camelcase into ES modules. Unfortunately this plugin modifies files that are already ES modules. As a work-around I'm using the following babel options in my development server:
const babelrc = {
babelrc: false,
configFile: false,
plugins: [
['bare-import-rewrite', {
alwaysRootImport: ['**'],
modulesDir: '/assets'
}],
'@babel/plugin-proposal-object-rest-spread'
],
overrides: [{
test: [path.resolve(__dirname, '../node_modules/camelcase/**')],
plugins: ['transform-commonjs']
}]
};
It would be very awesome if I could just put transform-commonjs
in the general plugins list instead of having to use overrides to restrict it to only CJS.
Thanks for this plugin, before I found this I had just created camelcase.js in my local folder with manual edits to make it ESM. Much better to just npm install camelcase
and have your plugin translate.
exports.colors = [ 6, 2, 3, 4, 5, 1 ];
try {
var supportsColor = require('supports-color');
if (supportsColor && supportsColor.level >= 2) {
exports.colors = [
20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68,
69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134,
135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 214, 215, 220, 221
];
}
} catch (err) {
// swallow - we only care if `supports-color` is available; it doesn't have to be.
}
TypeError: /home/tbranyen/tmp/tmp.mfYL7iA5gV/node_modules/debug/src/node.js: Duplicate declaration "colors"
29 | var supportsColor = require('supports-color');
30 | if (supportsColor && supportsColor.level >= 2) {
> 31 | exports.colors = [
Would you mind adding git tags for the commits associated with releases?
When a module has export.default =
, this transform creates a variable called default
. This is invalid because default
is a reserved word.
Runtime Error: Uncaught SyntaxError: Unexpected token 'default'
test
const hello = 'hello'
exports.default = hello
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.