💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# webpack优化 https://blog.csdn.net/u014399368/article/details/100095919 - 总结 - 优化构建速度--【缩小文件的搜索范围、DllPlugin减少基础模块编译次数、HappyPack开启多进程Loader转换、ParallelUglifyPlugin开启多进程压缩JS文件】 - 优化输出质量【加速网络请求-CDN】 - 优化开发体验【sourceMap--productionSourceMap: false,、DevServer刷新浏览器】 - CSS抽离和压缩 - 压缩 js 文件【UglifyJS插件和ParallelUglifyPlugin】 - 压缩 HTML【HtmlWebpackPlugin插件】 - tree shaking【摇树--清除无用css,js、usedExports、sideEffects】 - 优化图片【image-webpack-loader,压缩图片】 - 打包文件分析工具【webpack-bundle-analyzer】 ## 优化构建速度 - 缩小文件的搜索范围 > - * resolve字段告诉webpack怎么去搜索文件 > * resolve.modules告诉webpack去哪些目录下寻找第三方模块,默认值为['node_modules'] > * 对庞大的第三方模块设置resolve.alias > * module.noParse字段告诉Webpack不必解析哪些文件 - 使用DllPlugin减少基础模块编译次数 > - * DllPlugin动态链接库插件,其原理是把网页依赖的基础模块抽离出来打包到dll文件中,当需要导入的模块存在于某个dll中时,这个模块不再被打包,而是去dll中获取。**为什么会提升构建速度呢?**原因在于dll中大多包含的是常用的第三方模块,如react、react-dom,所以只要这些模块版本不升级,就只需被编译一次。 - 使用HappyPack开启多进程Loader转换 > - * 在整个构建流程中,最耗时的就是Loader对文件的转换操作了,而运行在Node.js之上的Webpack是单线程模型的,也就是只能一个一个文件进行处理,不能并行处理。HappyPack可以将任务分解给多个子进程,最后将结果发给主进程。JS是单线程模型,只能通过这种多进程的方式提高性能。 - 使用ParallelUglifyPlugin开启多进程压缩JS文件 > - - 先将代码解析成Object表示的AST(抽象语法树),再去应用各种规则去分析和处理AST,所以这个过程计算量大耗时较多。ParallelUglifyPlugin可以开启多个子进程,每个子进程使用UglifyJS压缩代码,可以并行执行 ## 优化输出质量--加速网络请求 - HTML文件:放在自己的服务器上且关闭缓存,不接入CDN - 静态的JS、CSS、图片等资源:开启CDN和缓存,同时文件名带上由内容计算出的Hash值,这样只要内容变化hash就会变化,文件名就会变化,就会被重新下载而不论缓存时间多长。 ## 优化开发体验 - 开发环境打开,sourceMap 定位到源代码; - * DevServer刷新浏览器 * DevServer刷新浏览器有两种方式: > 向网页中注入代理客户端代码,通过客户端发起刷新-- devserver: {inline:true} > 向网页装入一个iframe,通过刷新iframe实现刷新效果 ## CSS抽离和压缩 - 抽离、压缩CSS 单独生成的 css 文件可以和 js 文件并行下载 * * MiniCssExtractPlugin -- 抽离css为独立文件输出 `new MiniCssExtractPlugin({filename: "css/[name]_[contenthash:6].css"}) ` 或者 使用 extract-text-webpack-plugin 插件将css文件分离出来 * * css 文件的压缩 optimize-css-assets-webpack-plugin 插件来压缩 css,其默认使用的压缩引擎是 cssnano; cssnano基于PostCSS,不仅是删掉空格,还能理解代码含义,例如把color:#ff0000 转换成 color:red,css-loader内置了cssnano,只需要使用 css-loader?minimize 就可以开启cssnano压缩。 另外一种压缩CSS方式是使用PurifyCSSPlugin,需要配合 extract-text-webpack-plugin 使用,它主要的作用是可以去除没有用到的CSS代码,类似JS的Tree Shaking。 ## 压缩 js 文件 Webpack内置UglifyJS插件、ParallelUglifyPlugin,会分析JS代码语法树,理解代码的含义,从而做到去掉无效代码、去掉日志输入代码、缩短变量名等优化。 ```js const UglifyJSPlugin = require('webpack/lib/optimize/UglifyJsPlugin'); plugins: [ new UglifyJSPlugin({ compress: { warnings: false, //删除无用代码时不输出警告 drop_console: true, //删除所有console语句,可以兼容IE collapse_vars: true, //内嵌已定义但只使用一次的变量 reduce_vars: true, //提取使用多次但没定义的静态值到变量 }, output:{beautify:false,comments:false} //最紧凑输出-不保留空格和制表符;删除注释 }) ] ``` 使用webpack --optimize-minimize 启动webpack,可以注入默认配置的UglifyJSPlugin 第三方的uglify-webpack-plugin提供了压缩ES6代码的功能, 另外要防止babel-loader转换ES6代码,要在.babelrc中去掉babel-preset-env,因为正是babel-preset-env负责把ES6转换为ES5 。 ## 压缩 HTML 使用HtmlWebpackPlugin插件来生成HTML的模板时候,通过配置属性minify进行html优化 ```js module.exports = { ... plugin:[ new HtmlwebpackPlugin({ ... minify:{ minifyCSS: false, // 是否压缩css collapseWhitespace: false, // 是否折叠空格, 删除空白符与换行符 removeComments: true // 是否移除注释 } }) ] } ``` ## tree shaking: 摇树,清除无用css,js(Dead Code) 它正常工作的前提是代码必须采用ES6的模块化语法 在webpack实现Trss shaking有两种不同的方案: > usedExports:通过标记某些函数是否被使用,之后通过Terser来进行优化的 > sideEffects:跳过整个模块/文件,直接查看该文件是否有副作用 CSS Tree Shaking -- PurifyCSSPlugin ## 优化图片--- image-webpack-loader 使用 url-loader 优化,将小图片转化成base64压缩,防止小图片太多请求次数太多。 ```js module: { rules: [ { test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: { name: '[name]_[hash].[ext]', outputPath: 'images/' } }, // 优化小图片过多造成请求数太多--如果图片小于8192 bytes就直接 base64内置到模板 { loader: 'url-loader', options: { limit: 8192, outputPath: 'img/' } } { loader: 'image-webpack-loader', options: { mozjpeg: { progressive: true, quality: 65 }, // 压缩 jpeg 的配置 // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭 optipng: { enabled: false }, pngquant: { quality: '65-90', speed: 4 }, // 使用imagemin-pngquant压缩 png gifsicle: { interlaced: false, }, // 压缩 gif 的配置 webp: { quality: 75 } // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式 } } ] }, ] } ``` ## 其他Tips > - 配置babel-loader时,use: [‘babel-loader?cacheDirectory’] cacheDirectory用于缓存babel的编译结果,加快重新编译的速度。另外注意排除node_modules文件夹,因为文件都使用了ES5的语法,没必要再使用Babel转换。 > >- 配置externals,排除因为已使用`<script>`标签引入而不用打包的代码,noParse是排除没使用模块化语句的代码。使⽤externals优化cdn静态资源 > > 配置performance参数可以输出文件的性能检查配置。 > > 配置profile:true,是否捕捉Webpack构建的性能信息,用于分析是什么原因导致构建性能不佳。 > > 配置cache:true,是否启用缓存来提升构建速度。 > > 可以使用url-loader把小图片转换成base64嵌入到JS或CSS中,减少加载次数。 > > 通过imagemin-webpack-plugin压缩图片,通过webpack-spritesmith制作雪碧图。 > > 开发环境下将devtool设置为cheap-module-eval-source-map,因为生成这种source map的速度最快,能加速构建。在生产环境下将devtool设置为hidden-source-map > > 打包文件分析工具---webpack-bundle-analyzer # 以前整理 ## 如何利用webpack来优化前端性能? 用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效。 - **压缩代码**。 删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css 使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度----多核并行压缩来提升压缩速度 - **利用CDN加速**。 在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径 - **删除死代码(Tree Shaking)**。 将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数--optimize-minimize来实现 - **提取公共代码** `提取公共第三⽅库`: SplitChunksPlugin插件来进⾏公共模块抽取,利⽤浏览器缓存可以⻓期缓存这些⽆需频繁变动的公共代码 通过externals配置来提取常用库 多入口情况下,使用CommonsChunkPlugin来提取公共代码 - **Code Splitting** `Code Splitting`: 将代码按路由维度或者组件分块(chunk),这样做到按需加载,同时可以充分利⽤浏览器缓存 ## treeShaking机制的原理 * treeShaking 也叫`摇树优化`,是一种通过移除多于代码,来优化打包体积的,`生产环境默认开启`。 * 可以在`代码不运行`的状态下,分析出`不需要的代码`; * 利用`es6模块`的规范 * ES6 Module引入进行`静态分析`,故而`编译的时候正确判断到底加载了那些模块` * 静态分析程序流,判断那些模块和变量未被使用或者引用,进而删除对应代码 ## 使用vue-cli的2.8.x版本生成的webpack项目 ![](https://img.kancloud.cn/fb/fd/fbfdc4aff1ff5700687e519df3f54c03_278x334.png) * 配置webpack编译入口 * 配置webpack输出路径、名称和静态文件路径 * 配置不同模块的处理规则与命名规则 ~~~js var path = require('path') var utils = require('./utils') var config = require('../config') var vueLoaderConfig = require('./vue-loader.conf') // 获取根目录 function resolve(dir) { return path.join(__dirname, '..', dir) } module.exports = { // 定义入口文件 entry: { app: './src/main.js' }, output: { // 输出路径 path: config.build.assetsRoot, // 输出文件名称(name为entry中定义的key值) filename: '[name].js', // 静态资源路径(判断目前所处的环境) // 在开发环境下,路径为根目录 // 在生产环境下,路径为根目录下的static文件夹 publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, resolve: { // 自动解析拓展,可以在引用文件的时候不用写后缀 extensions: ['.js', '.vue', '.json'], // 配置别名,避免在结构嵌套过深的情况下出现../../../../xxx这种写法 alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src') } }, module: { // 配置不同模块处理规则 rules: [{ test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, { test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test')] }, { // 对于图片资源,当文件体积小于10kb时,将其生成为base64,直接插入html中 // 当大于10kb时,将图片名称进行按照命名规则进行更改 test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, { // 字体资源打包规则,与图片资源相同 test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } }] } } ~~~ # [vue-cli3中vue.config.js配置](https://segmentfault.com/a/1190000019319980) 在使用vue-cli3创建项目后,因为webpack的配置均被隐藏了,当你需要覆盖原有的配置时,则需要在项目的根目录下,新建vue.config.js文件,来配置新的配置。 * vue.config.js会被自动加载 ``` ~~~ module.exports = { /* 部署生产环境和开发环境下的URL:可对当前环境进行区分,baseUrl 从 Vue CLI 3.3 起已弃用,要使用publicPath */ /* baseUrl: process.env.NODE_ENV === 'production' ? './' : '/' */ publicPath: process.env.NODE_ENV === 'production' ? '/public/' : './', /* 输出文件目录:在npm run build时,生成文件的目录名称 */ outputDir: 'dist', /* 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录 */ assetsDir: "assets", /* 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度 */ productionSourceMap: false, /* 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变) */ filenameHashing: false, /* 代码保存时进行eslint检测 */ lintOnSave: true, /* webpack-dev-server 相关配置 */ devServer: { /* 自动打开浏览器 */ open: true, /* 设置为0.0.0.0则所有的地址均能访问 */ host: '0.0.0.0', port: 8066, https: false, hotOnly: false, /* 使用代理 */ proxy: { '/api': { /* 目标代理服务器地址 */ target: 'http://47.100.47.3/', /* 允许跨域 */ changeOrigin: true, }, }, }, } ~~~ ```