实现前端模块化,将多个 js,打包成一个 bundle.js (其他类型文件交由各自的 loader 处理)
1. webpack 了解吗?大概介绍一下
一种打包工具,实现前端模块化,将多个 js,打包成一个 bundle.js (其他类型文件交由各自的 loader 处理)。
其中核心概念:
entry: 定义入口 js 文件,一般单页项目定义一个,多页项目可传递数组
output: 定义输出文件的格式和目录
module: loader 定义的地方,常见的 jsx 处理用 babel-loader, vue 用 vue-loader, less 用 less-loader.(css 相对特殊,需要三个 loader 分别进行处理。各司其职,功能最小化)
plugin:
html-webpack-plugin, 在 html 文件中自动引入 js 文件
clean-webpack-plugin,在下次构建前清理上一次的打包产物
以 entry 作为入口,对代码静态分析 import 了哪些文件,通过不同的 loader 对不同后缀的文件处理,最终打包到一起。在最后的打包过程中,插件可以在适当的时机进行额外的操作。
2. loader 了解吗?常见的 loader 有哪些?
loader是从后往前执行,谁先定义后执行。
loader 本质是在 webpack 处理文件前,进行一次转换,可以是对新js语法的兼容(babel),也可以是对 css 文件的处理(css-loader, style-loader)
webpack 本身只能处理 js 文件,所以需要各种 loader 来对其他类型的文件进行处理。也正是因为 loader 机制的设定,webpack 的能力也非常便于扩展。
常见loader:
babel-loader: 实现对 es6 语法向 es5 的兼容
less-loader: 实现 .less 文件向 .css 文件的转换
css-loader: 处理 css 文件中,url, @import 这样的语法,转换成 js 可以处理的形式
style-loader: 将 css 文件,改成生成 style 标签并插入 html 中的功能
3. plugin 了解吗?常见的 plugin 有哪些?
plugin是对webpack现有功能的扩展,可以用于打包优化、文件压缩等多种目的。
常见plugin:
mini-css-extract-plugin:将项目中引入的 css 文件合并提取到一个 css 文件中,将 css 单独独立出来,可以更好的和 js 文件并行加载,提升页面性能。实际配置中,可以在开发环境使用 style-loader, 加快编译速度,而生产环境中使用 mini-css-extract-plugin,提高页面加载速度
html-webpack-plugin: 将打包出来的 js 文件,自动插入指定的 html 模版中,并生成 html 文件。可以多次使用,从而打包多个页面。
clean-webpack-plugin: 可以在打包前,清除上一次打包的产物
copy-webpack-plugin: 可以将指定目录下的文件直接复制到指定路径。一般用于处理静态资源的移动,比如图片,视频等
DefinePlugin: 可以配置全局对象,在页面 js 执行时可以直接获取。也就是在编译时,将变量注入运行时的环境。
4. loader 和 plugin 有什么区别?
plugin 具有比 loader 更大的能力:能够在 webpack 的整个编译过程中介入。
而 loader 只有处理单个文件时,会被使用。
比如 style-loader,一个 css 文件,就会插入一个 style 标签,而我们想要的 css 往往是合并成一个 .css 文件,而不是以 style 标签的形式插入。
style-loader 由于每次只能处理一个文件,所以并不具备把所有 css 文件合并的能力。
plugin 就是为了弥补这些不足而出现的,它的能力范围更大。
5. webpack 打包比较慢,为什么?有什么优化方法吗?
(1)webpack为什么打包慢?
webpack 的工作,会根据 entry 中指定的 js,一个一个加载并调用 loader 进行处理后,最终生成一个 bundle 文件。
打包慢,大概率就在于要处理的文件太多。不过现在 webpack 在文件修改后,本身就有优化,所以打包慢,一般发生在冷启动,和生产环境打包时。
(2)优化方法?
调整 loader 配置,增加 exclude,不对 node_modules 中文件进行处理,通过减少要处理的文件来减少构建时间;
增加 cache-loader,缓存之前的结果;
使用 Terser 开启多进程;
拆分项目,采用微前端的方案进行加载(把一个项目的多个页面进行拆分,通过微前端的技术将一个一个项目合并起来)。
6. webpack 有什么方法,可以使打包出来的页面性能更好?
(1)js, css 文件压缩,减少文件体积
(2)js, css 打包文件名增加 hash 值(output 中 filename 使用 [hash] 即可插入文件 hash 值),借助 http 强缓存减少加载耗时
(3)图片压缩,借助 image-webpack-loader 或者手动压缩图片后引入,减少页面资源体积
(4)tree-shaking:webpack 中开启 usedExports: true。引入的 npm 包如果支持,也会自动 shaking,无需配置
(5) 通过懒加载拆分不同路由的文件,按需加载 js
懒加载:不是在最顶部放入import,会返回一个promise。当文件被加载完成后,才会执行它的.then
7. tree-shaking 是什么?如何开启?
原理:静态代码分析
对于不是ES6语法定义的npm包可以坐tree-shaking吗?不能,开启 tree-shaking 的条件是使用 import 和 export。
本质:对代码静态分析,从入口文件开始,递归分析所有文件和他们的依赖关系。这一分析可以确定,哪些模块和模块的导出是被实际使用的。标记未使用的代码,即可在打包阶段进行移除。
webpack 中,通过配置 usedExports = true
开启 tree-shaking。
对于 npm 包中的内容,会通过 package.json 中的 sideEffects 来判断是否对其进行 tree-shaking
如果 sideEffects 为 false, 则认为该 npm 包没有副作用(修改了全局变量,执行某些初始化逻辑等),会正常进行 tree-shaking,否则不做处理。
该参数也可以指定为数组,从而对那些文件不进行 tree-shaking。
要注意,开启 tree-shaking 的条件是使用 import 和 export。如果是一些旧的 commonjs 等,是不支持 tree-shaking 的。