diff --git a/docs/dev-guide/ui-api.md b/docs/dev-guide/ui-api.md
index 4ee32902fe..a742100d9e 100644
--- a/docs/dev-guide/ui-api.md
+++ b/docs/dev-guide/ui-api.md
@@ -1274,7 +1274,7 @@ const ROUTER = 'vue-router-add'
api.onViewOpen(({ view }) => {
if (view.id === 'vue-project-plugins') {
- if (!api.hasPlugin('vue-router')) {
+ if (!api.hasPlugin('router')) {
api.addSuggestion({
id: ROUTER,
type: 'action',
@@ -1282,7 +1282,7 @@ api.onViewOpen(({ view }) => {
message: 'org.vue.cli-service.suggestions.vue-router-add.message',
link: 'https://router.vuejs.org/',
async handler () {
- await install(api, 'vue-router')
+ await install(api, 'router')
}
})
}
diff --git a/docs/guide/plugins-and-presets.md b/docs/guide/plugins-and-presets.md
index 0ebee9f122..ae0de69711 100644
--- a/docs/guide/plugins-and-presets.md
+++ b/docs/guide/plugins-and-presets.md
@@ -52,13 +52,6 @@ You can pass generator options to the installed plugin (this will skip the promp
vue add @vue/eslint --config airbnb --lintOn save
```
-`vue-router` and `vuex` are special cases - they do not have their own plugins, but you can add them nonetheless:
-
-``` bash
-vue add router
-vue add vuex
-```
-
If a plugin is already installed, you can skip the installation and only invoke its generator with the `vue invoke` command. The command takes the same arguments as `vue add`.
::: tip
@@ -112,7 +105,6 @@ Here's an example preset:
``` json
{
"useConfigFiles": true,
- "router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
@@ -120,7 +112,8 @@ Here's an example preset:
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
- }
+ },
+ "@vue/cli-plugin-router": {}
}
}
```
diff --git a/docs/ru/dev-guide/ui-api.md b/docs/ru/dev-guide/ui-api.md
index 6560eb3c28..91d657e756 100644
--- a/docs/ru/dev-guide/ui-api.md
+++ b/docs/ru/dev-guide/ui-api.md
@@ -1274,7 +1274,7 @@ const ROUTER = 'vue-router-add'
api.onViewOpen(({ view }) => {
if (view.id === 'vue-project-plugins') {
- if (!api.hasPlugin('vue-router')) {
+ if (!api.hasPlugin('router')) {
api.addSuggestion({
id: ROUTER,
type: 'action',
@@ -1282,7 +1282,7 @@ api.onViewOpen(({ view }) => {
message: 'org.vue.cli-service.suggestions.vue-router-add.message',
link: 'https://router.vuejs.org/',
async handler () {
- await install(api, 'vue-router')
+ await install(api, 'router')
}
})
}
diff --git a/docs/ru/guide/plugins-and-presets.md b/docs/ru/guide/plugins-and-presets.md
index 2233469f7a..7bd8b63618 100644
--- a/docs/ru/guide/plugins-and-presets.md
+++ b/docs/ru/guide/plugins-and-presets.md
@@ -52,13 +52,6 @@ vue add @foo/bar
vue add @vue/eslint --config airbnb --lintOn save
```
-Добавление `vue-router` и `vuex` — особый случай, у них нет собственных плагинов, но вы тем не менее можете их добавить:
-
-``` bash
-vue add router
-vue add vuex
-```
-
Если плагин уже установлен, вы можете пропустить установку и только вызвать его генератор с помощью команды `vue invoke`. Команда принимает такие же аргументы, как и `vue add`.
::: tip Совет
@@ -112,7 +105,6 @@ vue add vuex
``` json
{
"useConfigFiles": true,
- "router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
@@ -120,7 +112,8 @@ vue add vuex
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
- }
+ },
+ "@vue/cli-plugin-router": {}
}
}
```
diff --git a/docs/zh/guide/plugins-and-presets.md b/docs/zh/guide/plugins-and-presets.md
index 48b0edc0f7..db6b8754c5 100644
--- a/docs/zh/guide/plugins-and-presets.md
+++ b/docs/zh/guide/plugins-and-presets.md
@@ -52,13 +52,6 @@ vue add @foo/bar
vue add @vue/eslint --config airbnb --lintOn save
```
-`vue-router` 和 `vuex` 的情况比较特殊——它们并没有自己的插件,但是你仍然可以这样添加它们:
-
-``` bash
-vue add router
-vue add vuex
-```
-
如果一个插件已经被安装,你可以使用 `vue invoke` 命令跳过安装过程,只调用它的生成器。这个命令会接受和 `vue add` 相同的参数。
::: tip 提示
@@ -112,7 +105,6 @@ vue add vuex
``` json
{
"useConfigFiles": true,
- "router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
@@ -120,7 +112,8 @@ vue add vuex
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
- }
+ },
+ "@vue/cli-plugin-router": {}
}
}
```
diff --git a/packages/@vue/cli-plugin-router/.npmignore b/packages/@vue/cli-plugin-router/.npmignore
new file mode 100644
index 0000000000..e0b178a189
--- /dev/null
+++ b/packages/@vue/cli-plugin-router/.npmignore
@@ -0,0 +1,2 @@
+__tests__
+__mocks__
diff --git a/packages/@vue/cli-plugin-router/README.md b/packages/@vue/cli-plugin-router/README.md
new file mode 100644
index 0000000000..05786ca865
--- /dev/null
+++ b/packages/@vue/cli-plugin-router/README.md
@@ -0,0 +1,9 @@
+# @vue/cli-plugin-router
+
+> router plugin for vue-cli
+
+## Installing in an Already Created Project
+
+``` sh
+vue add @vue/router
+```
diff --git a/packages/@vue/cli-plugin-router/__tests__/routerGenerator.spec.js b/packages/@vue/cli-plugin-router/__tests__/routerGenerator.spec.js
new file mode 100644
index 0000000000..baac1337b6
--- /dev/null
+++ b/packages/@vue/cli-plugin-router/__tests__/routerGenerator.spec.js
@@ -0,0 +1,64 @@
+const generateWithPlugin = require('@vue/cli-test-utils/generateWithPlugin')
+
+test('base', async () => {
+ const { files, pkg } = await generateWithPlugin({
+ id: 'router',
+ apply: require('../generator'),
+ options: {}
+ })
+
+ expect(files['src/router/index.js']).toBeTruthy()
+ expect(files['src/router/index.js']).not.toMatch('history')
+ expect(files['src/views/About.vue']).toBeTruthy()
+ expect(files['src/views/Home.vue']).toBeTruthy()
+ expect(files['src/App.vue']).toMatch('Home')
+ expect(files['src/App.vue']).not.toMatch('
- <%_ } _%>
-<%_ } else { _%>
-
-
-
-<%_ } _%>
-<%_ if (!rootOptions.bare) { _%>
-<%_ if (rootOptions.cssPreprocessor !== 'stylus') { _%>
+<%_ if (rootOptions.cssPreprocessor !== 'stylus') { _%>
<%_ } _%>
<%_ } _%>
diff --git a/packages/@vue/cli-service/lib/PluginAPI.js b/packages/@vue/cli-service/lib/PluginAPI.js
index d3672d4ed1..39ebe76c28 100644
--- a/packages/@vue/cli-service/lib/PluginAPI.js
+++ b/packages/@vue/cli-service/lib/PluginAPI.js
@@ -64,8 +64,7 @@ class PluginAPI {
* @return {boolean}
*/
hasPlugin (id) {
- if (id === 'router') id = 'vue-router'
- if (['vue-router', 'vuex'].includes(id)) {
+ if (['vuex'].includes(id)) {
const pkg = this.service.pkg
return ((pkg.dependencies && pkg.dependencies[id]) || (pkg.devDependencies && pkg.devDependencies[id]))
}
diff --git a/packages/@vue/cli-ui/apollo-server/api/PluginApi.js b/packages/@vue/cli-ui/apollo-server/api/PluginApi.js
index 4c26ff6c86..e5ecbf2044 100644
--- a/packages/@vue/cli-ui/apollo-server/api/PluginApi.js
+++ b/packages/@vue/cli-ui/apollo-server/api/PluginApi.js
@@ -397,8 +397,7 @@ class PluginApi {
* @param {string} id Plugin id or short id
*/
hasPlugin (id) {
- if (id === 'router') id = 'vue-router'
- if (['vue-router', 'vuex'].includes(id)) {
+ if (['vuex'].includes(id)) {
const pkg = folders.readPackage(this.cwd, this.context, true)
return ((pkg.dependencies && pkg.dependencies[id]) || (pkg.devDependencies && pkg.devDependencies[id]))
}
diff --git a/packages/@vue/cli-ui/tests/e2e/specs/g2-plugins.js b/packages/@vue/cli-ui/tests/e2e/specs/g2-plugins.js
index ad36b135b2..8bd290edcf 100644
--- a/packages/@vue/cli-ui/tests/e2e/specs/g2-plugins.js
+++ b/packages/@vue/cli-ui/tests/e2e/specs/g2-plugins.js
@@ -1,7 +1,7 @@
describe('Plugins', () => {
it('Should display the plugins', () => {
cy.visit('/plugins')
- cy.get('.project-plugin-item').should('have.length', 4)
+ cy.get('.project-plugin-item').should('have.length', 5)
})
it('Should add a plugin', () => {
@@ -26,6 +26,6 @@ describe('Plugins', () => {
.should('be.visible')
.should('not.have.class', 'disabled')
.click()
- cy.get('.project-plugin-item').should('have.length', 4)
+ cy.get('.project-plugin-item').should('have.length', 5)
})
})
diff --git a/packages/@vue/cli-ui/ui-defaults/suggestions.js b/packages/@vue/cli-ui/ui-defaults/suggestions.js
index 8378ec3449..ae27af4081 100644
--- a/packages/@vue/cli-ui/ui-defaults/suggestions.js
+++ b/packages/@vue/cli-ui/ui-defaults/suggestions.js
@@ -8,7 +8,7 @@ const VUE_CONFIG_OPEN = 'org.vue.vue-config-open'
module.exports = api => {
api.onViewOpen(({ view }) => {
if (view.id === 'vue-project-plugins') {
- if (!api.hasPlugin('vue-router')) {
+ if (!api.hasPlugin('router')) {
api.addSuggestion({
id: ROUTER,
type: 'action',
@@ -16,7 +16,7 @@ module.exports = api => {
message: 'org.vue.cli-service.suggestions.vue-router-add.message',
link: 'https://router.vuejs.org/',
async handler () {
- await install(api, 'vue-router')
+ await install(api, 'router')
}
})
}
@@ -73,16 +73,19 @@ async function install (api, id) {
progress: -1
})
- const name = id === 'vue-router' ? 'router' : id
const context = api.getCwd()
let error
try {
- await invoke.runGenerator(context, {
- id: `core:${name}`,
- apply: loadModule(`@vue/cli-service/generator/${name}`, context)
- })
+ if (id === 'router') {
+ await invoke(id, {}, context)
+ } else {
+ await invoke.runGenerator(context, {
+ id: `core:${id}`,
+ apply: loadModule(`@vue/cli-service/generator/${id}`, context)
+ })
+ }
} catch (e) {
error = e
}
diff --git a/packages/@vue/cli/lib/Creator.js b/packages/@vue/cli/lib/Creator.js
index 7782b59cf6..e8db9c0774 100644
--- a/packages/@vue/cli/lib/Creator.js
+++ b/packages/@vue/cli/lib/Creator.js
@@ -92,10 +92,20 @@ module.exports = class Creator extends EventEmitter {
preset.plugins['@vue/cli-service'] = Object.assign({
projectName: name
}, preset)
+
if (cliOptions.bare) {
preset.plugins['@vue/cli-service'].bare = true
}
+ // legacy support for router
+ if (preset.router) {
+ preset.plugins['@vue/cli-plugin-router'] = {}
+
+ if (preset.routerHistoryMode) {
+ preset.plugins['@vue/cli-plugin-router'].historyMode = true
+ }
+ }
+
const packageManager = (
cliOptions.packageManager ||
loadOptions().packageManager ||
diff --git a/packages/@vue/cli/lib/Generator.js b/packages/@vue/cli/lib/Generator.js
index 87386bea07..ecd826a87e 100644
--- a/packages/@vue/cli/lib/Generator.js
+++ b/packages/@vue/cli/lib/Generator.js
@@ -243,8 +243,7 @@ module.exports = class Generator {
}
hasPlugin (_id) {
- if (_id === 'router') _id = 'vue-router'
- if (['vue-router', 'vuex'].includes(_id)) {
+ if (['vuex'].includes(_id)) {
const pkg = this.pkg
return ((pkg.dependencies && pkg.dependencies[_id]) || (pkg.devDependencies && pkg.devDependencies[_id]))
}
diff --git a/packages/@vue/cli/lib/add.js b/packages/@vue/cli/lib/add.js
index 848a843cd2..4d8b147921 100644
--- a/packages/@vue/cli/lib/add.js
+++ b/packages/@vue/cli/lib/add.js
@@ -14,9 +14,6 @@ const {
async function add (pluginName, options = {}, context = process.cwd()) {
// special internal "plugins"
- if (/^(@vue\/)?router$/.test(pluginName)) {
- return addRouter(context)
- }
if (/^(@vue\/)?vuex$/.test(pluginName)) {
return addVuex(context)
}
@@ -41,20 +38,6 @@ async function add (pluginName, options = {}, context = process.cwd()) {
}
}
-async function addRouter (context) {
- const inquirer = require('inquirer')
- const options = await inquirer.prompt([{
- name: 'routerHistoryMode',
- type: 'confirm',
- message: `Use history mode for router? ${chalk.yellow(`(Requires proper server setup for index fallback in production)`)}`
- }])
- invoke.runGenerator(context, {
- id: 'core:router',
- apply: loadModule('@vue/cli-service/generator/router', context),
- options
- })
-}
-
async function addVuex (context) {
invoke.runGenerator(context, {
id: 'core:vuex',
diff --git a/packages/@vue/cli/lib/options.js b/packages/@vue/cli/lib/options.js
index 197414cde1..e2f26e729a 100644
--- a/packages/@vue/cli/lib/options.js
+++ b/packages/@vue/cli/lib/options.js
@@ -10,6 +10,7 @@ const rcPath = exports.rcPath = getRcPath('.vuerc')
const presetSchema = createSchema(joi => joi.object().keys({
bare: joi.boolean(),
useConfigFiles: joi.boolean(),
+ // TODO: Use warn for router once @hapi/joi v16 releases
router: joi.boolean(),
routerHistoryMode: joi.boolean(),
vuex: joi.boolean(),
@@ -31,7 +32,6 @@ exports.validatePreset = preset => validate(preset, presetSchema, msg => {
})
exports.defaultPreset = {
- router: false,
vuex: false,
useConfigFiles: false,
cssPreprocessor: undefined,
diff --git a/packages/@vue/cli/lib/promptModules/__tests__/router.spec.js b/packages/@vue/cli/lib/promptModules/__tests__/router.spec.js
index 932ebafafa..9f9918177f 100644
--- a/packages/@vue/cli/lib/promptModules/__tests__/router.spec.js
+++ b/packages/@vue/cli/lib/promptModules/__tests__/router.spec.js
@@ -19,9 +19,11 @@ test('router', async () => {
]
const expectedOptions = {
- router: true,
- routerHistoryMode: true,
- plugins: {}
+ plugins: {
+ '@vue/cli-plugin-router': {
+ historyMode: true
+ }
+ }
}
await assertPromptModule(
diff --git a/packages/@vue/cli/lib/promptModules/router.js b/packages/@vue/cli/lib/promptModules/router.js
index f64b6ec4f6..2cdc1d239c 100644
--- a/packages/@vue/cli/lib/promptModules/router.js
+++ b/packages/@vue/cli/lib/promptModules/router.js
@@ -9,7 +9,7 @@ module.exports = cli => {
})
cli.injectPrompt({
- name: 'routerHistoryMode',
+ name: 'historyMode',
when: answers => answers.features.includes('router'),
type: 'confirm',
message: `Use history mode for router? ${chalk.yellow(`(Requires proper server setup for index fallback in production)`)}`,
@@ -19,8 +19,9 @@ module.exports = cli => {
cli.onPromptComplete((answers, options) => {
if (answers.features.includes('router')) {
- options.router = true
- options.routerHistoryMode = answers.routerHistoryMode
+ options.plugins['@vue/cli-plugin-router'] = {
+ historyMode: answers.historyMode
+ }
}
})
}
diff --git a/packages/@vue/cli/lib/util/features.js b/packages/@vue/cli/lib/util/features.js
index e64e69df04..916952ba01 100644
--- a/packages/@vue/cli/lib/util/features.js
+++ b/packages/@vue/cli/lib/util/features.js
@@ -4,7 +4,7 @@ const { toShortPluginId } = require('@vue/cli-shared-utils')
exports.getFeatures = (preset) => {
const features = []
if (preset.router) {
- features.push('vue-router')
+ features.push('router')
}
if (preset.vuex) {
features.push('vuex')