├── src └── .gitkeep ├── tpl └── .gitkeep ├── static └── .gitkeep ├── pageConfig ├── entry.js ├── removePage.js └── addPage.js ├── .eslintignore ├── .gitignore ├── config ├── prod.env.js ├── dev.env.js └── index.js ├── .editorconfig ├── .babelrc ├── .eslintrc.js ├── README.md └── package.json /src/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tpl/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pageConfig/entry.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | /dist/ 3 | npm-debug.log* 4 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /pageConfig/removePage.js: -------------------------------------------------------------------------------- 1 | 2 | const fs = require('fs') 3 | const path = require('path') 4 | const cp = require('child_process') 5 | const pathName = path.resolve(__dirname, 'entry.js') 6 | const pageName = process.argv[2] 7 | let entry = require('./entry.js') 8 | 9 | // 删除入口文件配置项 10 | entry[pageName] = null 11 | let res = `module.exports = { \n` 12 | Object.keys(entry).forEach(key => { 13 | if (entry[key]) { 14 | res += `\t${key}: './src/${key}/${key}.js',\n` 15 | } 16 | }) 17 | fs.writeFileSync(pathName, res + '}') 18 | 19 | // 删除页面目录, 包括router、pages、.vue和.js等 20 | cp.spawn('rm', ['-rf', `./src/${pageName}`]) 21 | 22 | // 删除模版html 23 | fs.unlinkSync(`./tpl/${pageName}.html`) -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // https://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parserOptions: { 6 | parser: 'babel-eslint' 7 | }, 8 | env: { 9 | browser: true, 10 | }, 11 | extends: [ 12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention 13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 14 | 'plugin:vue/essential', 15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md 16 | 'standard' 17 | ], 18 | // required to lint *.vue files 19 | plugins: [ 20 | 'vue' 21 | ], 22 | // add your custom rules here 23 | rules: { 24 | // allow async-await 25 | 'generator-star-spacing': 'off', 26 | // allow debugger during development 27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 28 | 'semi': 0 //关闭分号检查 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## multiPage-vue-cli 2 | ### 基于vue2和vue-cli2搭建的vue多页面应用脚手架,可自动生成webpack配置、模板html、入口js文件以及根组件、支持自定义中间件。在多页面需求比较多、需要频繁迭代、新增一级页面的场景中可以快速搭建应用雏形。 3 | ------------------- 4 | 5 | ### 1.用法: 6 | 7 | #### 1.安装依赖 8 | > `npm install` 9 | 10 | #### 2.生成一个一级page 11 | > `npm run add ${pageName}` 12 | 13 | #### 3.生成一个一级page并支持vueRouter 14 | > `npm run add ${pageName} y` 15 | 16 | #### 4.移除一个一级page 17 | > `npm run rm ${pageName}` 18 | 19 | #### 5.本地启动 20 | > `npm start` 21 | ##### 或者 22 | > `npm run start` 23 | 24 | #### 6.构建 25 | > `npm run build` 26 | 27 | ----------------------- 28 | 29 | ### 2.本地访问: 30 | 多页面的本地访问需要在webpack的devServer中配置historyApiFallback,目前集成的path路径直接是pageName,访问地址是`localhost:8088/${pathName}`也可以根据需求修改webpack.dev.conf.js中的rewritesConfig函数来自定义。 31 | 32 | ### 3.生成的页面结构 33 | 34 | 1.没有路由 35 | `${pagename}` 36 |    `${pagename}.vue` 37 |    `${pagename}.js` 38 | 2.有路由 39 | `${pagename}` 40 |    `pages` 41 |    `router` 42 |       `index.js` 43 |    `${pagename}.vue` 44 |    `${pagename}.js` 45 | 46 | ------------------------- 47 | ### 4.注意 48 | 执行`npm start`之前确保已经存在至少一个一级page,否则报错 49 | 50 | 51 | 52 | 项目集成了postcss-px-to-viewport等插件,解决移动端适配问题,可以参考[如何在Vue项目中使用vw实现移动端适配_vw, Layout, 布局, Vue, mobile 教程](https://www.w3cplus.com/mobile/vw-layout-in-vue.html) 53 | 54 | **建议**:如果是个人项目,config/index.js的host配置建议改成本机ip,便于配合autoOpenBrowser实现浏览器自动打开以及移动端访问,localhost移动端是无法访问的。如果是团队项目,建议改成0.0.0.0,便于团队中每个个人在移动端使用本机ip访问。 55 | -------------------------------------------------------------------------------- /pageConfig/addPage.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | const path = require('path') 4 | 5 | const pathName = path.resolve(__dirname, 'entry.js') 6 | 7 | const pageName = process.argv[2] 8 | 9 | const needRouter = process.argv[3] 10 | 11 | let entry = require('./entry.js') 12 | 13 | entry[pageName] = true 14 | 15 | // 生成入口文件 16 | let res = `module.exports = { \n` 17 | Object.keys(entry).forEach(key => { 18 | res += `\t${key}: './src/${key}/${key}.js',\n` 19 | }) 20 | fs.writeFileSync(pathName, res + '}') 21 | 22 | 23 | // 生成模板文件 24 | fs.writeFileSync(`./tpl/${pageName}.html`, ` 25 | 26 | 27 | 28 | 29 | 30 | ${pageName} 31 | 32 | 33 |
34 | 35 | 36 | 37 | `) 38 | 39 | // 生成入口文件目录 40 | fs.mkdirSync('./src/' + pageName) 41 | 42 | // 生成入口vue文件 43 | fs.writeFileSync(`./src/${pageName}/${pageName}.vue`, ` 44 | 51 | 52 | 57 | 58 | 61 | `) 62 | 63 | // 生成入口js文件 64 | fs.writeFileSync(`./src/${pageName}/${pageName}.js`, ` 65 | import Vue from 'vue' 66 | import App from './${pageName}.vue' 67 | ${needRouter === 'y' ? "import router from './router' " : ''} 68 | require('viewport-units-buggyfill').init(); 69 | 70 | Vue.config.productionTip = false; 71 | 72 | new Vue({ 73 | el: '#app', 74 | ${needRouter === 'y' ? 'router,' : ''} 75 | components: {App}, 76 | template: '' 77 | }) 78 | `) 79 | // 生成router配置文件 80 | const writeRouter = () => { 81 | fs.writeFileSync(`./src/${pageName}/router/index.js`, ` 82 | import Vue from 'vue' 83 | import Router from 'vue-router' 84 | 85 | Vue.use(Router) 86 | const router = new Router({ 87 | routes: [{ 88 | 89 | }] 90 | }) 91 | export default router 92 | `) 93 | } 94 | 95 | if (needRouter === 'y') { 96 | // 生成pages和router目录 97 | fs.mkdirSync(`./src/${pageName}/pages`) 98 | fs.mkdir(`./src/${pageName}/router`, (err, data) => { 99 | if (!err) { 100 | writeRouter() 101 | } 102 | }) 103 | } -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | const entry = require('../pageConfig/entry') 7 | let buildPath = {} 8 | Object.keys(entry).forEach(key => { 9 | buildPath[key] = path.resolve(__dirname, `../dist/${key}.html`) 10 | }) 11 | module.exports = { 12 | dev: { 13 | 14 | // Paths 15 | assetsSubDirectory: 'static', 16 | assetsPublicPath: '/', 17 | proxyTable: {}, 18 | 19 | // Various Dev Server settings 20 | host: 'localhost', // can be overwritten by process.env.HOST 21 | port: 8088, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 22 | autoOpenBrowser: false, 23 | errorOverlay: true, 24 | notifyOnErrors: true, 25 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 26 | 27 | // Use Eslint Loader? 28 | // If true, your code will be linted during bundling and 29 | // linting errors and warnings will be shown in the console. 30 | useEslint: true, 31 | // If true, eslint errors and warnings will also be shown in the error overlay 32 | // in the browser. 33 | showEslintErrorsInOverlay: false, 34 | 35 | /** 36 | * Source Maps 37 | */ 38 | 39 | // https://webpack.js.org/configuration/devtool/#development 40 | devtool: 'cheap-module-eval-source-map', 41 | 42 | // If you have problems debugging vue-files in devtools, 43 | // set this to false - it *may* help 44 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 45 | cacheBusting: true, 46 | 47 | cssSourceMap: true 48 | }, 49 | 50 | build: { 51 | // Template for index.html 52 | ...buildPath, 53 | 54 | // Paths 55 | assetsRoot: path.resolve(__dirname, '../dist'), 56 | assetsSubDirectory: 'static', 57 | assetsPublicPath: '/', 58 | 59 | /** 60 | * Source Maps 61 | */ 62 | 63 | productionSourceMap: true, 64 | // https://webpack.js.org/configuration/devtool/#production 65 | devtool: '#source-map', 66 | 67 | // Gzip off by default as many popular static hosts such as 68 | // Surge or Netlify already gzip all static assets for you. 69 | // Before setting to `true`, make sure to: 70 | // npm install --save-dev compression-webpack-plugin 71 | productionGzip: false, 72 | productionGzipExtensions: ['js', 'css'], 73 | 74 | // Run the build command with an extra argument to 75 | // View the bundle analyzer report after build finishes: 76 | // `npm run build --report` 77 | // Set to `true` or `false` to always turn it on or off 78 | bundleAnalyzerReport: process.env.npm_config_report 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sharetrend_sharepage", 3 | "version": "1.0.0", 4 | "description": "A Vue.js project", 5 | "author": "Nicole ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "add": "node pageConfig/addPage.js", 11 | "rm": "node pageConfig/removePage.js", 12 | "lint": "eslint --ext .js,.vue src", 13 | "build": "node build/build.js" 14 | }, 15 | "dependencies": { 16 | "cssnano": "^3.10.0", 17 | "cssnano-preset-advanced": "^4.0.0-rc.2", 18 | "postcss-aspect-ratio-mini": "^0.0.2", 19 | "postcss-cssnext": "^3.1.0", 20 | "postcss-px-to-viewport": "^0.0.3", 21 | "postcss-viewport-units": "^0.1.4", 22 | "postcss-write-svg": "^3.0.1", 23 | "viewport-units-buggyfill": "^0.6.2", 24 | "vue": "^2.5.2", 25 | "vue-router": "^3.0.1" 26 | }, 27 | "devDependencies": { 28 | "autoprefixer": "^7.1.2", 29 | "babel-core": "^6.22.1", 30 | "babel-eslint": "^8.2.1", 31 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 32 | "babel-loader": "^7.1.1", 33 | "babel-plugin-syntax-jsx": "^6.18.0", 34 | "babel-plugin-transform-runtime": "^6.22.0", 35 | "babel-plugin-transform-vue-jsx": "^3.5.0", 36 | "babel-preset-env": "^1.3.2", 37 | "babel-preset-stage-2": "^6.22.0", 38 | "chalk": "^2.0.1", 39 | "copy-webpack-plugin": "^4.0.1", 40 | "css-loader": "^0.28.0", 41 | "eslint": "^4.15.0", 42 | "eslint-config-standard": "^10.2.1", 43 | "eslint-friendly-formatter": "^3.0.0", 44 | "eslint-loader": "^1.7.1", 45 | "eslint-plugin-import": "^2.7.0", 46 | "eslint-plugin-node": "^5.2.0", 47 | "eslint-plugin-promise": "^3.4.0", 48 | "eslint-plugin-standard": "^3.0.1", 49 | "eslint-plugin-vue": "^4.0.0", 50 | "extract-text-webpack-plugin": "^3.0.0", 51 | "file-loader": "^1.1.4", 52 | "friendly-errors-webpack-plugin": "^1.6.1", 53 | "html-webpack-plugin": "^2.30.1", 54 | "node-notifier": "^5.1.2", 55 | "optimize-css-assets-webpack-plugin": "^3.2.0", 56 | "ora": "^1.2.0", 57 | "portfinder": "^1.0.13", 58 | "postcss-import": "^11.0.0", 59 | "postcss-loader": "^2.0.8", 60 | "postcss-url": "^7.2.1", 61 | "rimraf": "^2.6.0", 62 | "semver": "^5.3.0", 63 | "shelljs": "^0.7.6", 64 | "uglifyjs-webpack-plugin": "^1.1.1", 65 | "url-loader": "^0.5.8", 66 | "vue-loader": "^13.3.0", 67 | "vue-style-loader": "^3.0.1", 68 | "vue-template-compiler": "^2.5.2", 69 | "webpack": "^3.6.0", 70 | "webpack-bundle-analyzer": "^2.9.0", 71 | "webpack-dev-server": "^2.9.1", 72 | "webpack-merge": "^4.1.0" 73 | }, 74 | "engines": { 75 | "node": ">= 6.0.0", 76 | "npm": ">= 3.0.0" 77 | }, 78 | "browserslist": [ 79 | "> 1%", 80 | "last 2 versions", 81 | "not ie <= 8" 82 | ] 83 | } 84 | --------------------------------------------------------------------------------