webpack知识点梳理

464 阅读5分钟

webpack打包构建流程

image.png 1、初始化参数:获取用户在webpack.config.js文件配置的参数

2、开始编译:初始化compiler对象,注册所有的插件plugins,插件开始监听webpack构建过程的生命周期事件,不同环节会有相应的处理,然后开始执行编译。

3、确定入口:根据webpack.config.js文件的entry入口,开始解析文件构建ast语法树,找抽依赖,递归下去。

4、编译模块:递归过程中,根据文件类型和loader配置,调用相应的loader对不同的文件做转换处理,在找出该模块依赖的模块,递归本操作,直到项目中依赖的所有模块都经过了本操作的编译处理。

5、完成编译并输出:递归结束,得到每个文件结果,包含转换后的模块以及他们之前的依赖关系,根据entry以及output等配置生成代码块chunk

6、打包完成:根据output输出所有的chunk到相应的文件目录。

loader

直译为"加载器"。Webpack将⼀切⽂件视为模块,但是webpack原⽣是只能解析js⽂件,如果想将其他⽂件也打包的话,就会⽤到 loader 。 所以Loader的作⽤是让webpack拥有了加载和解析⾮js的能力。

webpack4

image.png

webpack5

image.png

常见loader

file-loader: 把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件

url-loader: 和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去

source-map-loader: 加载额外的 Source Map 文件,以方便断点调试

image-loader: 加载并且压缩图片文件

babel-loader:把ES6 转换成 ES5

css-loader: 加载 CSS,支持模块化、压缩、文件导入等特性

style-loader: 把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS

eslint-loader: 通过 ESLint 检查 JavaScript 代码

pulgins

直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运⾏的⽣命周期中会⼴播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

define-plugin: 定义环境变量

html-webpack-plugin: 简化html文件创建

uglifyjs-webpack-plugin: 通过 UglifyES 压缩 ES6 代码

webpack-parallel-uglify-plugin: 多核压缩,提高压缩速度

webpack-bundle-analyzer: 可视化webpack输出文件的体积

mini-css-extract-plugin: CSS提取到单独的文件中,支持按需加载

copy-webpack-plugin:打包时将文件完整复制

打包/构建优化措施

image.png 多线程打包: HappyPack:HappyPack.ThreadPool({ size: os.cpus().length });

性能:performance:可以控制 webpack 如何通知「资源(asset)和入口起点超过指定文件限制」

优化:optimization: {splitChunks: } all async initial

webpack分析

image.png

二次开发Webpack

image.png 实现Css的TreeShaking:purgecss-webpack-plugin

扩展日期格式:antd-dayjs-webpack-plugin

分析打包后的文件大小和依赖关系: BundleAnalyzerPlugin

压缩css: optimize-css-assets-webpack-plugin

压缩js:terser-webpack-plugin

webpack 4 版本 : optimization: { minimizer: new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin()}

webpack 5版本 css-minimizer-webpack-plugin

开启gzip压缩:compression-webpack-plugin

如何提高webpack的构建速度?

多入口情况下,使用 CommonsChunkPlugin 来提取公共代码

通过 externals 配置来提取常用库

利用 DIPlugin 和 DlIReferencelugin 预编译资源模块 通过 DIPugin 来对那些我们用但是绝对不会修改的npm包来进行预编译,再通过DIIReferencePlugin 将预编译的模块加载进来

使用 Happypack 实现多线程加速编译

使用 webpack-uglify-parallel 来提升 uglifyPlugin 的压缩速度,原理上 webpack-uglify-parallel 采用了多核并行压缩来提升压缩速度

使用 Tree-shaking 和 Scope Hoisting 来别除多余代码

怎么配置单页应用? 怎么配置多页应用?

单页应用可以理解为webpack的标准模式,直接在 entry 中指定单页应用的入口即可,这里不再整述多页应用的话,可以使用webpack的AutoWebPlugin 来完成简单自动化的构建,但是前提是项目的目录结构必须遵守他预设的规范,多页应用中要注意的是:每个页面都有公共的代码,可以将这些代码抽离出来,避免重复的加载。比如,每个页面都引用了同一套CSS样式表,随着业务的不断扩展,页面可能会不断的追加,所以一定要让入口的配置足够灵活,避免每次添加新页面还需要修改构建配置

如何提高webpack的打包速度?

happypack: 利用进程开行编译l0ader利用缓存来便得 rebuld 更快,遗愿的是作者表示已经不会继续开发此项目 类似的替代者是thread-loader

外部扩展(externals): 将不怎么需要更新的第三方库脱离webpack打包,不被打入bundle中,从而减少打包时间,比如Quev用script标签引入

dIl: 采用webpack的 DlIPlugin 和 DIReferencePlugin 引入d,让一些基本不会改动的代码先打包成静态资源,避免反复编译浪费时间

利用缓存: webpack.cache、babel-loader,.cacheDirectory、 HappyPack,cache 都可以利用缓存提高rebuild效率缩小文件搜索范围:比如babeloader插件如果你的文件仅存在于src中,那么可以 indude: path.resolve dimamesrc),当然大多数情况下这种操作的提升有限,除非不心build了node_modules文件