webpack相关面试题
# webpack 相关面试题
# webpack 如何对 js/css 代码进行压缩?
在 webpack 配置中设置 optimization 的 minimizer 属性,压缩 js 可以使用 terser-webpack-plugin 插件,插件内部使用的就是 terser 来实现对 js 代码的压缩,对 css 代码可以使用 css-minimizer-webpack-plugin 来对 css 代码进行压缩,插件内部使用 cssnano 优化和压缩 CSS。
# webpack 中 hash、chunkhash、contenthash 区别
- hash: 是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的 hash 值都会更改,并且全部文件都共用相同的 hash 值
- chunkhash: 是针对 entry 的每一个入口文件,独立的 hash。如果 entry 里面的其中一个文件内容改变,只会改变这个入口文件 build 之后的文件名,而不会影响到其他文件。
- contenthash: 是针对文件内容级别的,文件自身的内容改变 hash 值才会发生变化。
# Webpack 配置中用过哪些 Loader ?都有什么作用?
- file-loader: 把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)
- url-loader: 与 file-loader 类似,区别是用户可以设置一个阈值,大于阈值会交给 file-loader 处理,小于阈值时返回文件 base64 形式编码 (处理图片和字体)
- style-loader: 把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS,对于生产版本,建议 mini-css-extract-plugin 提供的 loader 从 bundle 中提取 CSS
- css-loader: 加载 CSS,支持模块化、压缩、文件导入等特性
- sass-loader: sass-loader 的作用就是将该 css 文件翻译成纯 css 语法文件,以便后续打包处理。
- less-loader: 与 sass-loader 作用相同用于处理 less 文件。
- postcss-loader: 通过 postcss css 后处理器对 css 进行处理,如配合 autoprefixer 插件自动补齐 CSS3 前缀
- vue-loader: 加载 Vue.js 单文件组件
- source-map-loader: 加载额外的 Source Map 文件,以方便断点调试
# Webpack 配置中用过哪些 Plugin ?都有什么作用?
- define-plugin: 定义环境变量 如 process.env
- html-webpack-plugin: 简化 HTML 文件创建 (依赖于 html-loader)
- uglifyjs-webpack-plugin: 压缩 js 代码(不支持 ES6 压缩 )
- terser-webpack-plugin: 压缩 js 代码(支持压缩 ES6 )
- css-minimizer-webpack-plugin: 这个插件使用 cssnano 优化和压缩 CSS。
- mini-css-extract-plugin: 分离样式文件,CSS 提取为独立文件,支持按需加载 (替代 extract-text-webpack-plugin)
- eslint-webpack-plugin: 该插件使用 eslint 来查找和修复 JavaScript 代码中的问题。
- clean-webpack-plugin: 目录清理
# Loader 和 Plugin 有什么区别?
Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
# 是否写过 Loader?简单描述一下编写 loader 的思路?
- loader 是使用在 node 环境的可以使用 node 的 api 或者引入自己安装的依赖
- webpack 会根据配置的 test 属性将匹配到的文件转换成字符串或者 buffer 传递给 loader,当前 loader 处理完之后的结果会传递给下一个 loader。
- webpack 提供了 loader-utils 和 schema-utils 工具库可以供使用
- 可以通过 exports.raw = true 告诉 Webpack 该 Loader 是否需要二进制数据
- loader 提供了 this 访问 loader context(上下文)使用 loader 内部的方法,
- 如:this.callback() 一个可以同步或者异步调用的可以返回多个结果的函数。预期的参数是:
this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);
1
2
3
4
5
6
2
3
4
5
6
- 如:this.async() 告诉 loader-runner 这个 loader 将会异步地回调。返回 this.callback。
this.async(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);
1
2
3
4
5
6
2
3
4
5
6
编写一个简单的 loader
// bar-loader.js
module.exports = function (content, map, meta) {
content = content.replace('world', 'lin')
this.callback(null, content, map, meta)
}
1
2
3
4
5
2
3
4
5
// index.js
const str = 'hello world'
console.log(str)
1
2
3
2
3
使用 loader
// webpack.config.js
const path = require('path')
module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bound.js'
},
module: {
rules: [
{
test: /.js$/,
use: ['./src/bar-loader.js']
}
]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
生成的 bound.js
/******/ ;(() => {
// webpackBootstrap
var __webpack_exports__ = {}
const str = 'hello world'
console.log(str)
/******/
})()
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 是否写过 Plugin?简单描述一下编写 Plugin 的思路?
compiler 暴露了和 Webpack 整个生命周期相关的钩子
compilation 暴露了与模块和依赖有关的粒度更小的事件钩子
插件需要在其原型上绑定 apply 方法,才能访问 compiler 实例
传给每个插件的 compiler 和 compilation 对象都是同一个引用,若在一个插件中修改了它们身上的属性,会影响后面的插件
找出合适的事件点去完成想要的功能
- emit 事件发生时,可以读取到最终输出的资源、代码块、模块及其依赖,并进行修改(emit 事件是修改 Webpack 输出资源的最后时机)
- watch-run 当依赖的文件发生变化时会触发
异步的事件需要在插件处理完任务时调用回调函数通知 Webpack 进入下一个流程,不然会卡住
编写一个简单的 loader
// testPlugin.js
// webpack 插件其实是一个具有 apply 属性的 JavaScript 对象。
// apply 属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。
const pluginName = 'ConsoleLogOnBuildWebpackPlugin'
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
compiler.hooks.run.tap(pluginName, compilation => {
console.log('webpack 构建过程开始!')
})
}
}
module.exports = ConsoleLogOnBuildWebpackPlugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
使用 plugin
const path = require('path')
const testPlugin = require('./src/testPlugin.js')
module.exports = {
mode: 'none',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bound.js'
},
plugins: [new testPlugin()]
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
运行 npx webpack 结果
linzhenbin@linzhenbindeAir test % npx webpack
webpack 构建过程开始!
asset bound.js 127 bytes [compared for emit] (name: main)
./src/index.js 43 bytes [built] [code generated]
webpack 5.70.0 compiled successfully in 35 ms
1
2
3
4
5
2
3
4
5
编辑 (opens new window)
上次更新: 2022/03/22, 18:03:49