Skip to content

Commit d64e7d3

Browse files
authored
feat: when transpileDependencies is set to true, transpile all dependencies in node_modules (#6354)
1 parent 54d5f78 commit d64e7d3

File tree

9 files changed

+107
-56
lines changed

9 files changed

+107
-56
lines changed

docs/config/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,12 @@ Deprecated since Vue CLI 3.3, please use [`publicPath`](#publicPath) instead.
194194

195195
### transpileDependencies
196196

197-
- Type: `Array<string | RegExp>`
198-
- Default: `[]`
197+
- Type: `boolean | Array<string | RegExp>`
198+
- Default: `false`
199+
200+
By default `babel-loader` ignores all files inside `node_modules`. You can enable this option to avoid unexpected untranspiled code from third-party dependencies.
199201

200-
By default `babel-loader` ignores all files inside `node_modules`. If you want to explicitly transpile a dependency with Babel, you can list it in this option.
202+
Transpiling all the dependencies could slow down the build process, though. If build performance is a concern, you can explicitly transpile only some of the dependencies by passing an array of package names or name patterns to this option.
201203

202204
::: warning Jest config
203205
This option is not respected by the [cli-unit-jest plugin](#jest), because in jest, we don't have to transpile code from `/node_modules` unless it uses non-standard features - Node >8.11 supports the latest ECMAScript features already.

docs/core-plugins/babel.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66

77
Uses Babel 7 + `babel-loader` + [@vue/babel-preset-app](https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/babel-preset-app) by default, but can be configured via `babel.config.js` to use any other Babel presets or plugins.
88

9-
By default, `babel-loader` excludes files inside `node_modules` dependencies. If you wish to explicitly transpile a dependency module, you will need to add it to the `transpileDependencies` option in `vue.config.js`:
9+
By default, `babel-loader` excludes files inside `node_modules` dependencies. You can enable the `transpileDependencies` option in `vue.config.js` to transpile the dependencies. Or, if you want to only transpile some of the dependency modules, you can pass an array to the `transpileDependencies` option:
1010

1111
``` js
1212
module.exports = {
13+
// Set to `true` to transpile all dependencies.
14+
// Or pass an array to transpile selectively.
1315
transpileDependencies: [
1416
// can be string or regex
1517
'my-dep',

docs/migrations/migrate-from-v4.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ No longer supports generating project with `node-sass`. It has been [deprecated]
9292
* `terser-webpack-plugin` is upgraded from v2 to v5 (v4 if you choose to stay at webpack 4), using terser 5 and some there are some changes in the options format. See full details in its [changelog](https://github.com/webpack-contrib/terser-webpack-plugin/blob/master/CHANGELOG.md).
9393
* When creating new projects, the default `less-loader` is updated from [v5 to v8](https://github.com/webpack-contrib/less-loader/blob/master/CHANGELOG.md)(v7 for webpack 4 users); `less` from [v3 to v4](https://github.com/less/less.js/pull/3573); `sass-loader` from [v8 to v11](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md) (v10 for webpack 4 users); `stylus-loader` from [v3 to v5](https://github.com/webpack-contrib/stylus-loader/blob/master/CHANGELOG.md) (v4 for webpack 4 users).
9494

95+
### Babel Plugin
96+
97+
The [`transpileDependencies` option](../config/#transpiledependencies) now accepts a boolean value. Setting it to `true` will transpile all dependencies inside `node_modules`.
98+
9599
### ESLint Plugin
96100

97101
* `eslint-loader` is replaced by [eslint-webpack-plugin](https://github.com/webpack-contrib/eslint-webpack-plugin), dropping support for ESLint <= 6.

docs/zh/config/README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,13 @@ module.exports = defineConfig({
195195

196196
### transpileDependencies
197197

198-
- Type: `Array<string | RegExp>`
199-
- Default: `[]`
198+
- Type: `boolean | Array<string | RegExp>`
199+
- Default: `false`
200+
201+
默认情况下 `babel-loader` 会忽略所有 `node_modules` 中的文件。你可以启用本选项,以避免构建后的代码中出现未转译的第三方依赖。
202+
203+
不过,对所有的依赖都进行转译可能会降低构建速度。如果对构建性能有所顾虑,你可以只转译部分特定的依赖:给本选项传一个数组,列出需要转译的第三方包包名或正则表达式即可。
200204

201-
默认情况下 `babel-loader` 会忽略所有 `node_modules` 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来。
202205

203206
### productionSourceMap
204207

packages/@vue/cli-plugin-babel/__tests__/babelRuntime.spec.js

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,31 @@ const { defaultPreset } = require('@vue/cli/lib/options')
44
const create = require('@vue/cli-test-utils/createTestProject')
55
const serve = require('@vue/cli-test-utils/serveWithPuppeteer')
66

7-
test('should add polyfills for code in @babel/runtime', async () => {
8-
const project = await create('babel-runtime-polyfills', defaultPreset)
7+
// iterableToArray no longer required in babel/runtime 7.8.7+
8+
// test('should add polyfills for code in @babel/runtime', async () => {
9+
// const project = await create('babel-runtime-polyfills', defaultPreset)
910

10-
await project.write('src/main.js', `
11-
const x = function () {
12-
setTimeout(
13-
// eslint-disable-next-line
14-
() => console.log(...arguments), 100
15-
);
16-
}
17-
x(1, 2)
18-
`)
11+
// await project.write('src/main.js', `
12+
// const x = function () {
13+
// setTimeout(
14+
// // eslint-disable-next-line
15+
// () => console.log(...arguments), 100
16+
// );
17+
// }
18+
// x(1, 2)
19+
// `)
1920

20-
await project.run('vue-cli-service build --mode development')
21-
const vendorFile = await project.read('dist/js/chunk-vendors.js')
21+
// await project.run('vue-cli-service build --mode development')
22+
// const vendorFile = await project.read('dist/js/chunk-vendors.js')
2223

23-
// iterableToArray is used to transform `console.log(...arguments)`
24-
expect(vendorFile).toMatch('iterableToArray')
25-
// with inline helpers, preset-env can detect the symbol polyfill is required
26-
// (because the implementation of `iterableToArray` relies on it)
27-
// however, with transform-runtime plugin, helpers are only references to @babel/runtime modules
28-
// so we need to make sure polyfill detection is enabled for @babel/runtime too
29-
expect(vendorFile).toMatch('es.symbol')
30-
})
24+
// // iterableToArray is used to transform `console.log(...arguments)`
25+
// expect(vendorFile).toMatch('iterableToArray')
26+
// // with inline helpers, preset-env can detect the symbol polyfill is required
27+
// // (because the implementation of `iterableToArray` relies on it)
28+
// // however, with transform-runtime plugin, helpers are only references to @babel/runtime modules
29+
// // so we need to make sure polyfill detection is enabled for @babel/runtime too
30+
// expect(vendorFile).toMatch('es.symbol')
31+
// })
3132

3233
test('should not transpile babel helpers multiple times', async () => {
3334
const project = await create('babel-runtime-helpers', defaultPreset)

packages/@vue/cli-plugin-babel/__tests__/transpileDependencies.spec.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ afterAll(async () => {
6868
await project.rm('package.json')
6969
})
7070

71-
test('dep from node_modules should not been transpiled', async () => {
71+
test('dep from node_modules should not been transpiled by default', async () => {
7272
await project.run('vue-cli-service build')
7373
expect(await readVendorFile()).toMatch('() => "__TEST__"')
7474
})
7575

76-
test('dep from node_modules should been transpiled', async () => {
76+
test('dep from node_modules should been transpiled when matched by transpileDependencies', async () => {
7777
await project.write(
7878
'vue.config.js',
7979
`module.exports = { transpileDependencies: ['external-dep', '@scope/external-dep'] }`
@@ -84,6 +84,17 @@ test('dep from node_modules should been transpiled', async () => {
8484
expect(await readVendorFile()).toMatch('return "__SCOPE_TEST__"')
8585
})
8686

87+
test('dep from node_modules should been transpiled when transpileDependencies is true', async () => {
88+
await project.write(
89+
'vue.config.js',
90+
`module.exports = { transpileDependencies: true }`
91+
)
92+
await project.run('vue-cli-service build')
93+
expect(await readVendorFile()).toMatch('return "__TEST__"')
94+
95+
expect(await readVendorFile()).toMatch('return "__SCOPE_TEST__"')
96+
})
97+
8798
// https://github.com/vuejs/vue-cli/issues/3057
8899
test('only transpile package with same name specified in transpileDependencies', async () => {
89100
await project.write(

packages/@vue/cli-plugin-babel/index.js

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ const path = require('path')
22
const babel = require('@babel/core')
33
const { isWindows } = require('@vue/cli-shared-utils')
44

5-
function genTranspileDepRegex (transpileDependencies) {
6-
const deps = transpileDependencies.map(dep => {
5+
function getDepPathRegex (dependencies) {
6+
const deps = dependencies.map(dep => {
77
if (typeof dep === 'string') {
88
const depPath = path.join('node_modules', dep, '/')
99
return isWindows
@@ -22,7 +22,6 @@ function genTranspileDepRegex (transpileDependencies) {
2222
module.exports = (api, options) => {
2323
const useThreads = process.env.NODE_ENV === 'production' && !!options.parallel
2424
const cliServicePath = path.dirname(require.resolve('@vue/cli-service'))
25-
const transpileDepRegex = genTranspileDepRegex(options.transpileDependencies)
2625

2726
// try to load the project babel config;
2827
// if the default preset is used,
@@ -39,34 +38,60 @@ module.exports = (api, options) => {
3938
.test(/\.m?jsx?$/)
4039
.exclude
4140
.add(filepath => {
41+
const SHOULD_SKIP = true
42+
const SHOULD_TRANSPILE = false
43+
4244
// With data URI support in webpack 5, filepath could be undefined
4345
if (!filepath) {
44-
return true
46+
return SHOULD_SKIP
4547
}
4648

47-
// always transpile js in vue files
49+
// Always transpile js in vue files
4850
if (/\.vue\.jsx?$/.test(filepath)) {
49-
return false
51+
return SHOULD_TRANSPILE
5052
}
51-
// exclude dynamic entries from cli-service
53+
// Exclude dynamic entries from cli-service
5254
if (filepath.startsWith(cliServicePath)) {
53-
return true
55+
return SHOULD_SKIP
56+
}
57+
58+
// To transpile `@babel/runtime`, the config needs to be
59+
// carefully adjusted to avoid infinite loops.
60+
// So we only do the tranpilation when the special flag is on.
61+
if (getDepPathRegex(['@babel/runtime']).test(filepath)) {
62+
return process.env.VUE_CLI_TRANSPILE_BABEL_RUNTIME
63+
? SHOULD_TRANSPILE
64+
: SHOULD_SKIP
5465
}
5566

56-
// only include @babel/runtime when the @vue/babel-preset-app preset is used
57-
if (
58-
process.env.VUE_CLI_TRANSPILE_BABEL_RUNTIME &&
59-
filepath.includes(path.join('@babel', 'runtime'))
60-
) {
61-
return false
67+
// if `transpileDependencies` is set to true, transpile all deps
68+
if (options.transpileDependencies === true) {
69+
// Some of the deps cannot be transpiled, though
70+
// https://stackoverflow.com/a/58517865/2302258
71+
const NON_TRANSPILABLE_DEPS = [
72+
'core-js',
73+
'webpack',
74+
'webpack-4',
75+
'css-loader',
76+
'mini-css-extract-plugin',
77+
'promise-polyfill',
78+
'html-webpack-plugin',
79+
'whatwg-fetch'
80+
]
81+
const nonTranspilableDepsRegex = getDepPathRegex(NON_TRANSPILABLE_DEPS)
82+
return nonTranspilableDepsRegex.test(filepath) ? SHOULD_SKIP : SHOULD_TRANSPILE
6283
}
6384

64-
// check if this is something the user explicitly wants to transpile
65-
if (transpileDepRegex && transpileDepRegex.test(filepath)) {
66-
return false
85+
// Otherwise, check if this is something the user explicitly wants to transpile
86+
if (Array.isArray(options.transpileDependencies)) {
87+
const transpileDepRegex = getDepPathRegex(options.transpileDependencies)
88+
if (transpileDepRegex && transpileDepRegex.test(filepath)) {
89+
return SHOULD_TRANSPILE
90+
}
6791
}
92+
6893
// Don't transpile node_modules
69-
return /node_modules/.test(filepath)
94+
return /node_modules/.test(filepath) ? SHOULD_SKIP : SHOULD_TRANSPILE
7095
})
7196
.end()
7297

packages/@vue/cli-service/lib/options.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ const schema = createSchema(joi => joi.object({
77
indexPath: joi.string(),
88
filenameHashing: joi.boolean(),
99
runtimeCompiler: joi.boolean(),
10-
transpileDependencies: joi.array(),
10+
transpileDependencies: joi.alternatives().try(
11+
joi.boolean(),
12+
joi.array()
13+
),
1114
productionSourceMap: joi.boolean(),
1215
parallel: joi.alternatives().try(
1316
joi.boolean(),
@@ -94,10 +97,8 @@ exports.defaults = () => ({
9497
// boolean, use full build?
9598
runtimeCompiler: false,
9699

97-
// deps to transpile
98-
transpileDependencies: [
99-
/* string or regex */
100-
],
100+
// whether to transpile all dependencies
101+
transpileDependencies: false,
101102

102103
// sourceMap for production build?
103104
productionSourceMap: !process.env.VUE_CLI_TEST,

packages/@vue/cli-service/types/ProjectOptions.d.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,13 @@ interface ProjectOptions {
8787
*/
8888
runtimeCompiler?: boolean;
8989
/**
90-
* Default: `[]`
90+
* Default: `false`
9191
*
92-
* If you want to explicitly transpile a dependency with Babel, you can list it in this option
92+
* If set to `true`, all dependencies in `node_modules` will be transpiled by Babel;
93+
* Or, if you only want to selectively transpile some of the dependencies, you can list them
94+
* in this option.
9395
*/
94-
transpileDependencies?: Array<string | RegExp>;
96+
transpileDependencies?: boolean | Array<string | RegExp>;
9597
/**
9698
* Default: `true`
9799
*

0 commit comments

Comments
 (0)