From 222f1c48f61cc52e24f3141200139f2a9740c278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=B1=E8=A3=A4=E8=A1=A9?= Date: Thu, 16 Aug 2018 11:08:53 +0800 Subject: [PATCH] update to webpack4.0 (#136) * dev * update * fix * refine * add ScriptExtHtmlWebpackPlugin * update * format * refine * typo * format * docs * docs --- README-zh.md | 49 ++++++----- README.md | 27 +++--- build/build.js | 26 +++--- build/check-versions.js | 24 ++++-- build/utils.js | 49 ++++++----- build/vue-loader.conf.js | 19 +---- build/webpack.base.conf.js | 17 ++-- build/webpack.dev.conf.js | 36 ++++---- build/webpack.prod.conf.js | 166 ++++++++++++++++++++++--------------- config/index.js | 15 ++-- package.json | 82 +++++++++--------- src/icons/index.js | 2 +- src/main.js | 2 +- src/utils/index.js | 17 +++- src/utils/request.js | 45 +++++----- src/utils/validate.js | 1 - src/views/404.vue | 16 +--- 17 files changed, 330 insertions(+), 263 deletions(-) diff --git a/README-zh.md b/README-zh.md index 03bc20f..92f3812 100644 --- a/README-zh.md +++ b/README-zh.md @@ -1,29 +1,32 @@ # vueAdmin-template -> 这是一个 极简的vue admin 管理后台 它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。 +> 这是一个 极简的 vue admin 管理后台 它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。 [线上地址](http://panjiachen.github.io/vueAdmin-template) ## Extra -如果你想要根据用户角色来动态生成侧边栏和router,你可以使用改分支[permission-control](https://github.com/PanJiaChen/vueAdmin-template/tree/permission-control) -  - ## 相关项目 - [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) - [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) +如果你想要根据用户角色来动态生成侧边栏和 router,你可以使用改分支[permission-control](https://github.com/PanJiaChen/vueAdmin-template/tree/permission-control) + +本项目基于`webpack4`开发,若还想使用`webpack3`开发,请使用该分支[webpack3](https://github.com/PanJiaChen/vueAdmin-template/tree/webpack3) + +## 相关项目 + +[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) + +[electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) 写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目: - - [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2) - - [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac) - - [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35) - - [手摸手,带你用vue撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56) - - [手摸手,带你封装一个vue component](https://segmentfault.com/a/1190000009090836) +- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2) +- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac) +- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35) +- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56) +- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836) ## Build Setup -``` bash - +```bash # Clone project git clone https://github.com/PanJiaChen/vueAdmin-template.git @@ -33,25 +36,28 @@ npm install # 建议不要用cnpm 安装有各种诡异的bug 可以通过如下操作解决npm速度慢的问题 npm install --registry=https://registry.npm.taobao.org -# serve with hot reload at localhost:9528 +# Serve with hot reload at localhost:9528 npm run dev -# build for production with minification +# Build for production with minification npm run build -# build for production and view the bundle analyzer report +# Build for production and view the bundle analyzer report npm run build --report ``` ## Demo + ![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif) -### Element-Ui 使用cdn教程 +### Element-Ui 使用 cdn 教程 + 首先找到 `index.html` ([根目录下](https://github.com/PanJiaChen/vueAdmin-template/blob/element-ui-cdn/index.html)) -引入 Element的css和js ,并且引入 vue 。因为 Element-Ui 是依赖 vue 的,所以必须在它之前引入 vue 。 +引入 Element 的 css 和 js ,并且引入 vue 。因为 Element-Ui 是依赖 vue 的,所以必须在它之前引入 vue 。 + +之后找到 [webpack.base.conf.js](https://github.com/PanJiaChen/vueAdmin-template/blob/element-ui-cdn/build/webpack.base.conf.js) 加入 `externals` 让 webpack 不打包 vue 和 element -之后找到 [webpack.base.conf.js](https://github.com/PanJiaChen/vueAdmin-template/blob/element-ui-cdn/build/webpack.base.conf.js) 加入 `externals` 让webpack 不打包 vue 和 element ``` externals: { vue: 'Vue', @@ -59,7 +65,7 @@ externals: { } ``` -之后还有一个小细节是如果你用了全局对象方式引入vue,就不需要 手动 `Vue.use(Vuex)` ,它会自动挂载,具体见 [issue](https://github.com/vuejs/vuex/issues/731) +之后还有一个小细节是如果你用了全局对象方式引入 vue,就不需要 手动 `Vue.use(Vuex)` ,它会自动挂载,具体见 [issue](https://github.com/vuejs/vuex/issues/731) 最终你可以使用 `npm run build --report` 查看效果 如图: @@ -70,8 +76,7 @@ externals: { **[对应分支](https://github.com/PanJiaChen/vueAdmin-template/tree/element-ui-cdn)** ## License + [MIT](https://github.com/PanJiaChen/vueAdmin-template/blob/master/LICENSE) license. Copyright (c) 2017-present PanJiaChen - - diff --git a/README.md b/README.md index 457ecc0..8b5f78b 100644 --- a/README.md +++ b/README.md @@ -8,36 +8,43 @@ ## Build Setup -``` bash - +```bash # Clone project git clone https://github.com/PanJiaChen/vueAdmin-template.git # Install dependencies npm install -# serve with hot reload at localhost:9528 +# Serve with hot reload at localhost:9528 npm run dev -# build for production with minification +# Build for production with minification npm run build -# build for production and view the bundle analyzer report +# Build for production and view the bundle analyzer report npm run build --report ``` +https://panjiachen.gitee.io/vue-element-admin-site/zh/guide/ + ## Demo + ![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif) ## Extra + If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vueAdmin-template/tree/permission-control) -## Related Project - [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) +This project is based on `webpack4` development. If you want to use `webpack3` development, please use this branch [webpack3](https://github.com/PanJiaChen/vueAdmin-template/tree/webpack3) - [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) +## Related Project + +[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) + +[electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) ### Element-Ui using cdn tutorial + First find `index.html`([root directory](https://github.com/PanJiaChen/vueAdmin-template/blob/element-ui-cdn/index.html)) Import css and js of `Element`, and then import vue. Because `Element` is vue-dependent, vue must be import before it. @@ -53,7 +60,7 @@ externals: { ``` Finally there is a small detail to pay attention to that if you import vue in global, you don't need to manually `Vue.use(Vuex)`, it will be automatically mounted, see - [issue](https://github.com/vuejs/vuex/issues/731) +[issue](https://github.com/vuejs/vuex/issues/731) And you can use `npm run build --report` to see the effect @@ -64,8 +71,8 @@ Pictured: **[Branch](https://github.com/PanJiaChen/vueAdmin-template/tree/element-ui-cdn)** - ## License + [MIT](https://github.com/PanJiaChen/vueAdmin-template/blob/master/LICENSE) license. Copyright (c) 2017-present PanJiaChen diff --git a/build/build.js b/build/build.js index 955e9de..8c6cebd 100644 --- a/build/build.js +++ b/build/build.js @@ -19,13 +19,15 @@ rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { webpack(webpackConfig, (err, stats) => { spinner.stop() if (err) throw err - process.stdout.write(stats.toString({ - colors: true, - modules: false, - children: false, - chunks: false, - chunkModules: false - }) + '\n\n') + process.stdout.write( + stats.toString({ + colors: true, + modules: false, + children: false, + chunks: false, + chunkModules: false + }) + '\n\n' + ) if (stats.hasErrors()) { console.log(chalk.red(' Build failed with errors.\n')) @@ -33,9 +35,11 @@ rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { } console.log(chalk.cyan(' Build complete.\n')) - console.log(chalk.yellow( - ' Tip: built files are meant to be served over an HTTP server.\n' + - ' Opening index.html over file:// won\'t work.\n' - )) + console.log( + chalk.yellow( + ' Tip: built files are meant to be served over an HTTP server.\n' + + " Opening index.html over file:// won't work.\n" + ) + ) }) }) diff --git a/build/check-versions.js b/build/check-versions.js index 3ef972a..c5c29e9 100644 --- a/build/check-versions.js +++ b/build/check-versions.js @@ -4,8 +4,11 @@ const semver = require('semver') const packageConfig = require('../package.json') const shell = require('shelljs') -function exec (cmd) { - return require('child_process').execSync(cmd).toString().trim() +function exec(cmd) { + return require('child_process') + .execSync(cmd) + .toString() + .trim() } const versionRequirements = [ @@ -24,23 +27,30 @@ if (shell.which('npm')) { }) } -module.exports = function () { +module.exports = function() { const warnings = [] for (let i = 0; i < versionRequirements.length; i++) { const mod = versionRequirements[i] if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { - warnings.push(mod.name + ': ' + - chalk.red(mod.currentVersion) + ' should be ' + - chalk.green(mod.versionRequirement) + warnings.push( + mod.name + + ': ' + + chalk.red(mod.currentVersion) + + ' should be ' + + chalk.green(mod.versionRequirement) ) } } if (warnings.length) { console.log('') - console.log(chalk.yellow('To use this template, you must update following to modules:')) + console.log( + chalk.yellow( + 'To use this template, you must update following to modules:' + ) + ) console.log() for (let i = 0; i < warnings.length; i++) { diff --git a/build/utils.js b/build/utils.js index e534fb0..c96d093 100644 --- a/build/utils.js +++ b/build/utils.js @@ -1,18 +1,19 @@ 'use strict' const path = require('path') const config = require('../config') -const ExtractTextPlugin = require('extract-text-webpack-plugin') +const MiniCssExtractPlugin = require('mini-css-extract-plugin') const packageConfig = require('../package.json') -exports.assetsPath = function (_path) { - const assetsSubDirectory = process.env.NODE_ENV === 'production' - ? config.build.assetsSubDirectory - : config.dev.assetsSubDirectory +exports.assetsPath = function(_path) { + const assetsSubDirectory = + process.env.NODE_ENV === 'production' + ? config.build.assetsSubDirectory + : config.dev.assetsSubDirectory return path.posix.join(assetsSubDirectory, _path) } -exports.cssLoaders = function (options) { +exports.cssLoaders = function(options) { options = options || {} const cssLoader = { @@ -30,8 +31,22 @@ exports.cssLoaders = function (options) { } // generate loader string to be used with extract text plugin - function generateLoaders (loader, loaderOptions) { - const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] + function generateLoaders(loader, loaderOptions) { + const loaders = [] + + // Extract CSS when that option is specified + // (which is the case during production build) + if (options.extract) { + loaders.push(MiniCssExtractPlugin.loader) + } else { + loaders.push('vue-style-loader') + } + + loaders.push(cssLoader) + + if (options.usePostCSS) { + loaders.push(postcssLoader) + } if (loader) { loaders.push({ @@ -42,24 +57,16 @@ exports.cssLoaders = function (options) { }) } - // Extract CSS when that option is specified - // (which is the case during production build) - if (options.extract) { - return ExtractTextPlugin.extract({ - use: loaders, - fallback: 'vue-style-loader' - }) - } else { - return ['vue-style-loader'].concat(loaders) - } + return loaders } - // https://vue-loader.vuejs.org/en/configurations/extract-css.html return { css: generateLoaders(), postcss: generateLoaders(), less: generateLoaders('less'), - sass: generateLoaders('sass', { indentedSyntax: true }), + sass: generateLoaders('sass', { + indentedSyntax: true + }), scss: generateLoaders('sass'), stylus: generateLoaders('stylus'), styl: generateLoaders('stylus') @@ -67,7 +74,7 @@ exports.cssLoaders = function (options) { } // Generate loaders for standalone style files (outside of .vue) -exports.styleLoaders = function (options) { +exports.styleLoaders = function(options) { const output = [] const loaders = exports.cssLoaders(options) diff --git a/build/vue-loader.conf.js b/build/vue-loader.conf.js index 33ed58b..5496c93 100644 --- a/build/vue-loader.conf.js +++ b/build/vue-loader.conf.js @@ -1,22 +1,5 @@ 'use strict' -const utils = require('./utils') -const config = require('../config') -const isProduction = process.env.NODE_ENV === 'production' -const sourceMapEnabled = isProduction - ? config.build.productionSourceMap - : config.dev.cssSourceMap module.exports = { - loaders: utils.cssLoaders({ - sourceMap: sourceMapEnabled, - extract: isProduction - }), - cssSourceMap: sourceMapEnabled, - cacheBusting: config.dev.cacheBusting, - transformToRequire: { - video: ['src', 'poster'], - source: 'src', - img: 'src', - image: 'xlink:href' - } + //You can set the vue-loader configuration by yourself. } diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index c7adc26..4be51b1 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -2,9 +2,10 @@ const path = require('path') const utils = require('./utils') const config = require('../config') +const { VueLoaderPlugin } = require('vue-loader') const vueLoaderConfig = require('./vue-loader.conf') -function resolve (dir) { +function resolve(dir) { return path.join(__dirname, '..', dir) } @@ -27,9 +28,10 @@ module.exports = { output: { path: config.build.assetsRoot, filename: '[name].js', - publicPath: process.env.NODE_ENV === 'production' - ? config.build.assetsPublicPath - : config.dev.assetsPublicPath + publicPath: + process.env.NODE_ENV === 'production' + ? config.build.assetsPublicPath + : config.dev.assetsPublicPath }, resolve: { extensions: ['.js', '.vue', '.json'], @@ -48,7 +50,11 @@ module.exports = { { test: /\.js$/, loader: 'babel-loader', - include: [resolve('src'), resolve('test') ,resolve('node_modules/webpack-dev-server/client')] + include: [ + resolve('src'), + resolve('test'), + resolve('node_modules/webpack-dev-server/client') + ] }, { test: /\.svg$/, @@ -85,6 +91,7 @@ module.exports = { } ] }, + plugins: [new VueLoaderPlugin()], node: { // prevent webpack from injecting useless setImmediate polyfill because Vue // source contains it (although only uses it if it's native). diff --git a/build/webpack.dev.conf.js b/build/webpack.dev.conf.js index 212d081..ec93025 100644 --- a/build/webpack.dev.conf.js +++ b/build/webpack.dev.conf.js @@ -9,7 +9,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin') const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') const portfinder = require('portfinder') -function resolve (dir) { +function resolve(dir) { return path.join(__dirname, '..', dir) } @@ -17,8 +17,12 @@ const HOST = process.env.HOST const PORT = process.env.PORT && Number(process.env.PORT) const devWebpackConfig = merge(baseWebpackConfig, { + mode: 'development', module: { - rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) + rules: utils.styleLoaders({ + sourceMap: config.dev.cssSourceMap, + usePostCSS: true + }) }, // cheap-module-eval-source-map is faster for development devtool: config.dev.devtool, @@ -39,7 +43,7 @@ const devWebpackConfig = merge(baseWebpackConfig, { proxy: config.dev.proxyTable, quiet: true, // necessary for FriendlyErrorsPlugin watchOptions: { - poll: config.dev.poll, + poll: config.dev.poll } }, plugins: [ @@ -47,8 +51,6 @@ const devWebpackConfig = merge(baseWebpackConfig, { 'process.env': require('../config/dev.env') }), new webpack.HotModuleReplacementPlugin(), - new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. - new webpack.NoEmitOnErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: 'index.html', @@ -56,7 +58,7 @@ const devWebpackConfig = merge(baseWebpackConfig, { inject: true, favicon: resolve('favicon.ico'), title: 'vue-element-admin' - }), + }) ] }) @@ -72,14 +74,20 @@ module.exports = new Promise((resolve, reject) => { devWebpackConfig.devServer.port = port // Add FriendlyErrorsPlugin - devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ - compilationSuccessInfo: { - messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], - }, - onErrors: config.dev.notifyOnErrors - ? utils.createNotifierCallback() - : undefined - })) + devWebpackConfig.plugins.push( + new FriendlyErrorsPlugin({ + compilationSuccessInfo: { + messages: [ + `Your application is running here: http://${ + devWebpackConfig.devServer.host + }:${port}` + ] + }, + onErrors: config.dev.notifyOnErrors + ? utils.createNotifierCallback() + : undefined + }) + ) resolve(devWebpackConfig) } diff --git a/build/webpack.prod.conf.js b/build/webpack.prod.conf.js index 7541838..1f5acef 100644 --- a/build/webpack.prod.conf.js +++ b/build/webpack.prod.conf.js @@ -7,17 +7,23 @@ const merge = require('webpack-merge') const baseWebpackConfig = require('./webpack.base.conf') const CopyWebpackPlugin = require('copy-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') -const ExtractTextPlugin = require('extract-text-webpack-plugin') -const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') +const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin') +const MiniCssExtractPlugin = require('mini-css-extract-plugin') +const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') const UglifyJsPlugin = require('uglifyjs-webpack-plugin') -function resolve (dir) { +function resolve(dir) { return path.join(__dirname, '..', dir) } const env = require('../config/prod.env') +// For NamedChunksPlugin +const seen = new Set() +const nameLength = 4 + const webpackConfig = merge(baseWebpackConfig, { + mode: 'production', module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, @@ -28,37 +34,18 @@ const webpackConfig = merge(baseWebpackConfig, { devtool: config.build.productionSourceMap ? config.build.devtool : false, output: { path: config.build.assetsRoot, - filename: utils.assetsPath('js/[name].[chunkhash].js'), - chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') + filename: utils.assetsPath('js/[name].[chunkhash:8].js'), + chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js') }, plugins: [ // http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack.DefinePlugin({ 'process.env': env }), - new UglifyJsPlugin({ - uglifyOptions: { - compress: { - warnings: false - } - }, - sourceMap: config.build.productionSourceMap, - parallel: true - }), // extract css into its own file - new ExtractTextPlugin({ - filename: utils.assetsPath('css/[name].[contenthash].css'), - // Setting the following option to `false` will not extract CSS from codesplit chunks. - // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. - // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 - allChunks: false, - }), - // Compress extracted CSS. We are using this plugin so that possible - // duplicated CSS from different components can be deduped. - new OptimizeCSSPlugin({ - cssProcessorOptions: config.build.productionSourceMap - ? { safe: true, map: { inline: false } } - : { safe: true } + new MiniCssExtractPlugin({ + filename: utils.assetsPath('css/[name].[contenthash:8].css'), + chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css') }), // generate dist index.html with correct asset hash for caching. // you can customize output by editing /index.html @@ -75,44 +62,34 @@ const webpackConfig = merge(baseWebpackConfig, { removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference - }, - // necessary to consistently work with multiple chunks via CommonsChunkPlugin - chunksSortMode: 'dependency' + } + // default sort mode uses toposort which cannot handle cyclic deps + // in certain cases, and in webpack 4, chunk order in HTML doesn't + // matter anyway + }), + new ScriptExtHtmlWebpackPlugin({ + //`runtime` must same as runtimeChunk name. default is `runtime` + inline: /runtime\..*\.js$/ + }), + // keep chunk.id stable when chunk has no name + new webpack.NamedChunksPlugin(chunk => { + if (chunk.name) { + return chunk.name + } + const modules = Array.from(chunk.modulesIterable) + if (modules.length > 1) { + const hash = require('hash-sum') + const joinedHash = hash(modules.map(m => m.id).join('_')) + let len = nameLength + while (seen.has(joinedHash.substr(0, len))) len++ + seen.add(joinedHash.substr(0, len)) + return `chunk-${joinedHash.substr(0, len)}` + } else { + return modules[0].id + } }), // keep module.id stable when vender modules does not change new webpack.HashedModuleIdsPlugin(), - // enable scope hoisting - new webpack.optimize.ModuleConcatenationPlugin(), - // split vendor js into its own file - new webpack.optimize.CommonsChunkPlugin({ - name: 'vendor', - minChunks (module) { - // any required modules inside node_modules are extracted to vendor - return ( - module.resource && - /\.js$/.test(module.resource) && - module.resource.indexOf( - path.join(__dirname, '../node_modules') - ) === 0 - ) - } - }), - // extract webpack runtime and module manifest to its own file in order to - // prevent vendor hash from being updated whenever app bundle is updated - new webpack.optimize.CommonsChunkPlugin({ - name: 'manifest', - minChunks: Infinity - }), - // This instance extracts shared chunks from code splitted chunks and bundles them - // in a separate chunk, similar to the vendor chunk - // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk - new webpack.optimize.CommonsChunkPlugin({ - name: 'app', - async: 'vendor-async', - children: true, - minChunks: 3 - }), - // copy custom static assets new CopyWebpackPlugin([ { @@ -121,7 +98,41 @@ const webpackConfig = merge(baseWebpackConfig, { ignore: ['.*'] } ]) - ] + ], + optimization: { + splitChunks: { + chunks: 'all', + cacheGroups: { + libs: { + name: 'chunk-libs', + test: /[\\/]node_modules[\\/]/, + priority: 10, + chunks: 'initial' // 只打包初始时依赖的第三方 + }, + elementUI: { + name: 'chunk-elementUI', // 单独将 elementUI 拆包 + priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app + test: /[\\/]node_modules[\\/]element-ui[\\/]/ + } + } + }, + runtimeChunk: 'single', + minimizer: [ + new UglifyJsPlugin({ + uglifyOptions: { + mangle: { + safari10: true + } + }, + sourceMap: config.build.productionSourceMap, + cache: true, + parallel: true + }), + // Compress extracted CSS. We are using this plugin so that possible + // duplicated CSS from different components can be deduped. + new OptimizeCSSAssetsPlugin() + ] + } }) if (config.build.productionGzip) { @@ -132,9 +143,7 @@ if (config.build.productionGzip) { asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( - '\\.(' + - config.build.productionGzipExtensions.join('|') + - ')$' + '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ), threshold: 10240, minRatio: 0.8 @@ -142,9 +151,28 @@ if (config.build.productionGzip) { ) } -if (config.build.bundleAnalyzerReport) { - const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin - webpackConfig.plugins.push(new BundleAnalyzerPlugin()) +if (config.build.generateAnalyzerReport || config.build.bundleAnalyzerReport) { + const BundleAnalyzerPlugin = require('webpack-bundle-analyzer') + .BundleAnalyzerPlugin + + if (config.build.bundleAnalyzerReport) { + webpackConfig.plugins.push( + new BundleAnalyzerPlugin({ + analyzerPort: 8080, + generateStatsFile: false + }) + ) + } + + if (config.build.generateAnalyzerReport) { + webpackConfig.plugins.push( + new BundleAnalyzerPlugin({ + analyzerMode: 'static', + reportFilename: 'bundle-report.html', + openAnalyzer: false + }) + ) + } } module.exports = webpackConfig diff --git a/config/index.js b/config/index.js index 9bf376a..615924d 100644 --- a/config/index.js +++ b/config/index.js @@ -6,7 +6,6 @@ const path = require('path') module.exports = { dev: { - // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', @@ -35,17 +34,12 @@ module.exports = { // https://webpack.js.org/configuration/devtool/#development devtool: 'cheap-source-map', - // If you have problems debugging vue-files in devtools, - // set this to false - it *may* help - // https://vue-loader.vuejs.org/en/options.html#cachebusting - cacheBusting: true, - // CSS Sourcemaps off by default because relative paths are "buggy" // with this option, according to the CSS-Loader README // (https://github.com/webpack/css-loader#sourcemaps) // In our experience, they generally work as expected, // just be aware of this issue when enabling this option. - cssSourceMap: false, + cssSourceMap: false }, build: { @@ -71,7 +65,7 @@ module.exports = { productionSourceMap: false, // https://webpack.js.org/configuration/devtool/#production - devtool: '#source-map', + devtool: 'source-map', // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. @@ -84,6 +78,9 @@ module.exports = { // View the bundle analyzer report after build finishes: // `npm run build --report` // Set to `true` or `false` to always turn it on or off - bundleAnalyzerReport: process.env.npm_config_report + bundleAnalyzerReport: process.env.npm_config_report || false, + + // `npm run build:prod --generate_report` + generateAnalyzerReport: process.env.npm_config_generate_report || false } } diff --git a/package.json b/package.json index a14328b..b800b4e 100644 --- a/package.json +++ b/package.json @@ -13,63 +13,65 @@ "test": "npm run lint" }, "dependencies": { - "axios": "0.17.1", - "element-ui": "2.3.4", + "axios": "0.18.0", + "element-ui": "2.4.6", "js-cookie": "2.2.0", "normalize.css": "7.0.0", "nprogress": "0.2.0", - "vue": "2.5.10", + "vue": "2.5.17", "vue-router": "3.0.1", "vuex": "3.0.1" }, "devDependencies": { - "autoprefixer": "7.2.3", + "autoprefixer": "8.5.0", "babel-core": "6.26.0", - "babel-eslint": "8.0.3", + "babel-eslint": "8.2.6", "babel-helper-vue-jsx-merge-props": "2.0.3", - "babel-loader": "7.1.2", + "babel-loader": "7.1.5", "babel-plugin-syntax-jsx": "6.18.0", "babel-plugin-transform-runtime": "6.23.0", - "babel-plugin-transform-vue-jsx": "3.5.0", - "babel-preset-env": "1.6.1", + "babel-plugin-transform-vue-jsx": "3.7.0", + "babel-preset-env": "1.7.0", "babel-preset-stage-2": "6.24.1", - "chalk": "2.3.0", - "copy-webpack-plugin": "4.2.3", - "css-loader": "0.28.7", - "eslint": "4.13.1", - "eslint-friendly-formatter": "3.0.0", - "eslint-loader": "1.9.0", - "eslint-plugin-html": "4.0.1", + "chalk": "2.4.1", + "copy-webpack-plugin": "4.5.2", + "css-loader": "1.0.0", + "eslint": "4.19.1", + "eslint-friendly-formatter": "4.0.1", + "eslint-loader": "2.0.0", + "eslint-plugin-html": "4.0.5", "eventsource-polyfill": "0.9.6", - "extract-text-webpack-plugin": "3.0.2", - "file-loader": "1.1.5", - "friendly-errors-webpack-plugin": "1.6.1", - "html-webpack-plugin": "2.30.1", - "node-notifier": "5.1.2", + "file-loader": "1.1.11", + "friendly-errors-webpack-plugin": "1.7.0", + "html-webpack-plugin": "^4.0.0-alpha", + "mini-css-extract-plugin": "0.4.1", + "node-notifier": "5.2.1", "node-sass": "^4.7.2", - "optimize-css-assets-webpack-plugin": "3.2.0", - "ora": "1.3.0", - "portfinder": "1.0.13", - "postcss-import": "11.0.0", - "postcss-loader": "2.0.9", - "postcss-url": "7.3.0", + "optimize-css-assets-webpack-plugin": "5.0.0", + "ora": "3.0.0", + "portfinder": "1.0.16", + "postcss-import": "12.0.0", + "postcss-loader": "2.1.6", + "postcss-url": "7.3.2", "rimraf": "2.6.2", - "sass-loader": "6.0.6", - "semver": "5.4.1", - "shelljs": "0.7.8", - "svg-sprite-loader": "3.5.2", - "uglifyjs-webpack-plugin": "1.1.3", - "url-loader": "0.6.2", - "vue-loader": "13.7.2", - "vue-style-loader": "3.0.3", - "vue-template-compiler": "2.5.10", - "webpack": "3.10.0", - "webpack-bundle-analyzer": "2.9.1", - "webpack-dev-server": "2.9.7", - "webpack-merge": "4.1.1" + "sass-loader": "7.0.3", + "script-ext-html-webpack-plugin": "2.0.1", + "semver": "5.5.0", + "shelljs": "0.8.2", + "svg-sprite-loader": "3.8.0", + "uglifyjs-webpack-plugin": "1.2.7", + "url-loader": "1.0.1", + "vue-loader": "15.3.0", + "vue-style-loader": "4.1.2", + "vue-template-compiler": "2.5.17", + "webpack": "4.16.5", + "webpack-bundle-analyzer": "2.13.1", + "webpack-cli": "3.1.0", + "webpack-dev-server": "3.1.5", + "webpack-merge": "4.1.4" }, "engines": { - "node": ">= 4.0.0", + "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": [ diff --git a/src/icons/index.js b/src/icons/index.js index 14e2e13..d9fe4d8 100644 --- a/src/icons/index.js +++ b/src/icons/index.js @@ -1,5 +1,5 @@ import Vue from 'vue' -import SvgIcon from '@/components/SvgIcon'// svg组件 +import SvgIcon from '@/components/SvgIcon' // svg组件 // register globally Vue.component('svg-icon', SvgIcon) diff --git a/src/main.js b/src/main.js index c04fdeb..1a38d20 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,6 @@ import Vue from 'vue' -import 'normalize.css/normalize.css'// A modern alternative to CSS resets +import 'normalize.css/normalize.css' // A modern alternative to CSS resets import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' diff --git a/src/utils/index.js b/src/utils/index.js index 9657c9c..93d4974 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -25,7 +25,7 @@ export function parseTime(time, cFormat) { } const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { let value = formatObj[key] - if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1] + if (key === 'a') { return ['一', '二', '三', '四', '五', '六', '日'][value - 1] } if (result.length > 0 && value < 10) { value = '0' + value } @@ -43,7 +43,8 @@ export function formatTime(time, option) { if (diff < 30) { return '刚刚' - } else if (diff < 3600) { // less 1 hour + } else if (diff < 3600) { + // less 1 hour return Math.ceil(diff / 60) + '分钟前' } else if (diff < 3600 * 24) { return Math.ceil(diff / 3600) + '小时前' @@ -53,6 +54,16 @@ export function formatTime(time, option) { if (option) { return parseTime(time, option) } else { - return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分' + return ( + d.getMonth() + + 1 + + '月' + + d.getDate() + + '日' + + d.getHours() + + '时' + + d.getMinutes() + + '分' + ) } } diff --git a/src/utils/request.js b/src/utils/request.js index 10f12db..50d423a 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -10,23 +10,26 @@ const service = axios.create({ }) // request拦截器 -service.interceptors.request.use(config => { - if (store.getters.token) { - config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 +service.interceptors.request.use( + config => { + if (store.getters.token) { + config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + } + return config + }, + error => { + // Do something with request error + console.log(error) // for debug + Promise.reject(error) } - return config -}, error => { - // Do something with request error - console.log(error) // for debug - Promise.reject(error) -}) +) // respone拦截器 service.interceptors.response.use( response => { - /** - * code为非20000是抛错 可结合自己业务进行修改 - */ + /** + * code为非20000是抛错 可结合自己业务进行修改 + */ const res = response.data if (res.code !== 20000) { Message({ @@ -37,13 +40,17 @@ service.interceptors.response.use( // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了; if (res.code === 50008 || res.code === 50012 || res.code === 50014) { - MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', { - confirmButtonText: '重新登录', - cancelButtonText: '取消', - type: 'warning' - }).then(() => { + MessageBox.confirm( + '你已被登出,可以取消继续留在该页面,或者重新登录', + '确定登出', + { + confirmButtonText: '重新登录', + cancelButtonText: '取消', + type: 'warning' + } + ).then(() => { store.dispatch('FedLogOut').then(() => { - location.reload()// 为了重新实例化vue-router对象 避免bug + location.reload() // 为了重新实例化vue-router对象 避免bug }) }) } @@ -53,7 +60,7 @@ service.interceptors.response.use( } }, error => { - console.log('err' + error)// for debug + console.log('err' + error) // for debug Message({ message: error.message, type: 'error', diff --git a/src/utils/validate.js b/src/utils/validate.js index 834a8dd..e110310 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -30,4 +30,3 @@ export function validatAlphabets(str) { const reg = /^[A-Za-z]+$/ return reg.test(str) } - diff --git a/src/views/404.vue b/src/views/404.vue index dccf573..97e57b2 100644 --- a/src/views/404.vue +++ b/src/views/404.vue @@ -2,10 +2,10 @@
- 404 - 404 - 404 - 404 + 404 + 404 + 404 + 404
OOPS!
@@ -21,17 +21,9 @@