Merge pull request #7588 from loganfsmyth/register-cycle-fixes
Have @babel/core lazy-load all dependencies and make @babel/register not explode because of that
This commit is contained in:
commit
a10c91790f
13
.babelrc.js
13
.babelrc.js
@ -46,7 +46,9 @@ module.exports = function(api) {
|
|||||||
"@babel/proposal-export-namespace-from",
|
"@babel/proposal-export-namespace-from",
|
||||||
"@babel/proposal-numeric-separator",
|
"@babel/proposal-numeric-separator",
|
||||||
["@babel/proposal-object-rest-spread", { useBuiltIns: true }],
|
["@babel/proposal-object-rest-spread", { useBuiltIns: true }],
|
||||||
convertESM ? "@babel/transform-modules-commonjs" : null,
|
|
||||||
|
// Explicitly use the lazy version of CommonJS modules.
|
||||||
|
convertESM ? ["@babel/transform-modules-commonjs", { lazy: true }] : null,
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
@ -56,6 +58,15 @@ module.exports = function(api) {
|
|||||||
["@babel/transform-for-of", { assumeArray: true }],
|
["@babel/transform-for-of", { assumeArray: true }],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: "./packages/babel-register",
|
||||||
|
plugins: [
|
||||||
|
// Override the root options to disable lazy imports for babel-register
|
||||||
|
// because otherwise the require hook will try to lazy-import things
|
||||||
|
// leading to dependency cycles.
|
||||||
|
convertESM ? "@babel/transform-modules-commonjs" : null,
|
||||||
|
].filter(Boolean),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -64,7 +64,7 @@ const assertTest = function(stdout, stderr, opts) {
|
|||||||
chai.expect(stderr).to.equal(expectStderr, "stderr didn't match");
|
chai.expect(stderr).to.equal(expectStderr, "stderr didn't match");
|
||||||
}
|
}
|
||||||
} else if (stderr) {
|
} else if (stderr) {
|
||||||
throw new Error("stderr:\n" + stderr);
|
throw new Error("stderr:\n" + stderr + "\n\nstdout:\n" + stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
const expectStdout = opts.stdout.trim();
|
const expectStdout = opts.stdout.trim();
|
||||||
|
|||||||
@ -100,3 +100,34 @@ Disable the cache.
|
|||||||
```sh
|
```sh
|
||||||
BABEL_DISABLE_CACHE=1 babel-node script.js
|
BABEL_DISABLE_CACHE=1 babel-node script.js
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Compiling plugins and presets on the fly
|
||||||
|
|
||||||
|
`@babel/register` uses Node's `require()` hook system to compile files
|
||||||
|
on the fly when they are loaded. While this is quite helpful overall, it means
|
||||||
|
that there can be confusing cases where code within a `require()` hook causes
|
||||||
|
_more_ calls to `require`, causing a dependency cycle. In Babel's case for
|
||||||
|
instance, this could mean that in the process of Babel trying to compile a
|
||||||
|
user's file, Babel could end up trying to compile itself _as it is loading_.
|
||||||
|
|
||||||
|
To avoid this problem, this module explicitly disallows re-entrant compilation,
|
||||||
|
e.g. Babel's own compilation logic explicitly cannot trigger further compilation
|
||||||
|
of any other files on the fly. The downside of this is that if you want to
|
||||||
|
define a plugin or preset that is itself live-compiled, the process is
|
||||||
|
complicated.
|
||||||
|
|
||||||
|
The crux of it is that your own code needs to load the plugin/preset first.
|
||||||
|
Assuming the plugin/preset loads all of its dependencies up front, what you'll
|
||||||
|
want to do is:
|
||||||
|
|
||||||
|
```
|
||||||
|
require("@babel/register")({
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
|
||||||
|
require("./my-plugin");
|
||||||
|
```
|
||||||
|
|
||||||
|
Because it is your own code that triggered the load, and not the logic within
|
||||||
|
`@babel/register` itself, this should successfully compile any plugin/preset
|
||||||
|
that that loads synchronously.
|
||||||
|
|||||||
@ -55,37 +55,47 @@ function compile(code, filename) {
|
|||||||
|
|
||||||
if (env) cacheKey += `:${env}`;
|
if (env) cacheKey += `:${env}`;
|
||||||
|
|
||||||
if (cache) {
|
let cached = cache && cache[cacheKey];
|
||||||
const cached = cache[cacheKey];
|
|
||||||
if (cached && cached.mtime === mtime(filename)) {
|
if (!cached || cached.mtime !== mtime(filename)) {
|
||||||
return cached.code;
|
cached = babel.transform(code, {
|
||||||
|
...opts,
|
||||||
|
sourceMaps: opts.sourceMaps === undefined ? "both" : opts.sourceMaps,
|
||||||
|
ast: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cache) {
|
||||||
|
cache[cacheKey] = cached;
|
||||||
|
cached.mtime = mtime(filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = babel.transform(code, {
|
if (cached.map) {
|
||||||
...opts,
|
|
||||||
sourceMaps: opts.sourceMaps === undefined ? "both" : opts.sourceMaps,
|
|
||||||
ast: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cache) {
|
|
||||||
cache[cacheKey] = result;
|
|
||||||
result.mtime = mtime(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.map) {
|
|
||||||
if (Object.keys(maps).length === 0) {
|
if (Object.keys(maps).length === 0) {
|
||||||
installSourceMapSupport();
|
installSourceMapSupport();
|
||||||
}
|
}
|
||||||
maps[filename] = result.map;
|
maps[filename] = cached.map;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.code;
|
return cached.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
let compiling = false;
|
||||||
|
|
||||||
|
function compileHook(code, filename) {
|
||||||
|
if (compiling) return code;
|
||||||
|
|
||||||
|
try {
|
||||||
|
compiling = true;
|
||||||
|
return compile(code, filename);
|
||||||
|
} finally {
|
||||||
|
compiling = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hookExtensions(exts) {
|
function hookExtensions(exts) {
|
||||||
if (piratesRevert) piratesRevert();
|
if (piratesRevert) piratesRevert();
|
||||||
piratesRevert = addHook(compile, { exts, ignoreNodeModules: false });
|
piratesRevert = addHook(compileHook, { exts, ignoreNodeModules: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function revert() {
|
export function revert() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user