Skip to content

Commit b1772ca

Browse files
authored
feat: allow choosing vue version on creation (and in presets) (#5637)
1 parent 7c2a36b commit b1772ca

File tree

57 files changed

+3431
-3969
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3431
-3969
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
node_modules
22
template
3+
template-vue3
34
packages/test
45
temp
56
entry-wc.js

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@
9191
},
9292
"resolutions": {
9393
"puppeteer": "1.11.0",
94-
"vue": "^2.6.11",
9594
"vue-template-compiler": "^2.6.11",
9695
"vue-server-renderer": "^2.6.11"
9796
}

packages/@vue/babel-preset-app/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Use this option when you have 3rd party dependencies that are not processed by B
8888

8989
- Default: `true`.
9090

91-
Set to `false` to disable JSX support. Or you can toggle [@vue/babel-preset-jsx](https://github.com/vuejs/jsx/tree/dev/packages/babel-preset-jsx) features here.
91+
Set to `false` to disable JSX support. Or you can toggle [@vue/babel-preset-jsx](https://github.com/vuejs/jsx/tree/dev/packages/babel-preset-jsx) (or [@ant-design-vue/babel-plugin-jsx](https://github.com/vueComponent/jsx) for Vue 3 projects) features here.
9292

9393
### loose
9494

packages/@vue/babel-preset-app/index.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,22 @@ module.exports = (context, options = {}) => {
112112

113113
// JSX
114114
if (options.jsx !== false) {
115-
presets.push([require('@vue/babel-preset-jsx'), typeof options.jsx === 'object' ? options.jsx : {}])
115+
let jsxOptions = {}
116+
if (typeof options.jsx === 'object') {
117+
jsxOptions = options.jsx
118+
}
119+
120+
let vueVersion = 2
121+
try {
122+
const Vue = require('vue')
123+
vueVersion = semver.major(Vue.version)
124+
} catch (e) {}
125+
126+
if (vueVersion === 2) {
127+
presets.push([require('@vue/babel-preset-jsx'), jsxOptions])
128+
} else if (vueVersion === 3) {
129+
plugins.push([require('@ant-design-vue/babel-plugin-jsx'), jsxOptions])
130+
}
116131
}
117132

118133
const runtimePath = path.dirname(require.resolve('@babel/runtime/package.json'))

packages/@vue/babel-preset-app/package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
},
2323
"homepage": "https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/babel-preset-app#readme",
2424
"dependencies": {
25+
"@ant-design-vue/babel-plugin-jsx": "^1.0.0-0",
2526
"@babel/core": "^7.9.6",
2627
"@babel/helper-compilation-targets": "^7.9.6",
2728
"@babel/helper-module-imports": "^7.8.3",
@@ -40,11 +41,15 @@
4041
},
4142
"peerDependencies": {
4243
"@babel/core": "*",
43-
"core-js": "^3"
44+
"core-js": "^3",
45+
"vue": "^2 || ^3.0.0-0"
4446
},
4547
"peerDependenciesMeta": {
4648
"core-js": {
4749
"optional": true
50+
},
51+
"vue": {
52+
"optional": true
4853
}
4954
}
5055
}

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

-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ const create = require('@vue/cli-test-utils/createUpgradableProject')
22
const { logs } = require('@vue/cli-shared-utils')
33

44
jest.setTimeout(300000)
5-
beforeEach(() => {
6-
process.env.VUE_CLI_TEST_DO_INSTALL_PLUGIN = true
7-
})
85

96
test('upgrade: plugin-babel v3.5', async () => {
107
const project = await create('plugin-babel-legacy', {

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

+5
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ beforeAll(async () => {
6363
)
6464
})
6565

66+
afterAll(async () => {
67+
// avoid the non-existent made-up deps interfere with other tests
68+
await project.rm('package.json')
69+
})
70+
6671
test('dep from node_modules should not been transpiled', async () => {
6772
await project.run('vue-cli-service build')
6873
expect(await readVendorFile()).toMatch('() => "__TEST__"')

packages/@vue/cli-plugin-eslint/__tests__/eslintMigrator.spec.js

-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
jest.setTimeout(300000)
22
jest.mock('inquirer')
33

4-
beforeEach(() => {
5-
process.env.VUE_CLI_TEST_DO_INSTALL_PLUGIN = true
6-
})
7-
84
const create = require('@vue/cli-test-utils/createUpgradableProject')
95
const { expectPrompts } = require('inquirer')
106

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
jest.setTimeout(300000)
2+
3+
const generateWithPlugin = require('@vue/cli-test-utils/generateWithPlugin')
4+
const createOutside = require('@vue/cli-test-utils/createUpgradableProject')
5+
6+
test('Vue 3 base', async () => {
7+
const { pkg } = await generateWithPlugin([
8+
{
9+
id: '@vue/cli-service',
10+
apply: require('@vue/cli-service/generator'),
11+
options: {
12+
vueVersion: '3'
13+
}
14+
},
15+
{
16+
id: '@vue/cli-plugineslint',
17+
apply: require('../generator'),
18+
options: {}
19+
}
20+
])
21+
22+
expect(pkg.scripts.lint).toBeTruthy()
23+
expect(pkg.eslintConfig.extends).toEqual([
24+
'plugin:vue/vue3-essential', 'eslint:recommended'
25+
])
26+
})
27+
28+
test('Should allow fragments in Vue 3 projects', async () => {
29+
const { write, run } = await createOutside('eslint-vue3-fragment', {
30+
vueVersion: '3',
31+
plugins: {
32+
'@vue/cli-plugin-eslint': {}
33+
}
34+
})
35+
await write('src/App.vue', `<template>
36+
<img alt="Vue logo" src="./assets/logo.png">
37+
<HelloWorld msg="Welcome to Your Vue.js App"/>
38+
</template>
39+
40+
<script>
41+
import HelloWorld from './components/HelloWorld.vue'
42+
43+
export default {
44+
name: 'App',
45+
components: {
46+
HelloWorld
47+
}
48+
}
49+
</script>
50+
`)
51+
52+
await run('vue-cli-service lint')
53+
})

packages/@vue/cli-plugin-eslint/eslintDeps.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ const DEPS_MAP = {
2828

2929
exports.DEPS_MAP = DEPS_MAP
3030

31-
exports.getDeps = function (api, preset) {
31+
exports.getDeps = function (api, preset, rootOptions = {}) {
3232
const deps = Object.assign({}, DEPS_MAP.base, DEPS_MAP[preset])
3333

34+
if (rootOptions.vueVersion === '3') {
35+
Object.assign(deps, { 'eslint-plugin-vue': '^7.0.0-0' })
36+
}
37+
3438
if (api.hasPlugin('typescript')) {
3539
Object.assign(deps, DEPS_MAP.typescript)
3640
}

packages/@vue/cli-plugin-eslint/eslintOptions.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
exports.config = (api, preset) => {
1+
exports.config = (api, preset, rootOptions = {}) => {
22
const config = {
33
root: true,
44
env: { node: true },
@@ -40,6 +40,15 @@ exports.config = (api, preset) => {
4040
}
4141
}
4242

43+
if (rootOptions.vueVersion === '3') {
44+
const updateConfig = cfg =>
45+
cfg.replace(
46+
/plugin:vue\/(essential|recommended|strongly-recommended)/gi,
47+
'plugin:vue/vue3-$1'
48+
)
49+
config.extends = config.extends.map(updateConfig)
50+
}
51+
4352
return config
4453
}
4554

packages/@vue/cli-plugin-eslint/generator/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
const fs = require('fs')
22
const path = require('path')
33

4-
module.exports = (api, { config, lintOn = [] }, _, invoking) => {
5-
const eslintConfig = require('../eslintOptions').config(api, config)
6-
const devDependencies = require('../eslintDeps').getDeps(api, config)
4+
module.exports = (api, { config, lintOn = [] }, rootOptions, invoking) => {
5+
const eslintConfig = require('../eslintOptions').config(api, config, rootOptions)
6+
const devDependencies = require('../eslintDeps').getDeps(api, config, rootOptions)
77

88
const pkg = {
99
scripts: {

packages/@vue/cli-plugin-router/__tests__/routerGenerator.spec.js

+74
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,77 @@ test('use with Babel', async () => {
6262

6363
expect(pkg.dependencies).toHaveProperty('vue-router')
6464
})
65+
66+
test('use with Vue 3', async () => {
67+
const { files, pkg } = await generateWithPlugin([
68+
{
69+
id: '@vue/cli-service',
70+
apply: require('@vue/cli-service/generator'),
71+
options: {
72+
vueVersion: '3'
73+
}
74+
},
75+
{
76+
id: '@vue/cli-plugin-router',
77+
apply: require('../generator'),
78+
options: {}
79+
}
80+
])
81+
82+
expect(files['src/router/index.js']).toBeTruthy()
83+
expect(files['src/router/index.js']).toMatch('createRouter')
84+
expect(files['src/router/index.js']).toMatch('history: createWebHashHistory()')
85+
86+
expect(files['src/main.js']).toMatch('.use(router)')
87+
88+
expect(pkg.dependencies).toHaveProperty('vue-router')
89+
expect(pkg.dependencies['vue-router']).toMatch('^4')
90+
})
91+
92+
test('Vue 3 + History Mode', async () => {
93+
const { files } = await generateWithPlugin([
94+
{
95+
id: '@vue/cli-service',
96+
apply: require('@vue/cli-service/generator'),
97+
options: {
98+
vueVersion: '3'
99+
}
100+
},
101+
{
102+
id: '@vue/cli-plugin-router',
103+
apply: require('../generator'),
104+
options: {
105+
historyMode: true
106+
}
107+
}
108+
])
109+
110+
expect(files['src/router/index.js']).toMatch(/import {.*createWebHistory/)
111+
expect(files['src/router/index.js']).toMatch('history: createWebHistory(process.env.BASE_URL)')
112+
})
113+
114+
test('Vue 3 + TypeScript', async () => {
115+
const { files } = await generateWithPlugin([
116+
{
117+
id: '@vue/cli-service',
118+
apply: require('@vue/cli-service/generator'),
119+
options: {
120+
vueVersion: '3'
121+
}
122+
},
123+
{
124+
id: '@vue/cli-plugin-router',
125+
apply: require('../generator'),
126+
options: {}
127+
},
128+
{
129+
id: '@vue/cli-plugin-typescript',
130+
apply: require('@vue/cli-plugin-typescript/generator'),
131+
options: {}
132+
}
133+
])
134+
135+
expect(files['src/router/index.ts']).toBeTruthy()
136+
expect(files['src/router/index.ts']).toMatch(/import {.*RouteRecordRaw/)
137+
expect(files['src/router/index.ts']).toMatch('const routes: Array<RouteRecordRaw> =')
138+
})

packages/@vue/cli-plugin-router/generator/index.js

+27-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
1-
module.exports = (api, options = {}) => {
1+
module.exports = (api, options = {}, rootOptions = {}) => {
2+
const isVue3 = (rootOptions.vueVersion === '3')
3+
24
api.injectImports(api.entryFile, `import router from './router'`)
3-
api.injectRootOptions(api.entryFile, `router`)
45

5-
api.extendPackage({
6-
dependencies: {
7-
'vue-router': '^3.2.0'
8-
}
9-
})
6+
if (isVue3) {
7+
api.transformScript(api.entryFile, require('./injectUseRouter'))
8+
api.extendPackage({
9+
dependencies: {
10+
'vue-router': '^4.0.0-0'
11+
}
12+
})
13+
} else {
14+
api.injectRootOptions(api.entryFile, `router`)
15+
16+
api.extendPackage({
17+
dependencies: {
18+
'vue-router': '^3.2.0'
19+
}
20+
})
21+
}
1022

1123
api.render('./template', {
1224
historyMode: options.historyMode,
1325
doesCompile: api.hasPlugin('babel') || api.hasPlugin('typescript'),
1426
hasTypeScript: api.hasPlugin('typescript')
1527
})
1628

29+
if (isVue3) {
30+
api.render('./template-vue3', {
31+
historyMode: options.historyMode,
32+
doesCompile: api.hasPlugin('babel') || api.hasPlugin('typescript'),
33+
hasTypeScript: api.hasPlugin('typescript')
34+
})
35+
}
36+
1737
if (api.invoking) {
1838
if (api.hasPlugin('typescript')) {
1939
/* eslint-disable-next-line node/no-extraneous-require */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module.exports = (file, api) => {
2+
const j = api.jscodeshift
3+
const root = j(file.source)
4+
5+
const appRoots = root.find(j.CallExpression, (node) => {
6+
if (j.Identifier.check(node.callee) && node.callee.name === 'createApp') {
7+
return true
8+
}
9+
10+
if (
11+
j.MemberExpression.check(node.callee) &&
12+
j.Identifier.check(node.callee.object) &&
13+
node.callee.object.name === 'Vue' &&
14+
j.Identifier.check(node.callee.property) &&
15+
node.callee.property.name === 'createApp'
16+
) {
17+
return true
18+
}
19+
})
20+
21+
appRoots.replaceWith(({ node: createAppCall }) => {
22+
return j.callExpression(
23+
j.memberExpression(createAppCall, j.identifier('use')),
24+
[j.identifier('router')]
25+
)
26+
})
27+
28+
return root.toSource()
29+
}

0 commit comments

Comments
 (0)