线上项目 欢迎STAR
前言
项目中使用到的库 vue element-ui vuex echarts vue-router
正常main.js中引入 基本都是1mb往上了, 如果网络环境不好,那基本就是卡个好几秒才能打开。
经过搜索学习 总结出当前的一套打包配置。基本秒开,完美上线。
如过您看出有什么不足,请私信或者评论提出。
先看效果
再上代码
vue.config.js
'use strict'
const path = require('path')
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i
function resolve(dir) {
return path.join(__dirname, dir)
}
// 输出 vue.config.js 配置 vue inspect --mode production > output.js
let _env = {}
if (process.env.NODE_ENV === 'production') {
_env = {
'vue': 'Vue',
'vuex': 'Vuex',
'vue-router': 'VueRouter',
'echarts': 'echarts',
'element-ui': 'ELEMENT'
}
}
module.exports = {
// build时构建文件的目录 构建时传入 --no-clean 可关闭该行为
outputDir: 'dist',
// build时放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
assetsDir: 'static',
// 指定生成的 index.html 的输出路径 (相对于 outputDir)。也可以是一个绝对路径
publicPath: '/',
// 默认在生成的静态资源文件名中包含hash以控制缓存
filenameHashing: true,
// 构建多页时使用
pages: undefined,
// eslint-loader是否在保存的时候检查
lintOnSave: true,
// 是否使用包含运行时编译器的Vue核心的构建
runtimeCompiler: false,
// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
productionSourceMap: false,
// webpack-dev-server 相关配置
devServer: {
// ...
},
chainWebpack: (config) => {
// 修复HMR
config.resolve.symlinks(true)
// 如果使用多页面打包,使用vue inspect --plugins查看html是否在结果数组中
config.resolve.alias
.set('@', resolve('src'))
if (process.env.NODE_ENV === 'production') {
// 开启打包压缩
config.plugin('CompressionWebpackPlugin')
.use(new CompressionWebpackPlugin({
filename: '[path][base].gz',
algorithm: 'gzip',
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false
}))
// 选择打包模板
config.plugin('html').tap(args => {
// 修复 Lazy loading routes Error
args[0].template = resolve('templates') + '\\index.prod.html'
args[0].chunksSortMode = 'none'
console.log('当前打包模板=> ' + args[0].template)
return args
})
} else {
config.plugin('html').tap(args => {
// 修复 Lazy loading routes Error
args[0].template = resolve('templates') + '\\index.dev.html'
args[0].chunksSortMode = 'none'
console.log('当前打包模板=> ' + args[0].template)
return args
})
}
},
configureWebpack: {
name: 'loading',
externals: _env
},
// 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来
css: {
// 启用 CSS modules
requireModuleExtension: false,
// 是否使用css分离插件
extract: true,
// 开启 CSS source maps?
sourceMap: false,
// css预设器配置项
loaderOptions: {
postcss: {
plugins: [
require('precss'),
require('autoprefixer'),
require('postcss-flexibility')
]
}
}
},
// 第三方插件配置
pluginOptions: {
// ...
}
}
pageage.json
{
"dependencies": {
"@babel/polyfill": "7.10.4",
"axios": "0.19.2",
"vuex": "3.1.0",
"vue": "2.6.11",
"vue-router": "3.0.2",
"echarts": "4.2.1",
"element-ui": "2.13.2",
"core-js": "3.6.5"
},
"devDependencies": {
"@babel/cli": "7.10.5",
"@babel/core": "7.10.5",
"@babel/preset-env": "7.10.4",
"@vue/cli-plugin-babel": "4.4.0",
"@vue/cli-plugin-eslint": "4.4.0",
"@vue/cli-service": "4.4.0",
"autoprefixer": "9.8.5",
"babel-eslint": "10.1.0",
"babel-plugin-import": "1.13.0",
"compression-webpack-plugin": "6.0.5",
"eslint": "6.7.2",
"eslint-plugin-vue": "6.2.2",
"node-sass": "4.14.1",
"postcss": "7.0.32",
"postcss-flexibility": "2.0.0",
"precss": "4.0.0",
"qs": "6.9.4",
"sass-loader": "9.0.2",
"style-loader": "1.2.1",
"vue-template-compiler": "2.6.11",
"webpack-dev-server": "2.6.1"
}
}
src/main.js
import Vue from 'vue'
import router from './router'
import store from './store'
import App from './App.vue'
import ELEMENT from 'element-ui'
const Echarts = require('echarts')
if (process.env.NODE_ENV === 'development') {
require('element-ui/lib/theme-chalk/index.css')
}
Vue.config.productionTip = false
Vue.use(ELEMENT)
Vue.prototype.echarts = Echarts
路由 src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '@/store/index.js'
if (process.env.NODE_ENV === 'development') {
Vue.use(VueRouter)
}
...
VUEX src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
if (process.env.NODE_ENV === 'development') {
Vue.use(Vuex)
}
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
export default store
.env.development
ENV = 'development'
.env.production
ENV = 'production'
打包模板
开发模板 templates index.dev.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<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>
<!-- built files will be auto injected -->
<script type="text/javascript">
if(!window.console){
window.console={
log:function(msg){},
err:function(msg){}
}
}
</script>
</body>
</html>
打包模板 templates index.prod.html
使用cdn来分发,最好是有自己的服务器或者使用稳定的cdn服务商
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="//cdn.bootcss.com/element-ui/2.14.0/theme-chalk/index.css">
</head>
<body>
<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>
<!-- built files will be auto injected -->
<script type="text/javascript">
if(!window.console){
window.console={
log:function(msg){},
err:function(msg){}
}
}
</script>
<script src="//cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script src="//cdn.bootcss.com/element-ui/2.14.0/index.min.js"></script>
<script src="//cdn.bootcss.com/vuex/3.1.0/vuex.min.js"></script>
<script src="//cdn.bootcss.com/echarts/4.8.0/echarts.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
</body>
</html>
遇到相关的问题
- compression-webpack-plugin
注意版本
filename: '[path][base].gz',不同版本是不一样的写法
6.0 以下会有如下警告
Conflict: Multiple assets emit different content to the same filename static/js/.gz
- requireModuleExtension: false
vue-cli的更新警告
WARN "css.modules" option in vue.config.js is deprecated now, please use "css.requireModuleExtension" instead.
- productionSourceMap: false
设置为 false 不生成map文件
- 版本号 一定要跟cdn完全一致