Merge pull request #123 from guoranred/master
add nprogress and cdn assets
| | |
| | | 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 |
| | | } |
| | |
| | | "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", |
| | |
| | | "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, |
| | |
| | | <meta name="viewport" content="width=device-width,initial-scale=1.0"> |
| | | <link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
| | | <title><%= htmlWebpackPlugin.options.title %></title> |
| | | <!-- require cdn assets css --> |
| | | <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %> |
| | | <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" /> |
| | | <% } %> |
| | | </head> |
| | | <body class="beauty-scroll"> |
| | | <noscript> |
| | | <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> |
| | | </noscript> |
| | | <div id="app"></div> |
| | | <!-- require cdn assets js --> |
| | | <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %> |
| | | <script type="text/javascript" src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> |
| | | <% } %> |
| | | <!-- built files will be auto injected --> |
| | | </body> |
| | | </html> |
| | |
| | | <a-icon type="search" class="search-icon" @click="enterSearchMode"/> |
| | | <a-auto-complete |
| | | ref="input" |
| | | :getPopupContainer="e => {return e.parentNode || document.body}" |
| | | :dataSource="dataSource" |
| | | :class="['search-input', searchMode ? 'enter' : 'leave']" |
| | | placeholder="站内搜索" |
| | |
| | | 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 progressStart = (to, from, next) => { |
| | | // start progress bar |
| | | if (!NProgress.isStarted()) { |
| | | NProgress.start() |
| | | } |
| | | next() |
| | | } |
| | | |
| | | /** |
| | | * 登录守卫 |
| | |
| | | if (!hasAuthority(to, permissions, roles)) { |
| | | message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`) |
| | | next({path: '/403'}) |
| | | NProgress.done() |
| | | } else { |
| | | next() |
| | | } |
| | |
| | | next() |
| | | } |
| | | |
| | | /** |
| | | * 进度条结束 |
| | | * @param to |
| | | * @param form |
| | | * @param options |
| | | */ |
| | | const progressDone = () => { |
| | | // finish progress bar |
| | | NProgress.done() |
| | | } |
| | | |
| | | export default { |
| | | beforeEach: [loginGuard, authorityGuard, redirectGuard], |
| | | afterEach: [] |
| | | beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard], |
| | | afterEach: [progressDone] |
| | | } |
| | |
| | | @import "color"; |
| | | @import "style"; |
| | | @import "nprogress"; |
New file |
| | |
| | | @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); } |
| | | } |
| | | |
| | |
| | | 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 = { |
| | | // webpack build externals |
| | | externals: { |
| | | vue: 'Vue', |
| | | 'vue-router': 'VueRouter', |
| | | vuex: 'Vuex', |
| | | axios: 'axios', |
| | | nprogress: 'NProgress', |
| | | clipboard: 'ClipboardJS', |
| | | '@antv/data-set': 'DataSet', |
| | | 'js-cookie': 'Cookies' |
| | | }, |
| | | 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', |
| | | '//cdn.jsdelivr.net/npm/js-cookie@2.2.1/src/js.cookie.min.js' |
| | | ] |
| | | } |
| | | |
| | | module.exports = { |
| | | devServer: { |
| | | // proxy: { |
| | |
| | | }, |
| | | 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', |
| | |
| | | resolveCss |
| | | }) |
| | | ) |
| | | // 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 项,因为此项优化与主题色替换功能冲突 |
| | | if (process.env.NODE_ENV === 'production') { |
| | | if (isProd) { |
| | | config.plugin('optimize-css') |
| | | .tap(args => { |
| | | args[0].cssnanoOptions.preset[1].colormin = false |
| | | return args |
| | | }) |
| | | } |
| | | // 生产环境下使用CDN |
| | | if (isProd) { |
| | | config.plugin('html') |
| | | .tap(args => { |
| | | args[0].cdn = assetsCDN |
| | | return args |
| | | }) |
| | | } |
| | | }, |
| | | css: { |
| | |
| | | } |
| | | } |
| | | }, |
| | | publicPath: process.env.NODE_ENV === 'production' ? '/vue-antd-admin/' : '/', |
| | | publicPath: isProd ? '/vue-antd-admin/' : '/', |
| | | outputDir: 'dist', |
| | | assetsDir: 'static', |
| | | productionSourceMap: false |