Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/@vue/babel-preset-app/__tests__/babel-preset.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ test('async/await', () => {
// should use regenerator runtime
expect(code).toMatch(`import "regenerator-runtime/runtime"`)
// should use required helper instead of inline
expect(code).toMatch(/import _asyncToGenerator from ".*runtime-corejs3\/helpers\/esm\/asyncToGenerator\"/)
expect(code).toMatch(/import _asyncToGenerator from ".*runtime\/helpers\/esm\/asyncToGenerator\"/)
})

test('jsx', () => {
Expand Down Expand Up @@ -135,7 +135,8 @@ test('jsx options', () => {
jsx: {
injectH: false
}
}]]
}]],
filename: 'test-entry-file.js'
})
expect(code).not.toMatch(`var h = arguments[0]`)
expect(code).toMatch(`return h("div", ["bar"])`)
Expand All @@ -152,6 +153,6 @@ test('disable absoluteRuntime', () => {
filename: 'test-entry-file.js'
})

expect(code).toMatch('import _toConsumableArray from "@babel/runtime-corejs3/helpers/esm/toConsumableArray"')
expect(code).toMatch('import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"')
expect(code).not.toMatch(getAbsolutePolyfill('es.promise'))
})
37 changes: 19 additions & 18 deletions packages/@vue/babel-preset-app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,24 +183,25 @@ module.exports = (context, options = {}) => {
absoluteRuntime
}])

// use @babel/runtime-corejs3 so that helpers that need polyfillable APIs will reference core-js instead.
// if useBuiltIns is not set to 'usage', then it means users would take care of the polyfills on their own,
// i.e., core-js 3 is no longer needed.
// this extra plugin can be removed once one of the two issues resolves:
// https://github.com/babel/babel/issues/7597
// https://github.com/babel/babel/issues/9903
if (useBuiltIns === 'usage' && !process.env.VUE_CLI_MODERN_BUILD) {
const runtimeCoreJs3Path = path.dirname(require.resolve('@babel/runtime-corejs3/package.json'))
plugins.push([require('babel-plugin-module-resolver'), {
alias: {
'@babel/runtime': '@babel/runtime-corejs3',
[runtimePath]: runtimeCoreJs3Path
}
}])
}

return {
presets,
plugins
overrides: [{
exclude: [/@babel[\/|\\\\]runtime/, /core-js/],
presets,
plugins
}, {
// there are some untranspiled code in @babel/runtime
// https://github.com/babel/babel/issues/9903
include: [/@babel[\/|\\\\]runtime/],
presets: [
[require('@babel/preset-env'), {
useBuiltIns,
corejs: 3
}]
]
}]
}
}

// a special flag to tell @vue/cli-plugin-babel to include @babel/runtime for transpilation
// otherwise the above `include` option won't take effect
process.env.VUE_CLI_TRANSPILE_BABEL_RUNTIME = true
2 changes: 0 additions & 2 deletions packages/@vue/babel-preset-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/preset-env": "^7.6.3",
"@babel/runtime": "^7.6.3",
"@babel/runtime-corejs3": "^7.6.3",
"@vue/babel-preset-jsx": "^1.1.1",
"babel-plugin-dynamic-import-node": "^2.2.0",
"babel-plugin-module-resolver": "^3.2.0",
"core-js": "^3.3.2",
"core-js-compat": "^3.3.2"
}
Expand Down
77 changes: 77 additions & 0 deletions packages/@vue/cli-plugin-babel/__tests__/babel-runtime.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
jest.setTimeout(80000)

const { defaultPreset } = require('@vue/cli/lib/options')
const create = require('@vue/cli-test-utils/createTestProject')
const serve = require('@vue/cli-test-utils/serveWithPuppeteer')

test('should add polyfills for code in @babel/runtime', async () => {
const project = await create('babel-runtime-polyfills', defaultPreset)

await project.write('src/main.js', `
const x = function () {
setTimeout(
// eslint-disable-next-line
() => console.log(...arguments), 100
);
}
x(1, 2)
`)

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

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

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

const mainjs = await project.read('src/main.js')
await project.write('src/main.js', `
// eslint-disable-next-line
console.log(typeof Symbol('a'))

${mainjs}
`)

// if the typeof symbol helper is transpiled recursively,
// there would be an error thrown and the page would be empty
await serve(
() => project.run('vue-cli-service serve'),
async ({ helpers }) => {
const msg = `Welcome to Your Vue.js App`
expect(await helpers.getText('h1')).toMatch(msg)
}
)
})

// #4742 core-js-pure imports are likely to be caused by
// incorrect configuration of @babel/plugin-transform-runtime
test('should not introduce polyfills from core-js-pure', async () => {
const project = await create('babel-runtime-core-js-pure', defaultPreset)

await project.write('src/main.js', `
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
render: h => h(App),
methods: {
myfunc: async function () {}
}
}).$mount('#app')
`)

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

expect(vendorFile).not.toMatch('core-js-pure')
})
17 changes: 16 additions & 1 deletion packages/@vue/cli-plugin-babel/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const path = require('path')
const babel = require('@babel/core')
const { isWindows } = require('@vue/cli-shared-utils')

function genTranspileDepRegex (transpileDependencies) {
Expand All @@ -17,9 +18,14 @@ function genTranspileDepRegex (transpileDependencies) {

module.exports = (api, options) => {
const useThreads = process.env.NODE_ENV === 'production' && !!options.parallel
const cliServicePath = require('path').dirname(require.resolve('@vue/cli-service'))
const cliServicePath = path.dirname(require.resolve('@vue/cli-service'))
const transpileDepRegex = genTranspileDepRegex(options.transpileDependencies)

// try to load the project babel config;
// if the default preset is used,
// there will be a VUE_CLI_TRANSPILE_BABEL_RUNTIME env var set.
babel.loadPartialConfig()

api.chainWebpack(webpackConfig => {
webpackConfig.resolveLoader.modules.prepend(path.join(__dirname, 'node_modules'))

Expand All @@ -36,6 +42,15 @@ module.exports = (api, options) => {
if (filepath.startsWith(cliServicePath)) {
return true
}

// only include @babel/runtime when the @vue/babel-preset-app preset is used
if (
process.env.VUE_CLI_TRANSPILE_BABEL_RUNTIME &&
filepath.includes(path.join('@babel', 'runtime'))
) {
return false
}

// check if this is something the user explicitly wants to transpile
if (transpileDepRegex && transpileDepRegex.test(filepath)) {
return false
Expand Down
4 changes: 4 additions & 0 deletions packages/@vue/cli-service/__tests__/serve.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const { defaultPreset } = require('@vue/cli/lib/options')
const create = require('@vue/cli-test-utils/createTestProject')
const serve = require('@vue/cli-test-utils/serveWithPuppeteer')

const sleep = n => new Promise(resolve => setTimeout(resolve, n))

test('serve', async () => {
const project = await create('e2e-serve', defaultPreset)

Expand Down Expand Up @@ -53,6 +55,7 @@ test('serve with router', async () => {
expect(await helpers.hasClass('a[href="#/about"]', 'router-link-exact-active')).toBe(false)

await page.click('a[href="#/about"]')
await sleep(1000)
expect(await helpers.getText('h1')).toMatch(`This is an about page`)
expect(await helpers.hasElement('#nav')).toBe(true)
expect(await helpers.hasClass('a[href="#/"]', 'router-link-exact-active')).toBe(false)
Expand All @@ -76,6 +79,7 @@ test('serve with legacy router option', async () => {
expect(await helpers.hasClass('a[href="/about"]', 'router-link-exact-active')).toBe(false)

await page.click('a[href="/about"]')
await sleep(1000)
expect(await helpers.getText('h1')).toMatch(`This is an about page`)
expect(await helpers.hasElement('#nav')).toBe(true)
expect(await helpers.hasClass('a[href="/"]', 'router-link-exact-active')).toBe(false)
Expand Down