背景
最近在面试,面试官们问一个东西都是 XXX 是啥,XXX 有啥用, XXX 原理是啥,XXX 有哪些优缺点, XXX 为啥要这样 😓
哈哈。所以学一个东西,连它的前世今生都得知道,知其然,知其所以然,我正好要去了解一下 webpack, 快上车!!!
Webpack 是啥
它是一个打包工具 😊
原始社会
先让我们回忆一下,没有它之前的前端资源是怎么编译上传的。
以前,他们都写 css+html+js, 最多就压缩一下代码了,把资源传上去浏览器就可以执行了。不知道你们写过这么老的页面不
// index.html
<html>
<head>
<link rel="stylesheet" href="styles.css">
</head>
<body>
/ ** 完整的 hmlt 标签 **/
</body>
// 手动引入所有依赖
<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
</html>
模块化
随着 js 框架的出现 以及 js 的模块化兴起(js 依赖 js 资源),我们看看 2010 年还没有 webpack 时,是怎么构建前端资源的呢
eg
// index.html 哦!只有一个 bundle.js 了,看来是对 js 文件有所处理了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Project</title>
</head>
<body>
<h1>Check the console for output</h1>
<script src="dist/bundle.js"></script>
</body>
</html>
// html 需要用到的 js 资源有:
- js/
- module1.js
- module2.js
// 这里 js 的模块打包工具,像是 gulp . grunt 。 都是给一个 js 入口文件,然后对其模块依赖进行打包。 可以看这里的配置,都是需要自己去手动配置的。
module.exports = function(grunt) {
grunt.initConfig({
concat: {
dist: {
src: ['src/module1.js', 'src/module2.js', 'src/app.js'],
dest: 'dist/app.js'
}
},
uglify: {
dist: {
files: {
'dist/bundle.js': ['dist/app.js']
}
}
}
});
与此同时,对项目的css 资源、js 的模块依赖资源,都是手动配置去针对文件进行对应处理,需要手动去编写大量配置。
webpack 来了!
2014年 webpack 1.0 版本发布了。它通过简单的入口配置,自动分析依赖模块资源,对资源进行转化、压缩处理,输出构建后的资源在浏览器上使用。
配置示例
module.exports = {
entry: './src/index.js', // 入口文件
output: {
filename: 'bundle.js', // 输出文件名
path: path.resolve(__dirname, 'dist') // 输出目录
},
module: {
rules: [
{
test: /\.js$/, // 匹配 .js 结尾的文件
},
{
test: /\.css$/, // 匹配 .css 结尾的文件
}
]
}
};
不同与 gulp / grunt 需要手动编排不同文件的处理步骤和优化手段。webpack 只需要你提供入口文件,分析所有依赖的模块,并内部实现了基础的优化能力。并且内置能力在不断优化中。从 2014年到现在,已经是 webpack 5.0 ,相信大家也经常看到 webpack 的许多优点:
文件处理多样性:
jsx / image / js / ts / css / json / svg …
资源大小
模块化: 文件的模块化处理, chunk 的重复利用
按需加载: 模块的依赖关系分析,页面按需引入所需要资源
优化能力
内置的优化能力: 压缩、treeShaking
配合生态插件:浏览器的兼容性处理
构建速度的优化:
增量构建
多线程构建
cache 缓存使用
自定义能力
通过 loader / plugin 实现自定义的文件处理
现在呢
看起来, webpack 真好是吧。但前端发展是多样化的、迅速的。 webpack 也随着不断的迭代,前端模块的多样性,前端框架的快速发展,支持不同的框架(react/ vue)、js 语法、 ts 等,更好的优化性能,webpack 也逐渐变得庞大,配置也变得更多。
现在都有哪些构建工具呢?
Parcel
一个快速、零配置的打包工具。
<html>
<body>
<script src="./index.js"></script>
</body>
</html>
parcel index.html
它支持一些资源类型的打包构建,所以不用手动额外配置。甩手掌柜真不错呀。 但也因为不能自定义配置和目前支持类型不算丰富,所以还是不能和webpack 相比的
rspack
Rspack 是一个2023年新兴的前端构建工具,由字节跳动开发和维护。其核心是通过基于 rust 编写的 swc 编译器,实现的类似 webpack 工具。
因为基于 rust(擅长并发性和内存管理) 语言处理 js 的语法转换、代码编译,所以在运行运行速度上可以提高10倍以上。
但是因为 swc 所支持的语法还不完善 ,加上 rspack 还有很多要补齐的能力,所以目前并不算稳定。
esbuild
esbuild 是一个快速的 JavaScript
和 TypeScript
打包器,它由 Go 语言编写而成。其编译速度可以超过 Webpack 和 Rollup 等传统工具 10-100 倍。这主要得益于 Go 语言的高性能特性。
const esbuild = require('esbuild');
esbuild.build({
entryPoints: ['src/index.js'],
outfile: 'dist/index.js',
bundle: true,
minify: true,
sourcemap: true,
format: 'esm', // 或者 'cjs' 用于 CommonJS 格式
}).catch(() => process.exit(1));
虽然 esbuild 也可以配合其他插件,对 css 、md 等其他文件进行处理,但都是手动编写配置去执行,并且生态系统也不算完整。
所以,我们可以用 esbuild 去构建 js、ts 工具包,对于业务项目可能就不那么合适啦
总结
好了,现在我们回过头来看上面那些问题,你会回答了吗?
快总结以下给我评论,我将按你的答案去面试!希望本文对你有用~