Skip to content

Commit b00776e

Browse files
committed
Support Babel 8 peer ranges
1 parent dcaac6b commit b00776e

6 files changed

Lines changed: 115 additions & 16 deletions

File tree

docs/customizing_babel_config.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ module.exports = function (api) {
6666
"@babel/preset-react",
6767
{
6868
development: isDevelopmentEnv || isTestEnv,
69-
useBuiltIns: true
69+
runtime: "classic"
7070
}
7171
]
7272
].filter(Boolean),
@@ -87,3 +87,23 @@ module.exports = function (api) {
8787
return resultConfig
8888
}
8989
```
90+
91+
### Babel 8
92+
93+
Shakapacker supports Babel 7 and Babel 8. If you use Babel 8, install matching
94+
Babel 8 packages for the Shakapacker preset and use `babel-loader` 10 or newer:
95+
96+
```bash
97+
npm install --save-dev @babel/core@^8 @babel/plugin-transform-runtime@^8 @babel/preset-env@^8 @babel/runtime@^8 babel-loader@^10
98+
```
99+
100+
Babel 8 requires Node `^22.18.0 || >=24.11.0` while running the build. It also
101+
removed some Babel 7 configuration options. The Shakapacker preset omits those
102+
removed options when Babel 8 is running, but app-level custom Babel config should
103+
also avoid Babel 7-only options such as `useBuiltIns` on `@babel/preset-react`
104+
or `helpers` on `@babel/plugin-transform-runtime`.
105+
106+
If your app relied on Babel 7 `@babel/preset-env` `useBuiltIns: "entry"`
107+
polyfill rewriting, move polyfill injection to your app config for Babel 8, for
108+
example with `babel-plugin-polyfill-corejs3`, or keep explicit `core-js` imports
109+
that match your browser support policy.

docs/peer-dependencies.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ releases support.
5656
Installed when you explicitly use `javascript_transpiler: "babel"`:
5757

5858
```text
59-
"@babel/core": "^7.17.9"
60-
"@babel/plugin-transform-runtime": "^7.17.0"
61-
"@babel/preset-env": "^7.16.11"
62-
"@babel/runtime": "^7.17.9"
59+
"@babel/core": "^7.17.9 || ^8.0.0"
60+
"@babel/plugin-transform-runtime": "^7.17.0 || ^8.0.0"
61+
"@babel/preset-env": "^7.16.11 || ^8.0.0"
62+
"@babel/runtime": "^7.17.9 || ^8.0.0"
6363
"babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0"
6464
```
6565

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@
102102
"webpack-subresource-integrity": "5.1.0"
103103
},
104104
"peerDependencies": {
105-
"@babel/core": "^7.17.9",
106-
"@babel/plugin-transform-runtime": "^7.17.0",
107-
"@babel/preset-env": "^7.16.11",
108-
"@babel/runtime": "^7.17.9",
105+
"@babel/core": "^7.17.9 || ^8.0.0",
106+
"@babel/plugin-transform-runtime": "^7.17.0 || ^8.0.0",
107+
"@babel/preset-env": "^7.16.11 || ^8.0.0",
108+
"@babel/runtime": "^7.17.9 || ^8.0.0",
109109
"@rspack/cli": "^2.0.0",
110110
"@rspack/core": "^2.0.0",
111111
"@rspack/dev-server": "^2.0.0",

package/babel/preset.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import type { ConfigAPI, PluginItem } from "@babel/core"
33

44
const CORE_JS_VERSION_REGEX = /^\d+\.\d+/
55

6+
const babelMajorVersion = (api: ConfigAPI & { version?: string }): number => {
7+
const version = api.version?.match(/^\d+/)
8+
return version ? parseInt(version[0], 10) : 7
9+
}
10+
611
const coreJsVersion = (): string => {
712
try {
813
const version = packageFullVersion("core-js").match(CORE_JS_VERSION_REGEX)
@@ -33,23 +38,33 @@ export = function config(api: ConfigAPI): {
3338
)
3439
}
3540

36-
const presets: PluginItem[] = [
37-
isTestEnv && ["@babel/preset-env", { targets: { node: "current" } }],
38-
(isProductionEnv || isDevelopmentEnv) && [
39-
"@babel/preset-env",
40-
{
41+
const isBabel8 = babelMajorVersion(api) >= 8
42+
const presetEnvOptions = isBabel8
43+
? {
44+
modules: "auto",
45+
exclude: ["transform-typeof-symbol"]
46+
}
47+
: {
4148
useBuiltIns: "entry",
4249
corejs: coreJsVersion(),
4350
modules: "auto",
4451
bugfixes: true,
4552
exclude: ["transform-typeof-symbol"]
4653
}
54+
55+
const presets: PluginItem[] = [
56+
isTestEnv && ["@babel/preset-env", { targets: { node: "current" } }],
57+
(isProductionEnv || isDevelopmentEnv) && [
58+
"@babel/preset-env",
59+
presetEnvOptions
4760
],
4861
moduleExists("@babel/preset-typescript") && "@babel/preset-typescript"
4962
].filter(Boolean) as PluginItem[]
5063

5164
const plugins: PluginItem[] = [
52-
["@babel/plugin-transform-runtime", { helpers: false }]
65+
isBabel8
66+
? "@babel/plugin-transform-runtime"
67+
: ["@babel/plugin-transform-runtime", { helpers: false }]
5368
].filter(Boolean) as PluginItem[]
5469

5570
return {

packages/shakapacker-webpack/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.0 || ^0.6.0",
4040
"@swc/core": "^1.3.0",
4141
"swc-loader": "^0.1.15 || ^0.2.0",
42-
"@babel/core": "^7.17.9",
42+
"@babel/core": "^7.17.9 || ^8.0.0",
4343
"babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0",
4444
"esbuild": ">=0.14.0 <1.0.0",
4545
"esbuild-loader": "^2.0.0 || ^3.0.0 || ^4.0.0",

test/package/rules/babel.test.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ jest.mock("../../../package/config", () => {
1616
})
1717

1818
const babelConfig = require("../../../package/rules/babel")
19+
const shakapackerBabelPreset = require("../../../package/babel/preset")
20+
const shakapackerManifest = require("../../../package.json")
21+
const shakapackerWebpackManifest = require("../../../packages/shakapacker-webpack/package.json")
22+
23+
const createBabelApi = (envName, version) => ({
24+
version,
25+
env: jest.fn((name) => (name ? name === envName : envName))
26+
})
27+
28+
const presetEnvOptions = (config) =>
29+
config.presets.find(
30+
(preset) => Array.isArray(preset) && preset[0] === "@babel/preset-env"
31+
)[1]
1932

2033
// Skip tests if babel config is not available (not the active transpiler)
2134
if (!babelConfig) {
@@ -83,3 +96,54 @@ if (!babelConfig) {
8396
})
8497
})
8598
} // end of else block for babelConfig check
99+
100+
describe("babel preset", () => {
101+
test("keeps Babel 7 preset-env and transform-runtime options", () => {
102+
const config = shakapackerBabelPreset(
103+
createBabelApi("production", "7.29.0")
104+
)
105+
106+
expect(presetEnvOptions(config)).toMatchObject({
107+
useBuiltIns: "entry",
108+
corejs: "3.8",
109+
modules: "auto",
110+
bugfixes: true,
111+
exclude: ["transform-typeof-symbol"]
112+
})
113+
expect(config.plugins).toContainEqual([
114+
"@babel/plugin-transform-runtime",
115+
{ helpers: false }
116+
])
117+
})
118+
119+
test("omits options Babel 8 removed", () => {
120+
const config = shakapackerBabelPreset(createBabelApi("production", "8.0.1"))
121+
const options = presetEnvOptions(config)
122+
123+
expect(options).toMatchObject({
124+
modules: "auto",
125+
exclude: ["transform-typeof-symbol"]
126+
})
127+
expect(options).not.toHaveProperty("useBuiltIns")
128+
expect(options).not.toHaveProperty("corejs")
129+
expect(options).not.toHaveProperty("bugfixes")
130+
expect(config.plugins).toContain("@babel/plugin-transform-runtime")
131+
expect(config.plugins).not.toContainEqual([
132+
"@babel/plugin-transform-runtime",
133+
{ helpers: false }
134+
])
135+
})
136+
137+
test("allows Babel 8 peers without changing Babel 7 development pins", () => {
138+
expect(shakapackerManifest.devDependencies["@babel/core"]).toBe("7.29.0")
139+
expect(shakapackerManifest.peerDependencies).toMatchObject({
140+
"@babel/core": "^7.17.9 || ^8.0.0",
141+
"@babel/plugin-transform-runtime": "^7.17.0 || ^8.0.0",
142+
"@babel/preset-env": "^7.16.11 || ^8.0.0",
143+
"@babel/runtime": "^7.17.9 || ^8.0.0"
144+
})
145+
expect(shakapackerWebpackManifest.peerDependencies["@babel/core"]).toBe(
146+
"^7.17.9 || ^8.0.0"
147+
)
148+
})
149+
})

0 commit comments

Comments
 (0)