第十五题:webpack 优化
KieSun opened this issue · comments
marked
“面试官你也太 Low 了,现在都用 Vite 了,别问了,下一题吧。”
webpack的优化方法有:cdn加速、代码压缩、tree shaking和提取公共代码等
-
提取公共代码
主要用到了webpack的commonschunkPlugin插件,可以规定从哪些chunk中提取公共代码及提取出的新chunk的名称。一般将chunk中涉及的公共基础运行库代码提取到base中,其他相同代码提取到common中。同时可以设定minChunks,minChunks=3表示如果在给定的chunks中有3个chunk中都出现了同一段代码则提取。 -
CDN加速
CDN指内容分发网络,目的是让用户能就近获取请求资源,提高用户访问系统的时间。本质是缓存,并且将数据缓存在离用户最近的地方。 -
代码压缩
使用到webpack的插件UglifyJSPlugin,
在启动webpack时使用代码:webpack --optimize-minimize
-tree shaking
基于模块间的引用关系,将不被引用或没有使用到的模块删除,模块级别,不能处理函数冗余。
没配置过,了解
-
1、使用最新的 webpack 版本。我们会经常进行性能优化。 保持最新的 Node.js 也能够保证性能。除此之外,保证你的包管理工具 (例如 npm 或者 yarn ) 为最新也能保证性能。较新的版本能够建立更高效的模块树以及提高解析速度。
-
2、将 loaders 应用于最少数的必要模块中。
-
3、使用 DllPlugin 将更改不频繁的代码进行单独编译。这将改善引用程序的编译速度,即使它增加了构建过程的复杂性。
-
4、减少编译的整体大小,以提高构建性能。尽量保持 chunks 小巧。 - 使用 更少/更小 的库。 - 在多页面应用程序中使用 CommonsChunksPlugin。 - 在多页面应用程序中以 async 模式使用 CommonsChunksPlugin 。 - 移除不使用的代码。 - 只编译你当前正在开发部分的代码。
-
5、使用 cache-loader 启用持久化缓存。使用 package.json 中的 "postinstall" 清除缓存目录。
-
6、基础包分离:使用 html-webpack-externals-plugin,将基础包通过 CDN 引入,不打入 bundle 中使用 SplitChunksPlugin 进行(公共脚本、基础包、页面公共文件)分离(Webpack4内置) ,替代了 CommonsChunkPlugin 插件
-
7、多进程/多实例构建:HappyPack(不维护了)、thread-loader
- 1: exclude
- 2: noParse 告诉webpack 可以忽略解析包的依赖
- 3: 配置alias resolve: { alias: { "@": path.resolve(__dirname, '../src') }, },
- 4: ProvidePlugin 可以让我们不用再使用某些包的时候 再去编写 import new webpack.ProvidePlugin({ identifier: 'module1', // ... });
- 5 IgnorePlugin 忽略某些包中的不必要的文件 new webpack.IgnorePlugin({ resourceRegExp: /^./locale/,contextRegExp:/moment/, }); new webpack.IgnorePlugin(/./locale/,/moment/); // import moment from 'moment' import 'monent/local/dddd.js
- 6 多进程打包 thread-loader
- 7 减小文件搜索范围
resolve: { modules: ['node_modules','src'], },
- 8 可以不用安装某些包 而是直接通过cdn的方式引入,而且再我们的模块中还可以正常通过 import导入 externals: { jquery: 'jQuery', },
Webpack 性能优化
webpack 打包速度分析
- speed-measure-webpack-plugin
先从打包流程分析具体是哪里耗时
- 初始化 webpack.config.js
- loader 解析
- 搜索依赖文件
- 打包生成Chunk
耗时部分
- loader解析部分
- 搜索依赖文件
- 打包生成 Chunk
缩短 loader解析时间
- rules 规则优化,include 指定目录 exclude 排除掉不需要使用的内容
- 多进程加速loader解析时间 happy-pack好像已经没有再维护了 thread-loader 可以使用 thread-loader 预热 warnup
- 加缓存 cache-loader,babel-loader 自带缓存配置的也可以使用具体参考文档
- cache-loader 缓存流程 cache-loader 和 thread-loader 优先级是 thread-loader 更高
缩短搜索依赖文件的时间
- resolve.module
- resolve.alias
- resolve.extension
缩短打包时间
- 缓存生成 chunk
- 使用 SplitChunksPlugin 分包 移除未使用代码 具体配置看 Webpack SplitChunkPlugin
- webpack-bundle-analyzer 分析包大小,那些公共的引用模块可以提出来
其他方式
- DLL
- noParse
- IgnorePlugin
- DLL 预先编译 第一次打包的时候预先编译好 第三方库的代码 如果不升级的话下次打包也不会打包他(DLL配置不方便,不推荐使用,Webpack4使用帮助已经不大了)
- noParse 指不需要 Webpack指定的模块 不需要编译的模块(不存在任何模块化语法在其中 没有 required 没有 import)
- IgnorePlugin 忽略大型包里引用的东西,大型包的模块化加载,需要引入的时候再进行引用 (在使用 moment 包的时候 会用到这个技巧)
1.配置 resolve.modules
减少搜索范围
2.配置装载机的 include & exclude
减少不必要的遍历,从而减少性能损失。
对于不需要处理的目录,予以排除,从而进一步提升性能。
3.安装webpack-parallel-uglify-plugin 压缩代码
减少构建时间
4.安装HappyPack 来加速代码构建
webpack性能优化
减少资源的大小
- 压缩图片大小,url-loaderfile-loader通过limit判断图片大小是否要压缩,进行不同的配置,小的图片转换成Base64位
- 参数mode,平时开发选择develpment,production 模式下 webpack 会对代码进行优化,如减小代码体积,删除只在开发环境用到的代码。
- 使用es6 模块,进行树摇(tree shaking){presets: ['es2015']}
- 提取公共模块 SplitChunksPlugin
文件缓存(让未修改的文件使用缓存,提高打包效率)
- webpack⽂件指纹策略:对文件名设置hash,chunkhash(同一个chunk),contenthash(针对文件内容)值,来区分不同的版本
- cache-loader/cacheDirectory:可以在一些开销大的loader上配置,用于缓存到磁盘中
- Dll缓存
缩小构建范围
- 使用resolve字段
- noParse:不依赖其他库的文件,可以直接引入不需要解析
- include,exclude:include表示可以引入的文件,exclude表示排除的文件,一些第三方模块并不需要babel-laoder,例如jquery,它本身是es5,所以可以直接排除
- oneOf 把一些文件使用特定的loader加载
多进程
- uglifyjs-webpack-plugin 多核压缩
- 使用ParallelUglifyPlugin开启多进程压缩js文件
其他
- 熟知的HMR 热模块更新
- 使用mock,解决跨域问题
- souceMap的参数配置 eval> inline> cheap
- optimization.splitChunks分包
- 检测工具 webpack-bundle-analyzer
- 基础包分离,html-webpack-externals-plugin,将一些基础包分离出来
- 使用clean-webpack-plugin清除dist,参数配置cleanOnceBeforeBuildPatterns 使dist⽬录下某个⽂件不被清理
- 在文件引入模块时使用预加载 预获取
import(/* webpackPrefetch: true */ '');
import(/* webpackPreload: true */ '');
- 使用CDN加速静态资源加载
webpack优化
我主要用vuecli脚手架,内部也是用的webpack打包,从vuecli3到vuecli5,现在都有项目
为什么要优化
默认的一些配置不能满足实际生产,webpack本身定制化和插件很成熟,能实现很多功能。
自己动手实现了一些常用的优化
- 路由按需加载 分块命名 import(/* webpackChunkName:'login'*/ '../component/Login.vue');
- 利用vue cli的环境变量,区分本地开发测试/正式环境,打包测试/正式环境
- 编写node脚本实现一键部署更新
- 资源一键上传七牛云,替换html引入的资源为cdn路径
- 自定义配置打包是否预渲染,是否页面单位像素自适应(rem)
- 同一项目仓库,多入口页面
- css预处理器支持sass语法
- 根据需求添加一些、引入loader
- webpack-dev-server 处理跨域请求
- 配置optimization.minimize实现代码打包后、压缩、美化、去除日志代码等。
- 配置optimization.splitChunks实现核心代码打包不拆分,并做文件大小的拆分限制等处理。
打包体积优化
- extends:防止将import进来的包打包的bundle中,在运行时通过script引入这些依赖
- scope hosting
- tree shaking
- 公共资源压缩
- 图片压缩
- 动态polyfill
构建性能优化
- 缩小文件查找范围
- loader中配置include/exclude
- resolve中的alias、extensions、modules、mainFiels
- modules中的nopase 忽略部分非模块化模块的递归解析
- 使用高版本的node和webpack
- 开启多进程
- happyPack
- hread-loader
- parallel-webpack
- ParallelUglifyPlugin
- 分包:DLLPlugin(动态链接库)进行分包,DllReferencePlugin对manifest.json引用
- 开启缓存:支持缓存的开启缓存 比如在babel-loader中,可以通过设置cacheDirectory来开启缓存
不支持缓存的,可以使用cache-loader
强推深入浅出webpack, 感觉这个看了 webpack理论就差不多了。
http://webpack.wuhaolin.cn/
自己的话再描述一遍
- 缩小文件搜索范围 (webpack根据导入语句去找文件,然后给对应的loader处理)
- 优化loader配置。通过include进行限制
- 优化 resolve.modules。 给绝对路径 去查node-modules
- 优化resolve.mainFields 。及第三方模块入口文件配置
- resolve.alias。 导入路径映射
- resolve.extensions。 后缀尝试
- module.noParse 忽略没有采用模块化标准的库 例如 jq
- 使用 DllPlugin 动态链接库
- HappyPack 开启子进程
- ParallelUglifyPlugin ,Uglify** 压缩代码
- 热更新;自动刷新;区分环境;
- webpack 静态资源接入cdn
- Tree Shaking 把不引用的模块摇下来 这个很好玩,依赖静态模块化
- 按需加载;提取公共代码;
- 运行时效率优化:Prepack
- Scope Hoisting 作用域提升
- 其他
- 打包静态文件到云端,通过不同环境区分前缀,提交代码携带manifest.json即可
提取公共代码
CDN加速
提取公共代码
使用高版本wepack
学习参考大佬的内容
- 打包体积优化
静态资源压缩(css, js, 图片资源)
按需引入,tree shaking
提取公共代码 - 打包速度优化
文件搜索(includes,exclude, alias等的数量要适度,过多会导致文件搜索费时)
多进程打包thread-loader
- 充分利用缓存,每次打包的时候只需要打包新增或者改变的内容(
cache-loader , dll plugin
等 ),具体细节没用过。
强推深入浅出webpack, 感觉这个看了 webpack理论就差不多了。
http://webpack.wuhaolin.cn/自己的话再描述一遍
缩小文件搜索范围 (webpack根据导入语句去找文件,然后给对应的loader处理)
- 优化loader配置。通过include进行限制
- 优化 resolve.modules。 给绝对路径 去查node-modules
- 优化resolve.mainFields 。及第三方模块入口文件配置
- resolve.alias。 导入路径映射
- resolve.extensions。 后缀尝试
- module.noParse 忽略没有采用模块化标准的库 例如 jq
使用 DllPlugin 动态链接库
HappyPack 开启子进程
ParallelUglifyPlugin ,Uglify** 压缩代码
热更新;自动刷新;区分环境;
webpack 静态资源接入cdn
Tree Shaking 把不引用的模块摇下来 这个很好玩,依赖静态模块化
按需加载;提取公共代码;
运行时效率优化:Prepack
Scope Hoisting 作用域提升
其他
- 打包静态文件到云端,通过不同环境区分前缀,提交代码携带manifest.json即可
这本书好像蛮久的了 有些概念到现在Webpack 4 Webpack5 不太适用了 例如4-11 提取公共代码 是 Webpack3的概念
现在HappyPack都没人维护了,DLL也已经过时,可以看看 cache-loader thread-loader