1、路由懒加载
在 Webpack 中,我们可以使用动态 import语法来定义代码分块点 (split point): import('./Foo.vue') // 返回 Promise 如果您使用的是 Babel,你将需要添加 syntax-dynamic-import 插件,才能使 Babel 可以正确地解析语法。 结合这两者,这就是如何定义一个能够被 Webpack 自动代码分割的异步组件。 const Foo = () => import('./Foo.vue') 在路由配置中什么都不需要改变,只需要像往常一样使用 Foo: const router = new VueRouter({ routes: [ { path: '/foo', component: Foo } ] }) 复制代码
2、服务器和webpack打包同时配置Gzip
Gzip是GNU zip的缩写,顾名思义是一种压缩技术。它将浏览器请求的文件先在服务器端进行压缩,然后传递给浏览器,浏览器解压之后再进行页面的解析工作。在服务端开启Gzip支持后,我们前端需要提供资源压缩包,通过Compression-Webpack-Plugin插件build提供压缩
// 安装插件 cnpm i --save-dev compression-webpack-plugin // 在vue-config.js 中加入 const CompressionWebpackPlugin = require('compression-webpack-plugin'); const productionGzipExtensions = ['js', 'css']; const isProduction = process.env.NODE_ENV === 'production'; ..... module.exports = { .... // 配置webpack configureWebpack: config => { if (isProduction) { // 开启gzip压缩 config.plugins.push(new CompressionWebpackPlugin({ algorithm: 'gzip', test: /\.js$|\.html$|\.json$|\.css/, threshold: 10240, minRatio: 0.8 })) } } } 复制代码
3、优化打包chunk-vendor.js文件体积过大
当我们运行项目并且打包的时候,会发现chunk-vendors.js这个文件非常大,那是因为webpack将所有的依赖全都压缩到了这个文件里面,这时我们可以将其拆分,将所有的依赖都打包成单独的js。
// 在vue-config.js 中加入 ..... module.exports = { .... // 配置webpack configureWebpack: config => { if (isProduction) { // 开启分离js config.optimization = { runtimeChunk: 'single', splitChunks: { chunks: 'all', maxInitialRequests: Infinity, minSize: 20000, cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name (module) { // get the name. E.g. node_modules/packageName/not/this/part.js // or node_modules/packageName const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1] // npm package names are URL-safe, but some servers don't like @ symbols return `npm.${packageName.replace('@', '')}` } } } } }; } } } // 至此,你会发现原先的vender文件没有了,同时多了好几个依赖的js文件 复制代码
4、启用CDN加速
用Gzip已把文件的大小减少了三分之二了,但这个还是得不到满足。那我们就把那些不太可能改动的代码或者库分离出来,继续减小单个chunk-vendors,然后通过CDN加载进行加速加载资源。
// 修改vue.config.js 分离不常用代码库 // 如果不配置webpack也可直接在index.html引入 module.exports = { configureWebpack: config => { if (isProduction) { config.externals = { 'vue': 'Vue', 'vue-router': 'VueRouter', 'moment': 'moment' } } } } // 在public文件夹的index.html 加载 <!-- CND --> <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.runtime.min.js"></script> <script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script> 复制代码
5、完整vue.config.js代码
const path = require('path') // 在vue-config.js 中加入 // 开启gzip压缩 const CompressionWebpackPlugin = require('compression-webpack-plugin'); // 判断开发环境 const isProduction = process.env.NODE_ENV === 'production'; const resolve = dir => { return path.join(__dirname, dir) } // 项目部署基础 // 默认情况下,我们假设你的应用将被部署在域的根目录下, // 例如:https://www.my-app.com/ // 默认:'/' // 如果您的应用程序部署在子路径中,则需要在这指定子路径 // 例如:https://www.foobar.com/my-app/ // 需要将它改为'/my-app/' // iview-admin线上演示打包路径: https://file.iviewui.com/admin-dist/ const BASE_URL = process.env.NODE_ENV === 'production' ? '/' : '/' module.exports = { //webpack配置 configureWebpack:config => { // 开启gzip压缩 if (isProduction) { config.plugins.push(new CompressionWebpackPlugin({ algorithm: 'gzip', test: /\.js$|\.html$|\.json$|\.css/, threshold: 10240, minRatio: 0.8 })); // 开启分离js config.optimization = { runtimeChunk: 'single', splitChunks: { chunks: 'all', maxInitialRequests: Infinity, minSize: 20000, cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name (module) { // get the name. E.g. node_modules/packageName/not/this/part.js // or node_modules/packageName const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1] // npm package names are URL-safe, but some servers don't like @ symbols return `npm.${packageName.replace('@', '')}` } } } } }; // 取消webpack警告的性能提示 config.performance = { hints:'warning', //入口起点的最大体积 maxEntrypointSize: 50000000, //生成文件的最大体积 maxAssetSize: 30000000, //只给出 js 文件的性能提示 assetFilter: function(assetFilename) { return assetFilename.endsWith('.js'); } } } }, // Project deployment base // By default we assume your app will be deployed at the root of a domain, // e.g. https://www.my-app.com/ // If your app is deployed at a sub-path, you will need to specify that // sub-path here. For example, if your app is deployed at // https://www.foobar.com/my-app/ // then change this to '/my-app/' publicPath: BASE_URL, // tweak internal webpack configuration. // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md devServer: { host: 'localhost', port: 8080, // 端口号 hotOnly: false, https: false, // https:{type:Boolean} open: true, //配置自动启动浏览器 proxy:null // 配置跨域处理,只有一个代理 }, // 如果你不需要使用eslint,把lintOnSave设为false即可 lintOnSave: true, css:{ loaderOptions:{ less:{ javascriptEnabled:true } }, extract: true,// 是否使用css分离插件 ExtractTextPlugin sourceMap: false,// 开启 CSS source maps modules: false// 启用 CSS modules for all css / pre-processor files. }, chainWebpack: config => { config.resolve.alias .set('@', resolve('src')) // key,value自行定义,比如.set('@@', resolve('src/components')) .set('@c', resolve('src/components')) }, // 打包时不生成.map文件 productionSourceMap: false // 这里写你调用接口的基础路径,来解决跨域,如果设置了代理,那你本地开发环境的axios的baseUrl要写为 '' ,即空字符串 // devServer: { // proxy: 'localhost:3000' // } }