Have @babel/core lazy-load all dependencies and make @babel/register not explode because of that#7588
Conversation
6ff42db to
52dac67
Compare
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/7384/ |
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/7328/ |
| } | ||
|
|
||
| // Ensure that require.resolve and other properties are carried over. | ||
| return Object.assign(babelRegisterRequire, req); |
| __filename, | ||
| )}).wrap(require, __filename, ${uid}, ${inRoot})`; | ||
|
|
||
| return `return (function(require){${code}\n}).call(this, ${override});`; |
There was a problem hiding this comment.
Yeah for some reason I was thinking it was needed, but it isn't is it.
There was a problem hiding this comment.
wonder how this affects the error messages (although that might just be messed up already)
There was a problem hiding this comment.
They'll be an extra scope in the debugger if you pause, but otherwise I don't think it will affect anything.
| inRoot: boolean, | ||
| ) => { exports: mixed } | void, | ||
| ) { | ||
| const files = new Set(); |
There was a problem hiding this comment.
The set seems to be write-only?
There was a problem hiding this comment.
It ends up exported and used in /node.js to skip them.
|
Were you able to test this? should probably run locally before next release then like #6134. For compiling with lazy and also new register although I guess this is a fix for the previous time we tried this. |
|
The tests for The main question for me right now, which I'm going back and forth on, is whether we care about the case of re-entrant configs. And if we do (which I think I do?), should it be something we require users to opt into? For instance right now people often do I think I'm personally leaning toward us making that behavior opt-in instead. We'd then instead require users to do if they wanted It'd be a lot safer for the average user since we get issues like #7208 reasonably often. Doing that would still require the logic in this PR, but I'd remove the |
|
Ok, just needs docs on that and maybe think if that's the best word for it. I guess not sure what else it would be called but the intention is to compile configs themselves with register which affect itself? Or could we error with a nicer message when it happens without? |
I don't follow. If we error without the flag on you mean? Without the flag I don't think I'd expect it to error, and with the flag we already give some errors about reentrant code. |
|
just wondering how someone would know to use the flag, if it's clear then never mind |
|
I think what I might do is tweak this PR to disallow reentrant plugins/presets entirely for now, and land that, and then do a second PR to add the |
Gotcha, yeah it's not super clear, but then I don't think it'll be super common anyway. It's not something that'll work with any of the other Babel integrations anyway since they don't do require hooks, so I think making it a special opt-in feature of babel-register seems fine. We'll definitely have to document it clearly though. |
52dac67 to
a5df709
Compare
|
Alright I decided to remove most of the complex logic that I had originally here for |
|
@loganfsmyth; note in the README? Not sure where you're referring to or if this is relevant to the issue I'm having anyway (#7208), but if you could point me towards that note I'd appreciate it. Thanks for all your hard work! |
There is some serious craziness in here for
@babel/registersooooo sorry 😬 Essentially we want to be able to loadbabel/corewith lazy requires safely in@babel/register, and that's dangerous/broken if register were left as-is because callingbabel.transformcould then actually trigger the require hook again causing a cycle.Triggering a cycle isn't guaranteed to be an issue, since you could imagine a world where someone does:
to compile a project with some custom plugin, while also compiling that plugin itself with a different config.
To achieve all that while still having
@babel/corekick offrequirecalls at random times during transformation, this PR makes@babel/registermuch smarter about how it loads@babel/core. You can almost think of it like it loads it with its own loader context that explicitly tracks while files it has loaded. By tracking all that, we can explicitly skip those files in the require hook, avoiding trying to compile files that are necessary for the compilation itself.There is then a small hole exposed in that loader logic so that when
@babel/coreloads.babelrc.jss, plugins, and presets, it will not track those, so that they actually do get passed to the require hook. This means it is up to the user to ensure that their Babel config does not introduce dependencies. We also have existing logic in@babel/coreto show helpful error messages when there are cycles detected in config files/plugins/presets.The end result of this PR is that
@babel/corecan lazy-load everything and all the rest of babel-register pretty much ends up behaving like it did before.Why!
The end goal of this PR is the lazy-loading. With PR's like #7472 encouraging tooling to load
@babel/coreto check for config, this means we need to make loading core as fast as possible. Currently, it is the exact opposite of that. A single call torequire("@babel/core")on my machine for instance takes~250-350ms. With this PR, it now takes~25-30mson my machine.This brings down the total time for a call to
require("@babel/core").loadPartialConfig()dramatically, which should make it easier for people to adopt over trying to implement the logic themselves.