From e414f89e271c5d2758701a35ee6ef7685f979072 Mon Sep 17 00:00:00 2001 From: guoranred <13926187239@163.com> Date: Mon, 14 Sep 2020 23:47:20 +0800 Subject: [PATCH 1/5] add nprogress --- package.json | 3 +- src/router/guards.js | 31 ++++++++++++- src/theme/default/index.less | 1 + src/theme/default/nprogress.less | 76 ++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/theme/default/nprogress.less diff --git a/package.json b/package.json index d22d1c2..2928731 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "vue-i18n": "^8.18.2", "vue-router": "^3.3.4", "vuedraggable": "^2.23.2", - "vuex": "^3.4.0" + "vuex": "^3.4.0", + "nprogress": "^0.2.0" }, "devDependencies": { "@ant-design/colors": "^4.0.1", diff --git a/src/router/guards.js b/src/router/guards.js index 4646765..72c32f6 100644 --- a/src/router/guards.js +++ b/src/router/guards.js @@ -1,7 +1,21 @@ import {hasAuthority} from '@/utils/authority-utils' import {loginIgnore} from '@/router/index' import {checkAuthorization} from '@/utils/request' +import NProgress from 'nprogress' +NProgress.configure({ showSpinner: false }) + +/** + * 前置守卫 + * @param to + * @param form + * @param next + */ +const beforeGuard = (to, from, next) => { + // start progress bar + NProgress.start() + next() +} /** * 登录守卫 * @param to @@ -14,6 +28,7 @@ const loginGuard = (to, from, next, options) => { if (!loginIgnore.includes(to) && !checkAuthorization()) { message.warning('登录已失效,请重新登录') next({path: '/login'}) + NProgress.done() } else { next() } @@ -33,6 +48,7 @@ const authorityGuard = (to, from, next, options) => { if (!hasAuthority(to, permissions, roles)) { message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`) next({path: '/403'}) + NProgress.done() } else { next() } @@ -61,7 +77,18 @@ const redirectGuard = (to, from, next, options) => { next() } +/** + * 后置守卫 + * @param to + * @param form + * @param options + */ +const afterGuard = () => { + // finish progress bar + NProgress.done() +} + export default { - beforeEach: [loginGuard, authorityGuard, redirectGuard], - afterEach: [] + beforeEach: [beforeGuard, loginGuard, authorityGuard, redirectGuard], + afterEach: [afterGuard] } diff --git a/src/theme/default/index.less b/src/theme/default/index.less index 2c13c4e..8eacd52 100644 --- a/src/theme/default/index.less +++ b/src/theme/default/index.less @@ -1,2 +1,3 @@ @import "color"; @import "style"; +@import "nprogress"; diff --git a/src/theme/default/nprogress.less b/src/theme/default/nprogress.less new file mode 100644 index 0000000..06e79c6 --- /dev/null +++ b/src/theme/default/nprogress.less @@ -0,0 +1,76 @@ +@import '~ant-design-vue/lib/style/themes/default'; + +/* Make clicks pass-through */ +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: @primary-color; + + position: fixed; + z-index: 1031; + top: 0; + left: 0; + + width: 100%; + height: 2px; +} + +/* Fancy blur effect */ +#nprogress .peg { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color; + opacity: 1.0; + + -webkit-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +/* Remove these to get rid of the spinner */ +#nprogress .spinner { + display: block; + position: fixed; + z-index: 1031; + top: 15px; + right: 15px; +} + +#nprogress .spinner-icon { + width: 18px; + height: 18px; + box-sizing: border-box; + + border: solid 2px transparent; + border-top-color: @primary-color; + border-left-color: @primary-color; + border-radius: 50%; + + -webkit-animation: nprogress-spinner 400ms linear infinite; + animation: nprogress-spinner 400ms linear infinite; +} + +.nprogress-custom-parent { + overflow: hidden; + position: relative; +} + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar { + position: absolute; +} + +@-webkit-keyframes nprogress-spinner { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes nprogress-spinner { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + From 4c7c5c1da1501814fbc07504199168878f743dc2 Mon Sep 17 00:00:00 2001 From: guoranred <13926187239@163.com> Date: Tue, 15 Sep 2020 00:02:53 +0800 Subject: [PATCH 2/5] add cdn assets --- public/index.html | 8 ++++++++ vue.config.js | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 61725f6..719a471 100644 --- a/public/index.html +++ b/public/index.html @@ -6,12 +6,20 @@ <%= htmlWebpackPlugin.options.title %> + + <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %> + + <% } %>
+ + <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %> + + <% } %> diff --git a/vue.config.js b/vue.config.js index 8277792..d009ff8 100644 --- a/vue.config.js +++ b/vue.config.js @@ -2,6 +2,33 @@ let path = require('path') const ThemeColorReplacer = require('webpack-theme-color-replacer') const {getThemeColors, modifyVars} = require('./src/utils/themeUtil') const {resolveCss} = require('./src/utils/theme-color-replacer-extend') + +const isProd = process.env.NODE_ENV === 'production' + +const assetsCDN = { + // webpack build externals + externals: { + vue: 'Vue', + 'vue-router': 'VueRouter', + vuex: 'Vuex', + axios: 'axios', + nprogress: 'NProgress', + clipboard: 'ClipboardJS', + '@antv/data-set': 'DataSet' + }, + css: [ + ], + js: [ + '//cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js', + '//cdn.jsdelivr.net/npm/vue-router@3.3.4/dist/vue-router.min.js', + '//cdn.jsdelivr.net/npm/vuex@3.4.0/dist/vuex.min.js', + '//cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js', + '//cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js', + '//cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js', + '//cdn.jsdelivr.net/npm/@antv/data-set@0.11.4/build/data-set.min.js' + ] +} + module.exports = { devServer: { // proxy: { @@ -30,16 +57,29 @@ module.exports = { resolveCss }) ) + config.externals = isProd ? assetsCDN.externals : {} }, chainWebpack: config => { // 生产环境下关闭css压缩的 colormin 项,因为此项优化与主题色替换功能冲突 - if (process.env.NODE_ENV === 'production') { + if (isProd) { config.plugin('optimize-css') .tap(args => { args[0].cssnanoOptions.preset[1].colormin = false return args }) } + config.plugin('html') + .tap(args => { + args[0].title = 'Vue Antd Admin' + return args + }) + if (isProd) { + config.plugin('html') + .tap(args => { + args[0].cdn = assetsCDN + return args + }) + } }, css: { loaderOptions: { @@ -51,7 +91,7 @@ module.exports = { } } }, - publicPath: process.env.NODE_ENV === 'production' ? '/vue-antd-admin/' : '/', + publicPath: isProd ? '/vue-antd-admin/' : '/', outputDir: 'dist', assetsDir: 'static', productionSourceMap: false From e2e92e9df9cacf1ef6939d280bf7b5903aee8ab8 Mon Sep 17 00:00:00 2001 From: guoranred <13926187239@163.com> Date: Tue, 15 Sep 2020 09:07:59 +0800 Subject: [PATCH 3/5] fix: fixed search item --- src/layouts/header/HeaderSearch.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/layouts/header/HeaderSearch.vue b/src/layouts/header/HeaderSearch.vue index ec4f116..dcc9fc1 100644 --- a/src/layouts/header/HeaderSearch.vue +++ b/src/layouts/header/HeaderSearch.vue @@ -3,6 +3,7 @@ Date: Tue, 15 Sep 2020 21:32:08 +0800 Subject: [PATCH 4/5] rename progress guard --- src/router/guards.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/router/guards.js b/src/router/guards.js index 72c32f6..c5559e4 100644 --- a/src/router/guards.js +++ b/src/router/guards.js @@ -6,16 +6,19 @@ import NProgress from 'nprogress' NProgress.configure({ showSpinner: false }) /** - * 前置守卫 + * 进度条开始 * @param to * @param form * @param next */ -const beforeGuard = (to, from, next) => { +const progressStart = (to, from, next) => { // start progress bar - NProgress.start() + if (!NProgress.isStarted()) { + NProgress.start() + } next() } + /** * 登录守卫 * @param to @@ -28,7 +31,6 @@ const loginGuard = (to, from, next, options) => { if (!loginIgnore.includes(to) && !checkAuthorization()) { message.warning('登录已失效,请重新登录') next({path: '/login'}) - NProgress.done() } else { next() } @@ -78,17 +80,17 @@ const redirectGuard = (to, from, next, options) => { } /** - * 后置守卫 + * 进度条结束 * @param to * @param form * @param options */ -const afterGuard = () => { +const progressDone = () => { // finish progress bar NProgress.done() } export default { - beforeEach: [beforeGuard, loginGuard, authorityGuard, redirectGuard], - afterEach: [afterGuard] + beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard], + afterEach: [progressDone] } From dcf65935e13cc3db417597affde3028d88bed4e2 Mon Sep 17 00:00:00 2001 From: guoranred <13926187239@163.com> Date: Tue, 22 Sep 2020 22:49:24 +0800 Subject: [PATCH 5/5] optimize production environment packaging --- babel.config.js | 10 +++++++++- package.json | 4 +++- vue.config.js | 35 +++++++++++++++++++++++++++-------- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/babel.config.js b/babel.config.js index e955840..4eb72d0 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,5 +1,13 @@ +const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) + +const plugins = [] +if (IS_PROD) { + plugins.push('transform-remove-console') +} + module.exports = { presets: [ '@vue/cli-plugin-babel/preset' - ] + ], + plugins } diff --git a/package.json b/package.json index 2928731..652e756 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,9 @@ "vue-template-compiler": "^2.6.11", "vuepress": "^1.5.2", "webpack-theme-color-replacer": "^1.3.12", - "whatwg-fetch": "^3.0.0" + "whatwg-fetch": "^3.0.0", + "compression-webpack-plugin": "^2.0.0", + "babel-plugin-transform-remove-console": "^6.9.4" }, "eslintConfig": { "root": true, diff --git a/vue.config.js b/vue.config.js index d009ff8..ba70c7d 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,8 +1,11 @@ let path = require('path') +const webpack = require('webpack') const ThemeColorReplacer = require('webpack-theme-color-replacer') const {getThemeColors, modifyVars} = require('./src/utils/themeUtil') const {resolveCss} = require('./src/utils/theme-color-replacer-extend') +const CompressionWebpackPlugin = require('compression-webpack-plugin') +const productionGzipExtensions = ['js', 'css'] const isProd = process.env.NODE_ENV === 'production' const assetsCDN = { @@ -14,7 +17,8 @@ const assetsCDN = { axios: 'axios', nprogress: 'NProgress', clipboard: 'ClipboardJS', - '@antv/data-set': 'DataSet' + '@antv/data-set': 'DataSet', + 'js-cookie': 'Cookies' }, css: [ ], @@ -25,7 +29,8 @@ const assetsCDN = { '//cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js', '//cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js', '//cdn.jsdelivr.net/npm/clipboard@2.0.6/dist/clipboard.min.js', - '//cdn.jsdelivr.net/npm/@antv/data-set@0.11.4/build/data-set.min.js' + '//cdn.jsdelivr.net/npm/@antv/data-set@0.11.4/build/data-set.min.js', + '//cdn.jsdelivr.net/npm/js-cookie@2.2.1/src/js.cookie.min.js' ] } @@ -49,6 +54,9 @@ module.exports = { }, configureWebpack: config => { config.entry.app = ["babel-polyfill", "whatwg-fetch", "./src/main.js"]; + config.performance = { + hints: false + } config.plugins.push( new ThemeColorReplacer({ fileName: 'css/theme-colors-[contenthash:8].css', @@ -57,7 +65,22 @@ module.exports = { resolveCss }) ) - config.externals = isProd ? assetsCDN.externals : {} + // Ignore all locale files of moment.js + config.plugins.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)) + // 生产环境下将资源压缩成gzip格式 + if (isProd) { + // add `CompressionWebpack` plugin to webpack plugins + config.plugins.push(new CompressionWebpackPlugin({ + algorithm: 'gzip', + test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), + threshold: 10240, + minRatio: 0.8 + })) + } + // if prod, add externals + if (isProd) { + config.externals = assetsCDN.externals + } }, chainWebpack: config => { // 生产环境下关闭css压缩的 colormin 项,因为此项优化与主题色替换功能冲突 @@ -68,11 +91,7 @@ module.exports = { return args }) } - config.plugin('html') - .tap(args => { - args[0].title = 'Vue Antd Admin' - return args - }) + // 生产环境下使用CDN if (isProd) { config.plugin('html') .tap(args => {