Skip to content

Commit b29cc12

Browse files
Updates
1 parent e545ec4 commit b29cc12

File tree

1 file changed

+27
-33
lines changed

1 file changed

+27
-33
lines changed

rfcs/0000-move-ecmascript-plugins-to-core.md

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,27 @@ export function internalPluginAvailable(name: string): boolean;
5353

5454
## Monorepo structure
5555

56-
All the plugins for stable ECMAScript features should be moved from the `./packages/babel-plugin-*` folders into `./packages/babel-core/src/transform-plugins/*`.
56+
All the plugins for stable ECMAScript features should be moved from the `./packages/babel-plugin-*` folders into `./packages/babel-core/src/internal-plugins/*`.
5757

5858
To make it easier to run tests for an individual plugin (currently you can use `yarn jest transform-classes`), we can still keep tests in separate internal workspaces, for example in `/test/core-plugins/[plugin name]`.
5959

6060
## New Stage 4 proposals
6161

6262
When an ECMAScript proposal is promoted from Stage 3 to Stage 4, we should:
6363
1. Enable it by default in `@babel/parser`
64-
2. Copy the transform plugin into `@babel/core`
64+
2. Copy the transform plugin into `@babel/core`, and rename it from `@babel/plugin-proposal-*` to `internal:transform-*`
6565
3. Enable it by default in `@babel/preset-env`
6666
4. Archive the `@babel/plugin-syntax-*` syntax plugin
6767
5. Archive the `@babel/plugin-proposal-*` transform plugin
6868

69-
`@babel/preset-env` should still depend on the archived proposal plugin: since it's a separate package, it could still be used with an older `@babel/core` version that doesn't support the new `internal:*` plugin.
69+
`@babel/preset-env` will only enable plugins supported by the currently used `@babel/core` version. If a proposal reaches stage 4 for the x.y.z Babel release, `@babel/preset-env` will only enable it when both the `@babel/core` and `@babel/preset-env` versions are at least x.y.z. `@babel/preset-env` will not fallback to the `@babel/plugin-proposal-*` plugin when using older `@babel/core` versions, for multiple reasons:
70+
- so that it does not need to depend on `-syntax-` plugins for compatibility with older `@babel/parser` versions;
71+
- to avoid downloading every plugin that reaches Stage 4 twice: once as part of `@babel/core` and once as a dependency of `@babel/preset-env`;
72+
- to encourage people to use the latest `@babel/core` version.
7073

71-
It can call, for example, `babel.internalPluginAvailable("internal:transform-classes")` to decide whether it should enable the internal plugin or fallback to the old proposal implementation.
74+
## Bugfix plugins
75+
76+
Bugfix plugins would be subject to the same policy as plugins for whole new features: if they are fixing a bug related to a standard (or stage 4) feature, they should be moved to `@babel/core` named following the `internal:bugfix-[engine name]-[bug description]` pattern.
7277

7378
# Drawbacks
7479

@@ -84,51 +89,40 @@ If we discover that the additional bundle size causes problems for other tools d
8489
## To the whole RFC
8590

8691
- Keep the current status.
87-
- Drop SemVer for the `@babel/core` `peerDependency` of plugins, so that we can require an higher `@babel/core` version when needed.
92+
- Drop SemVer for the `@babel/core` `peerDependency` of plugins, so that we can require an higher `@babel/core` version when needed. Plugins would then be able to require an higher `@bebel/core` version even without waiting for the next major release.
8893

8994
## To specific parts of the RFC
9095

91-
Instead of the `internalPluginAvailable` function, we could export an `internalPluginName` function with the following signature:
92-
93-
```js
94-
export function internalPluginName(name: string): string | undefined;
95-
```
96+
Instead of the `internalPluginAvailable` function, we can expose an `availableInternalPlugins: ReadonlySet<string>` that `@babel/core` consumers can use to check which plugins are available. This is as simple as `internalPluginAvailable`, with the advantage that it has a standard interface and it also allows iterating over the list of plugin names (is this something that we want to allow? what useages does it unlock?).
9697

97-
This function takes a plugin name (either internal or external) as the input, and returns the internal plugin name when it's available:
98-
99-
```js
100-
internalPluginName("internal:transform-classes"); // "internal:transform-classes"
101-
internalPluginName("@babel/plugin-transform-classes"); // "internal:transform-classes"
102-
internalPluginName("@babel/plugin-unknown"); // undefined
103-
```
98+
# Adoption strategy
10499

105-
`@babel/core` can then conditionally enable plugins like this:
100+
For most Babel users, this RFC doesn't require any direct action.
106101

107-
```js
108-
import transformClasses from "@babel/plugin-transform-classes";
102+
If they depend on one of the packages that will be moved to `@babel/core`, they can remove that dependency and use the `internal:` plugin in their configuraiton.
109103

110-
// ...
104+
# How we teach this
111105

112-
plugins: [
113-
babel.internalPluginName("@babel/plugin-transform-classes") ?? transformClasses
114-
]
115-
```
106+
Since this RFC doesn't have a big impact on how to use Babel, documenting the new `internal:` plugin is enough.
116107

117-
by doing so, we could make old `@babel/preset-env` versions aware of new `@babel/core` internal plugins, so that it doesn't accidentally enable an older proposal implementation after that it becomes Stage 4 and is moved to stage 4.
108+
In the next major release, we can publish an empty placeholder with a deprecation error for all the plugins moved to `@babel/core`, similarly to what we did with `@babel/[email protected]`.
118109

119-
Is it worth the additional complexity? (we would need a list of plugin names mappings in `@babel/core`).
110+
Additionally, whenever a proposal reaches Stage 4 and is included in `@babel/core` we can `npm deprecate` the previous `@babel/plugin-proposal-*` package, since it will stop being maintained and people should be encouraged to migrate to the `internal:transform-*` plugin.
120111

121-
# Adoption strategy
112+
# Internal migration strategy
122113

123-
For most Babel users, this RFC doesn't require any direct action.
114+
_NOTE: This paragrpah assumes that we want to implement this RFC in Babel 7. If we end up doing it for Babel 8.0.0, we won't have the "duplicated code" problem._
124115

125-
If they depend on one of the packages that will be moved to `@babel/core`, they can remove that dependency and use the `internal:` plugin in their configuraiton.
116+
When mirating to this new approach, we must keep in mind that we have an hard constraint: `@babel/preset-env` must continue being compatible with every `@babel/core` 7.x.y version, and it must continue to enable at least all the plugins that it's currently enabling. This means that we cannot simply move all the plugins to `@babel/core` and remove them from `@babel/preset-env`'s dependencies.
126117

127-
# How we teach this
118+
There are three possible approaches that we can take:
119+
1. Copy the existing stable plugins into `@babel/core`, but keep the old ones as dependencies of `@babel/preset-env` so that they can be used as a fallback when using an old `@babel/core` version. This leads to an increased combined size of `@babel/core`+`@babel/preset-env`, since all the plugins' code is effectively duplicated. It will be between around 1MB, less than the total `@babel/preset-env` size, because all the polyfill-related plugins and the compatibility data will _not_ be duplicated.
120+
2. Make `@babel/core` depend on all the existing stable plugins, and re-export them as `internal:transform-*` plugins.
121+
3. Make `@babel/preset-env` depend on a new `@babel/core` version, so that it can access the plugins even if it's being run by an older `@babel/core` version. We might need an intermediate package between `@babel/preset-env` and it's `@babel/core` dependency, because `@babel/core` is already a _peer_ dependency of `@babel/preset-env`.
128122

129-
Since this RFC doesn't have a big impact on how to use Babel, documenting the new `internal:` plugin is enough.
123+
Approach (2) and (3) lead to the best size outcome (i.e. it won't change), because package managers will continue to be able to deduplicate the plugins packages. However, we must continue assuming that plugins might be used with old `@babel/core` versions and thus they cannot rely on the advantages mentioned in the "Motivation" section above.
130124

131-
In the next major release, we can publish an empty placeholder with a deprecation error for all the plugins moved to `@babel/core`, similarly to what we did with `@babel/preset-[email protected]`.
125+
Regardess of the approach that we take, new Stage 4 plugins can be directly moved to `@babel/core`, since `@babel/preset-env` doesn't depend yet on them. Additionally, when releasing Babel 8 we can move all the _existing_ stage 4 plugins to `@babel/core` and remove them from `@babel/preset-env`'s dependencies.
132126

133127
# Open questions
134128

0 commit comments

Comments
 (0)