├── .browserslistrc ├── babel.config.js ├── public └── favicon.ico ├── postcss.config.js ├── src ├── assets │ └── logo.png ├── pages │ ├── index │ │ ├── App.vue │ │ ├── index.js │ │ ├── views │ │ │ └── index.vue │ │ ├── router.js │ │ └── index.html │ ├── page1 │ │ ├── index.js │ │ ├── views │ │ │ ├── page1-2.vue │ │ │ └── page1-1.vue │ │ ├── App.vue │ │ ├── router.js │ │ └── index.html │ └── page2 │ │ ├── index.js │ │ ├── views │ │ ├── page2-2.vue │ │ └── page2-1.vue │ │ ├── App.vue │ │ ├── router.js │ │ └── index.html └── components │ └── HelloWorld.vue ├── .gitignore ├── .eslintrc.js ├── vue.config.js ├── package.json └── README.md /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/app"] 3 | }; 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcddblue/multi-pages/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gcddblue/multi-pages/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/pages/index/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/pages/index/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | 5 | Vue.config.productionTip = false 6 | 7 | new Vue({ 8 | router, 9 | render: h => h(App) 10 | }).$mount('#app') 11 | -------------------------------------------------------------------------------- /src/pages/page1/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | 5 | Vue.config.productionTip = false 6 | 7 | new Vue({ 8 | router, 9 | render: h => h(App) 10 | }).$mount('#app') 11 | -------------------------------------------------------------------------------- /src/pages/page1/views/page1-2.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/pages/page2/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | 5 | Vue.config.productionTip = false 6 | 7 | new Vue({ 8 | router, 9 | render: h => h(App) 10 | }).$mount('#app') 11 | -------------------------------------------------------------------------------- /src/pages/page2/views/page2-2.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/pages/page2/views/page2-1.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/pages/page1/views/page1-1.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/pages/index/views/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/pages/page2/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/pages/page1/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /src/pages/index/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import home from './views/index.vue' 4 | 5 | Vue.use(Router) 6 | 7 | export default new Router({ 8 | routes: [ 9 | { 10 | path: '/', 11 | name: 'home', 12 | component: home 13 | } 14 | ] 15 | }) 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: ['plugin:vue/essential', '@vue/prettier'], 7 | rules: { 8 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 9 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 10 | 'prettier/prettier': [ 11 | 'error', 12 | { 13 | semi: false, 14 | singleQuote: true 15 | } 16 | ] 17 | }, 18 | parserOptions: { 19 | parser: 'babel-eslint' 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const glob = require('glob') 2 | 3 | function getEntry(url) { 4 | let entrys = {} 5 | glob.sync(url).forEach(item => { 6 | // splice(-3)取数组后三项 7 | let urlArr = item.split('/').splice(-3) 8 | entrys[urlArr[1]] = { 9 | entry: 'src/pages/' + urlArr[1] + '/' + 'index.js', 10 | template: 'src/pages/' + urlArr[1] + '/' + 'index.html', 11 | filename: urlArr[1] + '.html', 12 | title: 'pages-' + urlArr[1] 13 | } 14 | }) 15 | return entrys 16 | } 17 | let pages = getEntry('./src/pages/**?/*.html') 18 | module.exports = { 19 | pages 20 | } 21 | -------------------------------------------------------------------------------- /src/pages/page1/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | Vue.use(Router) 5 | 6 | export default new Router({ 7 | routes: [ 8 | { 9 | path: '/', 10 | name: 'home', 11 | component: () => import('./views/page1-1.vue') 12 | }, 13 | { 14 | path: '/page1-2', 15 | // route level code-splitting 16 | // this generates a separate chunk (about.[hash].js) for this route 17 | // which is lazy-loaded when the route is visited. 18 | component: () => 19 | import(/* webpackChunkName: "about" */ './views/page1-2.vue') 20 | } 21 | ] 22 | }) 23 | -------------------------------------------------------------------------------- /src/pages/page2/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | Vue.use(Router) 5 | 6 | export default new Router({ 7 | routes: [ 8 | { 9 | path: '/', 10 | name: 'home', 11 | component: () => import('./views/page2-1.vue') 12 | }, 13 | { 14 | path: '/page2-2', 15 | // route level code-splitting 16 | // this generates a separate chunk (about.[hash].js) for this route 17 | // which is lazy-loaded when the route is visited. 18 | component: () => 19 | import(/* webpackChunkName: "about" */ './views/page2-2.vue') 20 | } 21 | ] 22 | }) 23 | -------------------------------------------------------------------------------- /src/pages/index/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | multi-index 9 | 10 | 11 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/pages/page1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | multi-page1 9 | 10 | 11 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/pages/page2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | multi-page2 9 | 10 | 11 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "multi-pages", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^2.6.5", 12 | "vue": "^2.6.10", 13 | "vue-router": "^3.0.3" 14 | }, 15 | "devDependencies": { 16 | "@vue/cli-plugin-babel": "^3.11.0", 17 | "@vue/cli-plugin-eslint": "^3.11.0", 18 | "@vue/cli-service": "^3.11.0", 19 | "@vue/eslint-config-prettier": "^5.0.0", 20 | "babel-eslint": "^10.0.1", 21 | "eslint": "^5.16.0", 22 | "eslint-plugin-prettier": "^3.1.0", 23 | "eslint-plugin-vue": "^5.0.0", 24 | "glob": "^7.1.4", 25 | "prettier": "^1.18.2", 26 | "sass": "^1.18.0", 27 | "sass-loader": "^7.1.0", 28 | "vue-template-compiler": "^2.6.10" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 使用vue cli3配置多页项目 2 | 3 | > 我们在使用vue cli3脚手架构建页面时,大多都是单页应用(这其中的优势我就不多说了),但是在某些场景,我们需要构建多页应用,例如我们我们应用中有很多小型h5页面,或者多种活动页,这些页面互相之间没有什么关联,如果每个活动页面都构建一个应用,那也是不切实际的,所以我们需要使用vue脚手架构建多页应用,其中在vue-cli2.x版本配置多页需要修改的地方还是挺繁琐,不过好在cli3版本增加了pages属性,配置起来相当轻松。 4 | > 5 | > 项目源码地址 [multi-pages](https://github.com/gcddblue/multi-pages) 6 | 7 | #### 创建多页应用 8 | 9 | 首先 `vue create multi-pages` 初始化名为 `multi-pages` 的项目,我们删除views文件夹,新建一个名为`pages` 的文件夹,并创建 `index` 、 `page1` 、 `page2` 文件夹如下: 10 | 11 | ![](https://user-gold-cdn.xitu.io/2019/8/29/16cdc4199efe157d?w=261&h=658&f=png&s=25445) 12 | 13 | 这里index代表了项目首页,page1、page2在这里可以理解为需要构建的其他页面,我们可以在各自的页面文件下创建属于他们的入口文件index.js(相当于单页应用的main.js) router路由、组件components、vuex、axios等等,我们就把他们每个理解为独立的单页应用。 14 | 15 | #### 配置vue.config.js 16 | 17 | 在项目中创建 `vue.config.js` 文件来配置我们的多页应用。话不多说,整干货: 18 | 19 | ``` 20 | const glob = require('glob') 21 | 22 | function getEntry(url) { 23 | let entrys = {} 24 | glob.sync(url).forEach(item => { 25 | // splice(-3)取数组后三项 26 | let urlArr = item.split('/').splice(-3) 27 | entrys[urlArr[1]] = { 28 | entry: 'src/pages/' + urlArr[1] + '/' + 'index.js', 29 | template: 'src/pages/' + urlArr[1] + '/' + 'index.html', 30 | filename: urlArr[1] + '.html', 31 | title: 'pages-' + urlArr[1] 32 | } 33 | }) 34 | return entrys 35 | } 36 | let pages = getEntry('./src/pages/**?/*.html') 37 | module.exports = { 38 | pages 39 | } 40 | ``` 41 | 42 | 这里主要用到 `glob` 模块来处理多页路径,这样做的好处就是不用再pages添加后文件,再来vue.config.js中添加pages对象属性,当页面多时,这是相当繁琐的,所以我们需要借助 `glob` 模块,调用glob.sync(url)返回匹配到的路径数组,有关路径匹配规则,如下: 43 | 44 | ``` 45 | 1、* :匹配单个路径部分中的0个或多个字符。 46 | 47 |   2、?:匹配路径中某部分1个字符。 48 | 49 |   3、[...] :匹配一个字符的范围,类似于一个正则表达式的范围。如果范围的第一个字符是!或者,它匹配任何不在范围内的字符。 50 | 51 |   4、!(模式1|模式2|模式3):匹配与所提供的任何模式不匹配的任何内容。和正则表达式的!一样。 52 | 53 |   5、?(模式1|模式2|模式3):匹配所提供的模式的零或一个事件。 54 | 55 |   6、+(模式1|模式2|模式3):匹配所提供的模式的一个或多个事件。 56 | 57 |   7、*(a|b|c) :匹配所提供的模式的零个或多个事件。 58 | 59 |   8、@(pattern|pat*|pat?erN):匹配所提供的模式之一。 60 | 61 |   9、**:如果**在一个路径的部分,他会匹配零个或多个目录和子目录中搜索匹配。 62 | ``` 63 | 64 | 更多 [glob相关介绍请点击查看](https://www.cnblogs.com/waitforyou/p/7044171.html) 65 | 66 | 运行 `npm run serve` 输入 `http:localhost:8080` 跑动程序: 67 | 68 | 69 | 70 | ![](https://user-gold-cdn.xitu.io/2019/8/29/16cdc43b3639f7bc?w=1540&h=490&f=png&s=24196) 71 | 72 | 点击page1 、page2 都会重新请求刷新页面,最后 `npm run build` 打包程序: 73 | 74 | ![](https://user-gold-cdn.xitu.io/2019/8/29/16cdc40bbe6bc2d2?w=268&h=351&f=png&s=11594) 75 | 76 | 至此vue cli3多页面配置就简单实现了,大家可以依照这个例子,在实际项目中构建更多功能! 77 | 78 | > 想学习并实践开发vue项目的同学,可以关注我的个人后台管理spa页面,项目地址 [vue-admin-webapp](https://github.com/gcddblue/vue-admin-webapp) 欢迎star,fork 79 | 80 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 88 | 89 | 97 | 98 | 99 | 115 | --------------------------------------------------------------------------------