├── static └── .gitkeep ├── src ├── utils │ └── global.js ├── assets │ └── logo.png ├── App.vue ├── views │ ├── index.vue │ └── example │ │ ├── tree.vue │ │ └── table │ │ ├── index.vue │ │ ├── tableFirst.vue │ │ └── tableSecond.vue ├── styles │ └── index.css ├── main.js ├── permission.js ├── components │ ├── reLoad.vue │ ├── sideMeuns.vue │ └── layout.vue └── router │ └── index.js ├── test ├── unit │ ├── setup.js │ ├── .eslintrc │ ├── specs │ │ └── HelloWorld.spec.js │ └── jest.conf.js └── e2e │ ├── specs │ └── test.js │ ├── custom-assertions │ └── elementCount.js │ ├── nightwatch.conf.js │ └── runner.js ├── config ├── prod.env.js ├── test.env.js ├── dev.env.js └── index.js ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── index.html ├── .babelrc ├── README.md └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/global.js: -------------------------------------------------------------------------------- 1 | global.antRouter = '' //全局的路由 2 | -------------------------------------------------------------------------------- /test/unit/setup.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mrblackant/dynamicRouter-Second/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | }, 5 | "globals": { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const devEnv = require('./dev.env') 4 | 5 | module.exports = merge(devEnv, { 6 | NODE_ENV: '"testing"' 7 | }) 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 12 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | /test/unit/coverage/ 8 | /test/e2e/reports/ 9 | selenium-debug.log 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/views/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /src/views/example/tree.vue: -------------------------------------------------------------------------------- 1 | 4 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | router 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/views/example/table/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 17 | 18 | 20 | -------------------------------------------------------------------------------- /src/views/example/table/tableFirst.vue: -------------------------------------------------------------------------------- 1 | 4 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /src/views/example/table/tableSecond.vue: -------------------------------------------------------------------------------- 1 | 4 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /test/unit/specs/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import HelloWorld from '@/components/HelloWorld' 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(HelloWorld) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .toEqual('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /src/styles/index.css: -------------------------------------------------------------------------------- 1 | /*登录页*/ 2 | .form_wapper .el-form-item__label { 3 | color: #fff; 4 | 5 | } 6 | 7 | /*自定义菜单宽度、背景色*/ 8 | #app .el-submenu .el-menu-item, 9 | #app .nest-menu .el-submenu>.el-submenu__title { 10 | min-width: 180px !important; 11 | background-color: #1f2d3d !important; 12 | } 13 | 14 | #app .el-submenu .el-menu-item:hover, 15 | #app .nest-menu .el-submenu>.el-submenu__title:hover { 16 | background-color: #001528 !important; 17 | } 18 | -------------------------------------------------------------------------------- /.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 | "env": { 13 | "test": { 14 | "presets": ["env", "stage-2"], 15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import router from './router' 6 | import ElementUI from 'element-ui'; 7 | import 'element-ui/lib/theme-chalk/index.css'; 8 | import '@/utils/global'//全局 9 | // 控制路由表的js文件 10 | import '@/permission.js' 11 | Vue.config.productionTip = false 12 | Vue.use(ElementUI); 13 | 14 | /* eslint-disable no-new */ 15 | new Vue({ 16 | el: '#app', 17 | router, 18 | components: { App }, 19 | template: '' 20 | }) 21 | -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # router 2 | 3 | > vue动态菜单的实现方案 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /test/unit/jest.conf.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | rootDir: path.resolve(__dirname, '../../'), 5 | moduleFileExtensions: [ 6 | 'js', 7 | 'json', 8 | 'vue' 9 | ], 10 | moduleNameMapper: { 11 | '^@/(.*)$': '/src/$1' 12 | }, 13 | transform: { 14 | '^.+\\.js$': '/node_modules/babel-jest', 15 | '.*\\.(vue)$': '/node_modules/vue-jest' 16 | }, 17 | testPathIgnorePatterns: [ 18 | '/test/e2e' 19 | ], 20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'], 21 | setupFiles: ['/test/unit/setup'], 22 | mapCoverage: true, 23 | coverageDirectory: '/test/unit/coverage', 24 | collectCoverageFrom: [ 25 | 'src/**/*.{js,vue}', 26 | '!src/main.js', 27 | '!src/router/index.js', 28 | '!**/node_modules/**' 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // The assertion name is the filename. 3 | // Example usage: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // For more information on custom assertions see: 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | 10 | exports.assertion = function (selector, count) { 11 | this.message = 'Testing if element <' + selector + '> has count: ' + count 12 | this.expected = count 13 | this.pass = function (val) { 14 | return val === this.expected 15 | } 16 | this.value = function (res) { 17 | return res.value 18 | } 19 | this.command = function (cb) { 20 | var self = this 21 | return this.api.execute(function (selector) { 22 | return document.querySelectorAll(selector).length 23 | }, [selector], function (res) { 24 | cb.call(self, res) 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/gettingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/permission.js: -------------------------------------------------------------------------------- 1 | // 取到需要权限判断的路由表 2 | import { permissionRouter, fixedRouter } from '@/router' 3 | import router from '@/router' 4 | var addRouFlag = false 5 | 6 | router.beforeEach((to, from, next) => { 7 | // 取到用户的角色 8 | let GetRole = localStorage.getItem("userRole") 9 | 10 | // 如果登录了 11 | if (GetRole&&GetRole !== 'unload') { 12 | next() //next()方法后的代码也会执行 13 | // 1.如果路由表 没根据角色进行筛选,就筛选一次 14 | if (!addRouFlag) { 15 | addRouFlag = true 16 | // 2.根据用户的角色、和需要动态展示的路由,生成符合用户角色的路由 17 | var getRoutes = baseRoleGetRouters(permissionRouter, GetRole.split(",")) 18 | // 3.利用global属性,让渲染菜单的组件sideMeuns.vue重新生成左侧菜单 19 | global.antRouter = fixedRouter.concat(getRoutes) 20 | // 4.将生成好的路由addRoutes 21 | router.addRoutes(fixedRouter.concat(getRoutes)) 22 | // 5.push之后,会重新进入到beforeEach的钩子里,直接进入第一个if判断 23 | router.push({ path: to.path }) 24 | } 25 | } else { 26 | // 用户没登录,跳转到登录页面 27 | if (to.path === '/') { 28 | next() 29 | } else { 30 | next('/') 31 | } 32 | } 33 | 34 | }) 35 | 36 | 37 | function hasPermission(route, roles) { 38 | if (route.meta && route.meta.roles) { 39 | return roles.some(role => route.meta.roles.indexOf(role) >= 0) 40 | } else { 41 | return true 42 | } 43 | } 44 | // 根据用户的角色取到该用户对应的路由 45 | function baseRoleGetRouters(allRoutes, roles) { 46 | // allRoutes是动态路由表 47 | // roles是取到的用户角色,数组 48 | let rightRoutes = allRoutes.filter((route, index) => { 49 | if (hasPermission(route, roles)) { 50 | if (route.children && route.children.length) { 51 | route.children = baseRoleGetRouters(route.children, roles) 52 | } 53 | return true 54 | } 55 | return false 56 | }) 57 | return rightRoutes 58 | } 59 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | 4 | const webpack = require('webpack') 5 | const DevServer = require('webpack-dev-server') 6 | 7 | const webpackConfig = require('../../build/webpack.prod.conf') 8 | const devConfigPromise = require('../../build/webpack.dev.conf') 9 | 10 | let server 11 | 12 | devConfigPromise.then(devConfig => { 13 | const devServerOptions = devConfig.devServer 14 | const compiler = webpack(webpackConfig) 15 | server = new DevServer(compiler, devServerOptions) 16 | const port = devServerOptions.port 17 | const host = devServerOptions.host 18 | return server.listen(port, host) 19 | }) 20 | .then(() => { 21 | // 2. run the nightwatch test suite against it 22 | // to run in additional browsers: 23 | // 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings" 24 | // 2. add it to the --env flag below 25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 26 | // For more information on Nightwatch's config file, see 27 | // http://nightwatchjs.org/guide#settings-file 28 | let opts = process.argv.slice(2) 29 | if (opts.indexOf('--config') === -1) { 30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 31 | } 32 | if (opts.indexOf('--env') === -1) { 33 | opts = opts.concat(['--env', 'chrome']) 34 | } 35 | 36 | const spawn = require('cross-spawn') 37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 38 | 39 | runner.on('exit', function (code) { 40 | server.close() 41 | process.exit(code) 42 | }) 43 | 44 | runner.on('error', function (err) { 45 | server.close() 46 | throw err 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /src/components/reLoad.vue: -------------------------------------------------------------------------------- 1 | 19 | 51 | 52 | 79 | -------------------------------------------------------------------------------- /src/components/sideMeuns.vue: -------------------------------------------------------------------------------- 1 | 49 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | const layout = () => import('@/components/layout') 4 | // 登录页 5 | const reload = () => import('@/components/reLoad') 6 | 7 | const main = () => import('@/views/index') 8 | const table = () => import('@/views/example/table/index') 9 | const tree = () => import('@/views/example/tree') 10 | const tableFirst = () => import('@/views/example/table/tableFirst') 11 | const tableSecond = () => import('@/views/example/table/tableSecond') 12 | Vue.use(Router) 13 | // 固定的路由表 14 | export const fixedRouter = [{ 15 | path: '', 16 | component: reload, 17 | hidden: true 18 | }, 19 | { 20 | path: '', 21 | component: layout, //整体页面的布局(包含左侧菜单跟主内容区域) 22 | children: [{ 23 | path: 'main', 24 | component: main, 25 | meta: { 26 | title: '首页', //菜单名称 27 | roles: ['user', 'admin'], //当前菜单哪些角色可以看到 28 | icon: 'el-icon-info' //菜单左侧的icon图标 29 | } 30 | }] 31 | }, 32 | ] 33 | // 需要权限判断展示的路由 34 | export const permissionRouter = [{ 35 | path: "/example", 36 | component: layout, 37 | name: "Example", 38 | meta: { 39 | title: "案例", 40 | icon: "el-icon-success", 41 | roles: ['admin', 'user'] 42 | }, 43 | children: [{ 44 | path: "/example/table", 45 | name: "Table", 46 | component: table, 47 | meta: { 48 | title: "table案例", 49 | icon: "el-icon-goods", 50 | roles: ['admin'] 51 | }, 52 | // 三级菜单写法,对应demotable案例下边的两个菜单 53 | children: [{ 54 | path: "table1", 55 | name: "Table1", 56 | component: tableFirst, 57 | meta: { 58 | title: "table1", 59 | icon: "el-icon-mobile-phone", 60 | roles: ['admin'] 61 | 62 | } 63 | }, 64 | { 65 | path: "table2", 66 | name: "Table2", 67 | component: tableSecond, 68 | meta: { 69 | title: "table2", 70 | icon: "el-icon-service", 71 | roles: ['admin'] 72 | } 73 | } 74 | ] 75 | }, 76 | { 77 | path: "tree", 78 | name: "Tree", 79 | component: tree, 80 | meta: { 81 | title: "树形菜单", 82 | icon: "el-icon-upload", 83 | roles: ['user', 'admin'] 84 | } 85 | } 86 | ] 87 | }] 88 | 89 | 90 | export default new Router({ 91 | routes: fixedRouter 92 | 93 | }) 94 | -------------------------------------------------------------------------------- /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 | 7 | module.exports = { 8 | dev: { 9 | proxyTable: { 10 | '/api': { 11 | target: '192.168.8.83:80/', //接口域名  12 | changeOrigin: true, //是否跨域 13 | pathRewrite: { 14 | '^api': '' //需要rewrite重写的 15 | } 16 | } 17 | }, 18 | // Paths 19 | assetsSubDirectory: 'static', 20 | assetsPublicPath: '/', 21 | proxyTable: {}, 22 | 23 | // Various Dev Server settings 24 | host: 'localhost', // can be overwritten by process.env.HOST 25 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 26 | autoOpenBrowser: false, 27 | errorOverlay: true, 28 | notifyOnErrors: true, 29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 30 | 31 | 32 | /** 33 | * Source Maps 34 | */ 35 | 36 | // https://webpack.js.org/configuration/devtool/#development 37 | devtool: 'cheap-module-eval-source-map', 38 | 39 | // If you have problems debugging vue-files in devtools, 40 | // set this to false - it *may* help 41 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 42 | cacheBusting: true, 43 | 44 | cssSourceMap: true 45 | }, 46 | 47 | build: { 48 | // Template for index.html 49 | index: path.resolve(__dirname, '../dist/index.html'), 50 | 51 | // Paths 52 | assetsRoot: path.resolve(__dirname, '../dist'), 53 | assetsSubDirectory: 'static', 54 | assetsPublicPath: './', 55 | 56 | /** 57 | * Source Maps 58 | */ 59 | 60 | productionSourceMap: true, 61 | // https://webpack.js.org/configuration/devtool/#production 62 | devtool: '#source-map', 63 | 64 | // Gzip off by default as many popular static hosts such as 65 | // Surge or Netlify already gzip all static assets for you. 66 | // Before setting to `true`, make sure to: 67 | // npm install --save-dev compression-webpack-plugin 68 | productionGzip: false, 69 | productionGzipExtensions: ['js', 'css'], 70 | 71 | // Run the build command with an extra argument to 72 | // View the bundle analyzer report after build finishes: 73 | // `npm run build --report` 74 | // Set to `true` or `false` to always turn it on or off 75 | bundleAnalyzerReport: process.env.npm_config_report 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/components/layout.vue: -------------------------------------------------------------------------------- 1 | 26 | 59 | 60 | 96 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "router", 3 | "version": "1.0.0", 4 | "description": "vue动态菜单的实现方案", 5 | "author": "赵云 ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "unit": "jest --config test/unit/jest.conf.js --coverage", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e", 13 | "build": "node build/build.js" 14 | }, 15 | "dependencies": { 16 | "element-ui": "^2.6.2", 17 | "vue": "^2.5.2", 18 | "vue-router": "^3.0.1" 19 | }, 20 | "devDependencies": { 21 | "autoprefixer": "^7.1.2", 22 | "babel-core": "^6.22.1", 23 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 24 | "babel-jest": "^21.0.2", 25 | "babel-loader": "^7.1.1", 26 | "babel-plugin-dynamic-import-node": "^1.2.0", 27 | "babel-plugin-syntax-jsx": "^6.18.0", 28 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 29 | "babel-plugin-transform-runtime": "^6.22.0", 30 | "babel-plugin-transform-vue-jsx": "^3.5.0", 31 | "babel-preset-env": "^1.3.2", 32 | "babel-preset-stage-2": "^6.22.0", 33 | "babel-register": "^6.22.0", 34 | "chalk": "^2.0.1", 35 | "chromedriver": "^2.27.2", 36 | "copy-webpack-plugin": "^4.0.1", 37 | "cross-spawn": "^5.0.1", 38 | "css-loader": "^0.28.0", 39 | "extract-text-webpack-plugin": "^3.0.0", 40 | "file-loader": "^1.1.4", 41 | "friendly-errors-webpack-plugin": "^1.6.1", 42 | "html-webpack-plugin": "^2.30.1", 43 | "jest": "^22.0.4", 44 | "jest-serializer-vue": "^0.3.0", 45 | "nightwatch": "^0.9.12", 46 | "node-notifier": "^5.1.2", 47 | "optimize-css-assets-webpack-plugin": "^3.2.0", 48 | "ora": "^1.2.0", 49 | "portfinder": "^1.0.13", 50 | "postcss-import": "^11.0.0", 51 | "postcss-loader": "^2.0.8", 52 | "postcss-url": "^7.2.1", 53 | "rimraf": "^2.6.0", 54 | "selenium-server": "^3.0.1", 55 | "semver": "^5.3.0", 56 | "shelljs": "^0.7.6", 57 | "uglifyjs-webpack-plugin": "^1.1.1", 58 | "url-loader": "^0.5.8", 59 | "vue-jest": "^1.0.2", 60 | "vue-loader": "^13.3.0", 61 | "vue-style-loader": "^3.0.1", 62 | "vue-template-compiler": "^2.5.2", 63 | "webpack": "^3.6.0", 64 | "webpack-bundle-analyzer": "^2.9.0", 65 | "webpack-dev-server": "^2.9.1", 66 | "webpack-merge": "^4.1.0" 67 | }, 68 | "engines": { 69 | "node": ">= 6.0.0", 70 | "npm": ">= 3.0.0" 71 | }, 72 | "browserslist": [ 73 | "> 1%", 74 | "last 2 versions", 75 | "not ie <= 8" 76 | ] 77 | } 78 | --------------------------------------------------------------------------------