Skip to content

Commit

Permalink
feat!: make router a separate plugin (#4196)
Browse files Browse the repository at this point in the history
* refactor: move router to its own plugin

* refactor: rename routerHistoryMode option to historyMode

* test: add @vue/cli-plugin-router tests

* feat: change src/router.js for most common use cases

* fix: fix cli-ui tests

* docs: Remove router root option from docs

* fix: add support for legacy router option
  • Loading branch information
pksunkara authored and sodatea committed Jul 5, 2019
1 parent 9eadfe1 commit 246ae67
Show file tree
Hide file tree
Showing 33 changed files with 305 additions and 187 deletions.
4 changes: 2 additions & 2 deletions docs/dev-guide/ui-api.md
Expand Up @@ -1274,15 +1274,15 @@ 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',
label: 'org.vue.cli-service.suggestions.vue-router-add.label',
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')
}
})
}
Expand Down
11 changes: 2 additions & 9 deletions docs/guide/plugins-and-presets.md
Expand Up @@ -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
Expand Down Expand Up @@ -112,15 +105,15 @@ Here's an example preset:
``` json
{
"useConfigFiles": true,
"router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
}
},
"@vue/cli-plugin-router": {}
}
}
```
Expand Down
4 changes: 2 additions & 2 deletions docs/ru/dev-guide/ui-api.md
Expand Up @@ -1274,15 +1274,15 @@ 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',
label: 'org.vue.cli-service.suggestions.vue-router-add.label',
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')
}
})
}
Expand Down
11 changes: 2 additions & 9 deletions docs/ru/guide/plugins-and-presets.md
Expand Up @@ -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 Совет
Expand Down Expand Up @@ -112,15 +105,15 @@ vue add vuex
``` json
{
"useConfigFiles": true,
"router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
}
},
"@vue/cli-plugin-router": {}
}
}
```
Expand Down
11 changes: 2 additions & 9 deletions docs/zh/guide/plugins-and-presets.md
Expand Up @@ -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 提示
Expand Down Expand Up @@ -112,15 +105,15 @@ vue add vuex
``` json
{
"useConfigFiles": true,
"router": true,
"vuex": true,
"cssPreprocessor": "sass",
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": ["save", "commit"]
}
},
"@vue/cli-plugin-router": {}
}
}
```
Expand Down
2 changes: 2 additions & 0 deletions packages/@vue/cli-plugin-router/.npmignore
@@ -0,0 +1,2 @@
__tests__
__mocks__
9 changes: 9 additions & 0 deletions 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
```
64 changes: 64 additions & 0 deletions 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('<router-link to="/">Home</router-link>')
expect(files['src/App.vue']).not.toMatch('<script>')
expect(files['src/App.vue']).toMatch('#nav a.router-link-exact-active')

expect(pkg.dependencies).toHaveProperty('vue-router')
})

test('history mode', async () => {
const { files, pkg } = await generateWithPlugin({
id: 'router',
apply: require('../generator'),
options: {
historyMode: true
}
})

expect(files['src/router/index.js']).toBeTruthy()
expect(files['src/router/index.js']).toMatch('history')
expect(files['src/views/About.vue']).toBeTruthy()
expect(files['src/views/Home.vue']).toBeTruthy()
expect(files['src/App.vue']).toMatch('<router-link to="/">Home</router-link>')
expect(files['src/App.vue']).not.toMatch('<script>')
expect(files['src/App.vue']).toMatch('#nav a.router-link-exact-active')

expect(pkg.dependencies).toHaveProperty('vue-router')
})

test('use with Babel', async () => {
const { pkg, files } = await generateWithPlugin([
{
id: 'babel',
apply: require('@vue/cli-plugin-babel/generator'),
options: {}
},
{
id: 'router',
apply: require('../generator'),
options: {}
}
])

expect(files['src/router/index.js']).toBeTruthy()
expect(files['src/router/index.js']).toMatch('component: () => import')
expect(files['src/views/About.vue']).toBeTruthy()
expect(files['src/views/Home.vue']).toBeTruthy()
expect(files['src/App.vue']).toMatch('<router-link to="/">Home</router-link>')
expect(files['src/App.vue']).not.toMatch('<script>')
expect(files['src/App.vue']).toMatch('#nav a.router-link-exact-active')

expect(pkg.dependencies).toHaveProperty('vue-router')
})
@@ -1,34 +1,22 @@
module.exports = (api, options = {}) => {
api.assertCliVersion('^4.0.0-alpha.3')
api.assertCliServiceVersion('^4.0.0-alpha.3')

api.injectImports(api.entryFile, `import router from './router'`)
api.injectRootOptions(api.entryFile, `router`)

api.extendPackage({
dependencies: {
'vue-router': '^3.0.6'
}
})

api.render('./template', {
historyMode: options.routerHistoryMode,
historyMode: options.historyMode,
doesCompile: api.hasPlugin('babel') || api.hasPlugin('typescript')
})

if (api.invoking) {
api.postProcessFiles(files => {
const appFile = files[`src/App.vue`]
if (appFile) {
files[`src/App.vue`] = appFile.replace(/^<template>[^]+<\/script>/, `
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
`.trim())
}
})

if (api.hasPlugin('typescript')) {
/* eslint-disable-next-line node/no-extraneous-require */
const convertFiles = require('@vue/cli-plugin-typescript/generator/convert')
Expand Down
65 changes: 65 additions & 0 deletions packages/@vue/cli-plugin-router/generator/template/src/App.vue
@@ -0,0 +1,65 @@
---
extend: '@vue/cli-service/generator/template/src/App.vue'
replace:
- !!js/regexp /<template>[^]*?<\/template>/
- !!js/regexp /\n<script>[^]*?<\/script>\n/
- !!js/regexp / margin-top[^]*?<\/style>/
---
<%# REPLACE %>
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</div>
</template>
<%# END_REPLACE %>
<%# REPLACE %>
<%# END_REPLACE %>
<%# REPLACE %>
}
<%_ if (rootOptions.cssPreprocessor !== 'stylus') { _%>
<%_ if (!rootOptions.cssPreprocessor) { _%>
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
<%_ } else { _%>
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
<%_ } _%>
<%_ } else { _%>
#nav
padding 30px
a
font-weight bold
color #2c3e50
&.router-link-exact-active
color #42b983
<%_ } _%>
</style>
<%# END_REPLACE %>
@@ -0,0 +1,37 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
<%_ if (doesCompile) { _%>
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
<%_ } else { _%>
component: function () {
return import(/* webpackChunkName: "about" */ '../views/About.vue')
}
<%_ } _%>
}
]

const router = new VueRouter({
<%_ if (historyMode) { _%>
mode: 'history',
base: process.env.BASE_URL,
<%_ } _%>
routes
})

export default router
1 change: 1 addition & 0 deletions packages/@vue/cli-plugin-router/index.js
@@ -0,0 +1 @@
module.exports = (api, options = {}) => {}
31 changes: 31 additions & 0 deletions packages/@vue/cli-plugin-router/package.json
@@ -0,0 +1,31 @@
{
"name": "@vue/cli-plugin-router",
"version": "4.0.0-alpha.3",
"description": "router plugin for vue-cli",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vue-cli.git",
"directory": "packages/@vue/cli-plugin-router"
},
"keywords": [
"vue",
"cli",
"router"
],
"author": "Evan You",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vue-cli/issues"
},
"homepage": "https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-router#readme",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@vue/cli-shared-utils": "^4.0.0-alpha.3"
},
"devDependencies": {
"@vue/cli-test-utils": "^4.0.0-alpha.3"
}
}

0 comments on commit 246ae67

Please sign in to comment.