[Fresh] Initial Babel plugin implementation#15711
Conversation
Always declare them at the bottom and rely on hoisting.
|
I initially thought component IDs would include the file name (e.g. Instead I think the filename should be handled at the module runtime level. Whether we're in Metro/Webpack/something else, we should be able to know the module ID of currently initializing module inside the integration glue code. This is guaranteed to be correct because it's what the bundler actually uses. We'll also need this module ID anyway for preserving context identity. So this doesn't even add a new requirement. Filenames are also problematic because they would mess up centralized development JS code caching if absolute. So it seems like Babel plugin shouldn't try to put the filenames into the output. One caveat is that a bundler may unify several previously distinct modules into one. Like if you enable Rollup-like optimizations in development. In that case we'd need to know filenames or module IDs at the Babel call time. However it's probably a bad idea for a development / hot reloaded setup anyway (e.g. Rollup doesn't support it — rollup/rollup#50). So I don't think we need to handle this until somebody actually asks for it. |
I've decided for now that the plugin doesn't need filename, and it will be handled by module runtime integration instead.
Is it important that the (Still reviewing... just an initial question.) |
|
Not strictly necessary. But since at least some need to be at the bottom (the ones in expressions like Edit: to be clear, for |
bvaughn
left a comment
There was a problem hiding this comment.
Kind of just skimmed the Babel plug-in (since I don't write or look at these often) but I read the tests and snapshots more closely and they look good 👍
|
|
||
| var _c3; | ||
|
|
||
| __register__(_c, 'Hello'); |
There was a problem hiding this comment.
Wonder why it sometimes uses single quotes and other times uses double quotes with escape slashes...
| }).code; | ||
| } | ||
|
|
||
| describe('ReactFreshBabelPlugin', () => { |
| `); | ||
|
|
||
| function isComponentishName(name) { | ||
| return typeof name === 'string' && name[0] >= 'A' && name[0] <= 'Z'; |
|
Pushed a few bugfixes. I coalesced all variable definitions into one so that it doesn't take as many lines. Also checked that our own test suite works with the plugin enabled. |
Gotcha! That's what I assumed. I was just curious. 😄Thanks for confirming.
Sounds like a nice tweak. |
* Add initial Babel plugin implementation * Register exported functions * Fix missing declarations Always declare them at the bottom and rely on hoisting. * Remove unused code * Don't pass filename to tests I've decided for now that the plugin doesn't need filename, and it will be handled by module runtime integration instead. * Fix bugs * Coalesce variable declarations
* Add initial Babel plugin implementation * Register exported functions * Fix missing declarations Always declare them at the bottom and rely on hoisting. * Remove unused code * Don't pass filename to tests I've decided for now that the plugin doesn't need filename, and it will be handled by module runtime integration instead. * Fix bugs * Coalesce variable declarations
This adds a basic implementation of the Babel plugin. It's incomplete and will be expanded as we go.
Its takes code like
and turns it into something like
We rely on var and function declaration hoisting here. The registration all happens at the bottom so that if module init throws, we throw away the broken components.
The transform handles some basic cases like top-level functions and arrows (normal or exported). In the future I'll add support for some HOC patterns like
memo. The transform intentionally injects variable in the middle of assignment so that in theory we could even do things like_c3 = forwardRef(_c2 = memo(_c1 = function() { }))without changing code semantics.In the follow-ups, I'll handle more cases and tie this with our integration tests so we can verify the whole thing works as expected.