前言
各位同学看到这里,就表明《重学webpack系列》
已经更新完毕
,这个系列我们一起探讨了一下webpack的核心机制
,包括前端模块化
的演变历史、webpack
所能解决的问题、loader
、plugin
、devServer
、sourceMap
、hotModuleReplace
、webpack
的运行机制、高级特性
与框架
的结合使用。这一章我们主要是来讲一下关于webpack
的常见面试题
与个人的后期创作目标
,还是那句话,欢迎点赞
、关注
,一溪之石感谢各位。
常见的面试题
一、在项目中让你配置一下Webpack,你应该注意什么?
针对这个问题,关于Webpack的基本配置无疑就是需要mode
、devtool
、entry
、output
、module
、plugin
、devServer
几个配置项,mode
能够告知Webpack
以成熟的预设去帮助打包,entry
告知Webpack
打包入口是什么文件,output
告知Webpack
打包输出到哪里,loader
、plugin
为加载非js
文件,Webpack
的工程化构建流程提供一套最佳的解决方案,devServer
为本地开发提供一个服务器,用于提高开发效率,详见重学webpack系列(零) -- 全局概况,我们还可以配置sourceMap
、HMR
来帮助我们提高开发效率。
二、关于mode的三种预设,你觉得他们之间有什么不同呢?
关于mode
,Webpack
提供了三种预设,分别为:none
、development
、production
。
none
:不会启用Webpack
的任何优化插件,基本上不使用。development
:自动优化
打包速度,启用内置插件
更好的捕捉错误
,便于代码调试
。production
:启动内置插件
优化打包结果,不过打包速度偏慢
,便于生产模式访问效率
三、你对loader了解多少,你们常用哪些loader呢,如果让你手写一个loader你有什么想法呢?
loader
作为Webpack
集成的对非js资源加载、Webpack
工程化中功能处理的模块,我们项目中常见于对样式、图片、文字、音频、字体等文件的加载、对代码兼容、缓存等功能的支持所需要的loader
如下。
style-loader
:用于生成一个style
标签,把css
引入到页面中。css-loader
:加载css
资源。scss-loader
:加载scss
资源。postcss-loader
:处理css
浏览器的兼容,自动加上前缀。eslint-loader
:代码规范化。url-loader
:加载图片,文字等资源,通过publicPath
生成一个路径,供外部成员调用。babel-loader
:代码降级,解决兼容问题。- ...
如果让我写一个loader
,那么我得根据loader
的执行要求:我不管loader
如何处理逻辑,但是返回的必须是一段可执行的JavaScript
代码。
四、你对plugin了解多少,你们常用哪些plugin呢,如果让你手写一个plugin你有什么想法呢?
plugin
顾名思义为"插件",它能够帮助我们做一下loader
做不到的事情,比如代码压缩
、打包
结果的清除等等,项目中常见的plugin
如下。
CleanWebpackPlugin
:用于在每一次打包生成新的bundle.js
之前,清除上一次的打包文件。HtmlWebpackPlugin
:用于生成html
文件。CopyWebpackPlugin
:用于拷贝那些不需要参与打包的文件。MiniCssExtractPlugin
:用于提取所有css
文件。ProgressBarPlugin
:打包可视化进度条。HotModuleReplacementPlugin
:可用于热更新。DllReferencePlugin
:分包拆包,webpack5
中已经不再维护了,推荐使用Webpack
的optimization
配置项。
如果让我写一个plugin
,那么我得根据plugin
的执行要求:
- 每一个插件的本身就是一个函数。
- 每个函数内部都要实现一个
apply
方法。 - 借助
webpack
生命周期钩子,通过compiler
对象访问钩子,帮我们把插件注入到webpack
运行流程中执行。 - 根据需求编写我们的逻辑。
五、loader与plugin的区别在哪呢,你知道有两种引入css的方式吗,他们的区别呢?
loader
与plugin
的本质都是函数,但是loader
要求必须返回可执行的JavaScript
代码,而plugin
则必须实现一个apply
方法,且需要借助Webpack
的生命钩子方才能执行,这就是他们最大的区别
,其次loader
也可以实现构建工程化里面的功能,比如babel-loader
,但是按照约定俗成,我们直接把loader
成为模块加载器
,主要用于资源模块的加载,而plugin
能够完成loader
不能完成的的事情,只能说他是对loader
功能的扩展,且他的功能更加丰富。
两种引入css
的方式一种是style-loader
,一种是MiniCssExtractPlugin
style-loader
:生成style
标签,引入到页面。MiniCssExtractPlugin
:生成link
标签,引入到页面。
六、Webpack的optimization有配置过吗?可以简单说说吗?
module.exports = {
...
optimization : {
splitChunks: {
// chunks: 'all' || 'async' || 'initial' , all与initial效果类似,async为异步模块
cacheGroups: {
commons: {
chunks: "initial",//相同的chunks提出来
minChunks: 2,//依赖了两个以上的关系
minSize: 0 //这个依赖最小体积为0
},
vendor: {
test: /node_modules/,
// 默认选项,表示只要有依赖的第三方包就要拆出去,跟all差不多
chunks: "initial",
name: "vendor",
enforce: true
}
}
},
usedExports: true, // 只导出外部成员引用模块
// 此属性用于模块导入合并,因为单独的模块导入要使用_webpack_require_函数。
// 此属性就是可以利用_webpack_require_一次性导入所有模块,也叫作用域提升。
concatenateModules: true,
minimize: true, // 开启代码压缩,或者配置压缩器
// minimizer:[ new OptimizeCssAssetsWebpackPlugin() new terser-webpack-plugin() ]
sideEffect: true,
}
}
七、Webpack的构建原理是怎样的呢?
npm run build
就可以让webpack
自动打包构建了,然后webpack
会经历如下步骤。
webpack-cli
启动。- 载入配置项参数,初始化
Compiler
对象,加载所有配置项plugin
。 - 使用
Compiler
对象的run
方法开始编译项目。 - 通过
entry
找到入口文件,解析模块依赖,形成依赖树。 - 递归遍历依赖树,让
loader
去加载对应的模块以及依赖模块。 - 合并
loader
处理结果,组装成chunks
,转换成文件,输出到build
目录。
详见重学webpack系列(八) -- webpack的运行机制与工作原理
八、Webpack的HMR原理你知道吗,请简单说说?
HMR
就是模块的热更新,核心原理就是创建一个本地服务器,通过与client
建立socket
链接,当依赖资源有更新的时候,能够实现正在运行中的模块热替换。具体参见重学webpack系列(七) -- webpack的HMR的实践与原理
九、treeShaking知道吗,说说他跟babel-loader是否产生冲突呢?
treeShanking
顾名思义就是把代码中,没有被外部成员引用到的代码优化掉,起到压缩的作用,在production
中,treeShaking
是自动开启的。因为我们知道treeShaking
是基于ESM
生效的,那么我们在项目中配置了babel-loader
会把ESM
转为Common.js
,那treeShaking
是不是就失效了呢,在babel-loader
中,禁用了babel
对ESM
的转化,所以treeShaking
还是能够生效的。
module.exports = {
...
module:{
rules:[
{
test:'js',
use:{
loader: "babel-loader",
// 禁止开启对ESM模块的转变
options: { presets: [ ['@babel/preset-env', { "modules": false }] ] }
}
}
]
}
}
十、你能不能介绍一下Webpack5都新增了哪些特性呢,简单说说吧?
webpack5
中,mode='production'
自动开启。- 内置
terser-webpack-plugin
插件,mode='production'
自动压缩。 optimization.concatenateModules = true
,作用域提升,模块合并。cache-loader
废弃,持久化缓存,module.exports = { cache: { type: 'filesystem', // 文件系统 }, }
asset module
资源模块代替file-loader
、url-loader
。webpack server
启动本地服务,详见webpack启动服务。- ......
十一、你了解Webpack的三种hash吗?请简单说说?
三种hash
分别为文件hash
,chunkhash
,contenthash
。
hash
: 为打包后所有文件的hash
,只要其中一个文件改变,此hash
就会改变。chunkhash
: 为不同文件的单独hash
值,只要本身内容改变就会改变hash
值。contenthash
: 为不同文件单独hash
,只要本身内容改变就会改变hash
值,可用于解决外部依赖文件的变更,影响到自身的hash
的变化的情况。
十二、Webpack的resolve配置项有用过吗,请简单说说他有什么作用?
可用作指定配置,告知Webpack以什么样的方式去构建,表现在:
- 别名:
alias
- 文件类型:
extensions
- 解析的模块范围:
modules
module.exports = {
resolve: {
alias:{
'@':'root/src' // 指定别名@,通过@可以找到文件目录
},
extensions:{
['.jsx', '.tsx', '.vue'] // 指定webpack需要解析哪些类型的文件
},
modules:{
['node_modules', 'root/src'] // 指定webpack需要解析那些范围的文件
}
}
}
十三、说一说你在项目中做了Webpack层面的哪些优化呢,以及你所了解的Webpack层面的优化?
详见重学webpack系列(九) -- webpack的高级特性与前端性能优化
展望
这篇文章与上一篇文章更新隔了20
多天,下一个系列前端构建工具vite进阶系列,搁浅的也有些时间了,所以接下来的主要创作时间就放在了这个上面,同时也希望跟各位同学一起交流学习心得。