参考[webpack构建流程 - 掘金 (juejin.cn)]
webpack的构建流程
-
初始化参数。获取用户在webpack.config.js文件配置的参数
-
开始编译。初始化compiler对象,注册所有的插件plugins,插件开始监听webpack构建过程的生命周期事件,不同环节会有相应的处理,然后开始执行编译。
-
确定入口。根据webpack.config.js文件的entry入口,开始解析文件构建ast语法树,找到依赖,递归下去。
-
编译模块。递归过程中,根据文件类型和loader配置,调用相应的loader对不同的文件做转换处理,在找出该模块依赖的模块,递归本操作,直到项目中依赖的所有模块都经过了本操作的编译处理。
-
完成编译并输出。递归结束,得到每个文件结果,包含转换后的模块以及他们之前的依赖关系,根据entry以及output等配置生成代码块chunk
-
打包完成。根据output输出所有的chunk到相应的文件目录
plugins和loader的区别
关于这个问题,首先要会到webpack定义loader、plugin的定义:
loader:loader让webpack去处理那些非JavaScript文件(webpack自身只理解javascript)。loader可以将所有类型的文件转换成webpack能处理的有效模块。然后利用webpack的打包能力,对它们进行处理。
plugin:插件可以用于执行其他范围更广的任务,插件的范围包括,打包优化,代码压缩,甚至可以重新定义环境中的变量。插件的目的是用于解决loader无法实现的其他事。
首先要了解loader是将非javascript文件转换为webpack能处理的有效模块,那么loader是一个输入资源转换输出的过程。
- loader.js需要到导出一个函数,这个函数对加载的资源进行处理
- 函数输入为加载到的资源,输出为加工的资源
- 输出的结果有两种形式:第一就是输出为标准的JS代码,让打包结果可以正常执行,第二就是输出的结果交给下一个loader继续执行
- 开发好的loader.js配置到webpack.config.js下面的module.rules
webpack常用loader
- bable-loader , babel-loader基于babel,用于解析JavaScript文件。babel有丰富的预设和插件,babel的配置可以直接写到options里或者单独写到配置文件里。
- ts-loader , 用来打包编译Typescript;
- file-loader, 用于处理文件类型资源,如jpg,png等图片。返回值为publicPath为准
- url-loader: 它与file-loader作用相似,也是处理图片的,只不过url-loader可以设置一个根据图片大小进行不同的操作,如果该图片大小大于指定的大小,则将图片进行打包资源,否则将图片转换为base64字符串合并到js文件里。
- style-loader 通过注入标签将CSS插入到DOM中;
- css-loader , 仅处理css的各种加载语法。
- postcss-loader,PostCSS 是一个允许使用 JS 插件转换样式的工具。
- less-loader。
webpack常用plugin
-
html-webpack-plugin,基本作用是生成html文件
-
clean-webpack-plugin,默认情况下,这个插件会删除webpack的output.path中的所有文件,以及每次成功重新构建后所有未使用的资源。
-
mini-css-extract-plugin, 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件。
-
webpack.HotModuleReplacementPlugin
-
webpack-bundle-analyzer,可以看到项目各模块的大小,可以按需优化。
webpack的分包策略
- 按需加载:使用像 import() 这样的动态导入语法,可以实现加载代码的按需异步加载。
- 公共代码分离:使用 SplitChunksPlugin,可以把公共模块单独提取出来,防止重复加载。
- 页面级代码分割:使用 entry 配置多入口,然后抽取公共部分,可以实现每个页面只加载它需要的代码。
- 动态导入分包:使用 include/exclude 规则,使得 node_modules 中的模块按需进行代码分割。
- 组件级代码分割:结合 React.lazy 和 Suspense,可以将页面拆分为多个组件级的代码块。
- Hash 分割:通过配置 output.filename 进行 hash 分割,可以做到文件缓存优化。
- CDN 分割:把一些静态资源分别部署到不同的 CDN 上,实现资源并行加载。
- 路由级代码分割:基于路由进行代码分割,每个路由只加载对应的组件。