You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Objective: Determine the feasibility and implications of replacing the default Babel builder with SWC in Webpack5-based projects, especially in the context of the Storybook.
1. Investigate hurdles to remove the babel-loader and replace it with swc-loader
Results:
babel-plugin-react-docgen
In Storybook 8.0, we want to use react-docgen as the default tool to extract type information for the controls panel. Currently, it is operated via a babel plugin called babel-plugin-react-docgen.
Task: Replace the babel plugin by an appropriate webpack-loader, which calls react-docgen. Similar was done for the vite-builder.
storybookjs/babel-plugin-named-exports-order
This plugin is necessary to persist the correct export order of Stories, since webpack and vite sometimes doesn't preserve the original order.
Task: This plugin has to be rewritten as a webpack-loader. Similar was done for the vite builder.
SWC does not have flow support. People would have to opt-out from swc and use babel instead, if they would like to continue to use flow.
2. List all frameworks which are not able to use SWC or in a limited way
Frameworks
Angular
Switching to SWC does not make much sense since Angular plans to continue with esbuild instead of SWC as a compiler. The Angular esbuild builder is still experimental though and we don't know yet how to easily integrate it. We are collaborating with the Angular team to achieve some esbuild support sooner or later. For now, we cannot ditch babel support since SWC still needs to support Angular.
Next.js
We have some custom babel plugins in place, which are necessary for Next.js. We cannot rewrite them to SWC plugins, since the Node binding of SWC doesn't have a Javascript Plugin API. Plugins have to be translated into Rust and then compiled together with SWC, which then could be used via WASM in Node.js. An alternative would be to try out whether we could use the Next.js' custom Rust compiler, which builds on top of SWC or to use Next.js' next-custom-loader, which configures swc under the hood. I have tried out this approach. The main issue is, that, for example, the font webpack plugins have to be rewritten since Next.js' implementation of how fonts are loaded differs from the current implementation in Storybook with Babel. I can't say how complex and long it takes to fully support SWC.
[UPDATE] Next.js findings
After some experimentation, it was possible to use Next.js' next-swc-loader in @storybook/nextjs. This also made it possible to support @next/font without the need of creating custom Babel files like it is needed in Storybook 7.
It can be experimented with the following canary version: 0.0.0-pr-24504-sha-5d9e47a4.
Unfortunately, because next-swc-loader uses internal profiling utilities which are not available in Storybook's implementation, we needed to create a local patch of the next-swc-loader to remove the profiling, and thus make the loader work correctly. Some small changes are needed to support both Babel and SWC, but it's very feasible.
Ember
Ember sets up some babel plugins: (babel-plugin-ember-modules-api-polyfill and babel-plugin-htmlbars-inline-precompile). Not sure, whether it works with SWC out of the box.
Preact
Preact has a plugin to support fast refresh. Hooks, though, require a special babel plugin. This isn't available for SWC. Therefore, full support for fast refresh is not possible.
What are the implications of relying on SWC and removing Babel from Storybook 8?
Babel is still pretty much relevant (over 44 million weekly downloads on npm). Once Babel 8 is released, if there are substantial changes or anything breaks in Storybook projects, we will not detect this and thus will rely on users to report back. We will have to act upon providing fixes, or just delegate this to users, but this will likely result in frustration.
Users will have to set up Babel themselves in their project. Maybe this can be automated via automigration or codemod, but only to an extend, as user's projects can vary in complexity.
Storybook 7 relies on certain babel configuration such as babel-plugin-named-exports-order and caching setup. In Storybook 8, assuming all the Babel configs are removed, users who migrate from Storybook 7 to Storybook 8 would need to know about these inner workings and set them up themselves.
Users who opt out of SWC will still have SWC in the bundle, with an additional 35mb in size, even if not used.
What about the coverage addon, which relies on Babel?
In Storybook 8.0, the webpack5 builder is configured per default with swc. The babel-loader is not set up; hence, users must manually set up the babel integration. The swc-loader will be set up per default to provide a zero-config experience for users, which setup Storybook in new projects
Tasks
Remove babel-loader and its dependencies
The webpack5 builder doesn't implement babel anymore. Therefore we can remove babel as a peer dependency in all packages where possible.
The babel and babelDefault presets can be removed. export const babel = ... and export const babelDefault = ... statements doesn't have any effects in preset files anymore.
The Typescript preset setting skipBabel is not handled anymore and should be removed in all places.
Remove the automigration which adds a missing babel rc file
During sandbox generation, don't install a default list of babel presets and plugins automatically for webpack-based projects
Docs: Remove documentation about how to use custom babel configuration via presets
Remove the internal/swc-webpack sandbox, since we have sandboxes, which cover swc as a compiler
Set up babel-loader for frameworks which don't support SWC
Ember
A list of babel plugins, which were applied per default:
react-refresh/babel
storybook-react-refresh
@babel/preset-react
babel-plugin-add-react-displayname
Add SWC compiler as default compiler for Webpack5
Set up SWC-loader per default for webpack5
Add required custom SWC configuration for specific frameworks/renderers
In Storybook 8, the Webpack5 builder is not set up with a default compiler. Instead, Storybook or the community will provide addons to configure a compiler for Storybook. Since the default experience should still work out of the box, Storybook will provide a @storybook/addon-webpack5-compiler-swc package, which sets up the swc-loader. All newly generated webpack5-based sandboxes, which are SWC capable, will be set up with this addon configured.
To guarantee a smooth migration, we will also provide a @storybook/addon-webpack5-compiler-babel7 package, which configures the babel-loader and the necessary setup for projects that cannot or don't want to migrate away from a babel setup.
Questions:
How should we handle breaking changes between major versions of Babel?
There are two possibilities: Either we release a new addon like @storybook/addon-webpack5-compiler-babel8 to encapsulate Babel 8-related logic, or we move the addon outside of the mono repo to be able to use its versioning. It could follow semver-versioning and wouldn't be coupled to the breaking change version cycle of the mono repository.
Tasks
All tasks from Proposal 1, except setting up SWC
Create a @storybook/addon-webpack5-compiler-swc package
Register swc-loader via webpackFinal in preset.ts
Adjust sandboxes to add the addon for all webpack5 sandboxes, which are capable of using SWC
Create a @storybook/addon-webpack5-compiler-babel7 package
Register babel-loader via webpackFinal in preset.ts
Configure it for all supported frameworks/renderers
Write an auto migration to add @storybook/addon-webpack5-compiler-babel7 for all Webpack5-based projects
Add documentation to setup a compiler for Webpack5
Spike Results
Sandbox
Default Compiler
Description
Angular
X
The angular framework doesn't need any compiler addon because we load their webpack config, which already has the babel-loader set up.
HTML-WEBPACK5
SWC
PREACT-WEBPACK5
SWC
A documentation might be necessary for users who might stick with babel to make sure that a .babelrc file exists and that "@babel/plugin-transform-react-jsx is set up properly, because Storybook wouldn't apply any default configuration anymore
CRA JS/TS
X
Should not use SWC since it uses babel already under the hood.
Next.js
X
Does initialize its very own next-swc-loader to setup swc. If the user wants to opt-out for Babel, custom babel configuration remain in place and @storybook/addon-webpack5-compiler-babel7 must be used.
Advantages
builder-webpack5 is lightweight since it doesn't ship any default compiler
separation of concerns: We strictly separate the Webpack5 builder and compilers. Also, updating compilers can happen in the same addon package or a new one if it turns out that covering multiple babel versions in one addon is impossible.
Disadvantages
We introduce two new dependencies
The text was updated successfully, but these errors were encountered:
Objective: Determine the feasibility and implications of replacing the default Babel builder with SWC in Webpack5-based projects, especially in the context of the Storybook.
1. Investigate hurdles to remove the babel-loader and replace it with swc-loader
Results:
babel-plugin-react-docgen
In Storybook 8.0, we want to use
react-docgen
as the default tool to extract type information for the controls panel. Currently, it is operated via a babel plugin calledbabel-plugin-react-docgen
.Task: Replace the babel plugin by an appropriate webpack-loader, which calls
react-docgen
. Similar was done for the vite-builder.storybookjs/babel-plugin-named-exports-order
This plugin is necessary to persist the correct export order of Stories, since webpack and vite sometimes doesn't preserve the original order.
Task: This plugin has to be rewritten as a webpack-loader. Similar was done for the vite builder.
react-refresh/babel
The react-refresh/babel plugin is necessary to make fast refresh work for React-based projects. It works together with the webpack plugin https://github.com/pmmmwh/react-refresh-webpack-plugin
Task: A specific SWC setting has to be passed to the
swc-loader
to enable fast-refresh for react-based projects only: https://swc.rs/docs/configuration/compilation#jsctransformreactrefreshNo flow support
SWC does not have flow support. People would have to opt-out from swc and use babel instead, if they would like to continue to use flow.
2. List all frameworks which are not able to use SWC or in a limited way
Frameworks
Angular
Switching to SWC does not make much sense since Angular plans to continue with esbuild instead of SWC as a compiler. The Angular esbuild builder is still experimental though and we don't know yet how to easily integrate it. We are collaborating with the Angular team to achieve some esbuild support sooner or later. For now, we cannot ditch babel support since SWC still needs to support Angular.
Next.js
We have some custom babel plugins in place, which are necessary for Next.js. We cannot rewrite them to SWC plugins, since the Node binding of SWC doesn't have a Javascript Plugin API. Plugins have to be translated into Rust and then compiled together with SWC, which then could be used via WASM in Node.js. An alternative would be to try out whether we could use the Next.js' custom Rust compiler, which builds on top of SWC or to use Next.js' next-custom-loader, which configures swc under the hood. I have tried out this approach. The main issue is, that, for example, the font webpack plugins have to be rewritten since Next.js' implementation of how fonts are loaded differs from the current implementation in Storybook with Babel. I can't say how complex and long it takes to fully support SWC.
[UPDATE] Next.js findings
After some experimentation, it was possible to use Next.js'
next-swc-loader
in@storybook/nextjs
. This also made it possible to support@next/font
without the need of creating custom Babel files like it is needed in Storybook 7.It can be experimented with the following canary version:
0.0.0-pr-24504-sha-5d9e47a4
.Unfortunately, because
next-swc-loader
uses internal profiling utilities which are not available in Storybook's implementation, we needed to create a local patch of thenext-swc-loader
to remove the profiling, and thus make the loader work correctly. Some small changes are needed to support both Babel and SWC, but it's very feasible.Ember
Ember sets up some babel plugins: (babel-plugin-ember-modules-api-polyfill and babel-plugin-htmlbars-inline-precompile). Not sure, whether it works with SWC out of the box.
Preact
Preact has a plugin to support fast refresh. Hooks, though, require a special babel plugin. This isn't available for SWC. Therefore, full support for fast refresh is not possible.
Satellites depending on babel
Sandbox compatibility
Questions
What are the implications of relying on SWC and removing Babel from Storybook 8?
babel-plugin-named-exports-order
and caching setup. In Storybook 8, assuming all the Babel configs are removed, users who migrate from Storybook 7 to Storybook 8 would need to know about these inner workings and set them up themselves.What about the coverage addon, which relies on Babel?
Should we bootstrap new Webpack5-based Storybook inits with SWC per default in 7.x already?
Proposals
Proposal 1: Storybook 8 does not provide any Babel support
PR: #24504
In Storybook 8.0, the webpack5 builder is configured per default with swc. The babel-loader is not set up; hence, users must manually set up the babel integration. The swc-loader will be set up per default to provide a zero-config experience for users, which setup Storybook in new projects
Tasks
Remove babel-loader and its dependencies
babel
andbabelDefault
presets can be removed.export const babel = ...
andexport const babelDefault = ...
statements doesn't have any effects in preset files anymore.skipBabel
is not handled anymore and should be removed in all places.internal/swc-webpack
sandbox, since we have sandboxes, which cover swc as a compilerA list of babel plugins, which were applied per default:
Add SWC compiler as default compiler for Webpack5
next-swc-loader
, which uses a custom build of swc with plugins integrated)storybook-addon-swc
addon if in useAdvantages
Disadvantages
swc
andswc-loader
as dependencies are always shipped, even if it is not needed (CRA, Next.js, Angular)Proposal 2: Storybook 8 is compiler agnostic for the Webpack5 builder
PR: #24598
In Storybook 8, the Webpack5 builder is not set up with a default compiler. Instead, Storybook or the community will provide addons to configure a compiler for Storybook. Since the default experience should still work out of the box, Storybook will provide a
@storybook/addon-webpack5-compiler-swc
package, which sets up theswc-loader
. All newly generated webpack5-based sandboxes, which are SWC capable, will be set up with this addon configured.To guarantee a smooth migration, we will also provide a
@storybook/addon-webpack5-compiler-babel7
package, which configures the babel-loader and the necessary setup for projects that cannot or don't want to migrate away from a babel setup.Questions:
How should we handle breaking changes between major versions of Babel?
There are two possibilities: Either we release a new addon like
@storybook/addon-webpack5-compiler-babel8
to encapsulate Babel 8-related logic, or we move the addon outside of the mono repo to be able to use its versioning. It could follow semver-versioning and wouldn't be coupled to the breaking change version cycle of the mono repository.Tasks
webpackFinal
in preset.tswebpackFinal
in preset.ts@storybook/addon-webpack5-compiler-babel7
for all Webpack5-based projectsSpike Results
"@babel/plugin-transform-react-jsx
is set up properly, because Storybook wouldn't apply any default configuration anymoreswc
. If the user wants to opt-out for Babel, custom babel configuration remain in place and@storybook/addon-webpack5-compiler-babel7
must be used.Advantages
builder-webpack5
is lightweight since it doesn't ship any default compilerDisadvantages
The text was updated successfully, but these errors were encountered: