前端 Bundler,即前端打包工具,用于处理和优化前端资源(JavaScript、CSS、HTML、图片、字体等)的工具。它将这些资源组合并捆绑成一个或多个文件,以减少加载时间和提高应用性能
为什么需要 bundler
随着现代前端开发的复杂度不断增加,Bundler 作为构建过程的重要组成部分,帮助开发者管理复杂的依赖关系、进行代码拆分、实现模块化开发,并优化构建输出,已经成为开发流程中不可或缺的一部分
模块化开发:支持现代 JavaScript 模块系统,提高代码可维护性。 减少 HTTP 请求:将多个文件合并打包,减少请求数量,提高加载速度。 代码转译与兼容性:将现代 JavaScript 转译成兼容的旧版本。 优化与压缩:自动优化和压缩代码,减小文件体积。 静态资源处理:处理和优化 CSS、图片、字体等静态资源。 提升开发体验:提供热模块替换等功能,提高开发效率。 代码分割与懒加载:按需加载代码,提高执行性能。 自动化与任务管理:简化和自动化构建任务,提升开发过程效率。
Webpack
Webpack 是目前最流行的前端打包工具,功能强大,插件生态丰富,适合处理复杂的前端项目。
功能全面、生态丰富、高度可定制,几乎可以满足所有需求 配置繁琐复杂,学习成本高 性能相对于 Go、Rust 编写的 bundler 较慢
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js', // 入口文件
output: {
path: path.resolve(__dirname, 'dist'), // 输出目录
filename: 'bundle.js', // 输出文件名
clean: true // 清理输出目录
},
module: {
rules: [
{
test: /.js$/, // 匹配.js文件(使用正则表达式)
exclude: /node_modules/, // 排除node_modules目录
use: {
loader: 'babel-loader', // 使用babel-loader
}
},
{
test: /.css$/, // 匹配.css文件
use: ['style-loader', 'css-loader'] // 依次使用style-loader和css-loader
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html', // 指定模板文件
filename: 'index.html', // 输出文件名
})
],
devServer: {
contentBase: path.join(__dirname, 'public'), // 指定静态文件目录
compress: true, // 启用gzip压缩
port: 9000, // 端口号
open: true, // 自动打开浏览器
hot: true // 启用热模块替换
},
resolve: {
extensions: ['.js', '.jsx'] // 自动解析文件扩展名
},
mode: 'development' // 设置模式为开发模式
};
如果应用规模不大,或者暂时对构建性能的要求并不高,Webpack 是最保险的选择
Vite
严格来讲 Vite 并不能仅仅是 bundler,Vite 既是一个前端开发服务器和任务运行器,也是一个 bundler,只不过在不同阶段,它的功能侧重点有所不同
开发阶段:主要对模块进行即时编译和 HMR,而不进行传统的打包,因此这个阶段可以认为它不是传统的 bundler。 生产构建阶段:使用 Rollup 进行完整的打包和优化工作,因此在这个阶段,它确实可以被认为是一个 bundler。
这种双重策略使得 Vite 能够在提供极快开发体验的同时,也能生成高效的生产代码,从而更好地适应现代前端开发的需求。
mport { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
input: 'src/main.js',
output: {
entryFileNames: `assets/[name].js`,
chunkFileNames: `assets/[name].js`,
assetFileNames: `assets/[name].[ext]`
},
}
}
});
如果使用 Vue 那可以直接应用 Vite,使用 React 等如果没有历史包袱,Vite 也是一个不错的选择,如果是老项目建议沿用 Webpack 或替换为 Rspack 等和 Webpack 生态兼容的选择
ESBuild
ESBuild 是一个新的打包工具,因其极高的编译速度而迅速受到关注和青睐,使用 Go 语言编写。
高速构建:编译速度非常快,是 Webpack 的数倍。适合开发环境和快速构建。 简单易用:配置简洁,适合快速上手。 生态系统较小:插件和加载器数量不如 Webpack 丰富,某些复杂需求可能无法实现。 功能覆盖不完全:目前不支持所有 Webpack 的高级特性,如复杂的代码分割策略。
ESBuild 取代 Webpack 独立使用的话生态和代码风格=功能的缺失可能会使大问题,但可以作为 Webpack 的一个插件使用,以获得 Webpack 的生态系统和配置灵活性的同时,利用 ESBuild 的高效编译能力来加速构建过程
module.exports = {
entry: './src/index.tsx', // 入口文件
output: {
filename: 'bundle.js', // 打包后的文件名
path: path.resolve(__dirname, 'dist') // 输出路径
},
module: {
rules: [
{
test: /.tsx?$/, // 匹配 TypeScript 和 TSX 文件
loader: 'esbuild-loader',
options: {
loader: 'tsx', // 适配 TypeScript 和 React 的 JSX
target: 'es2015' // 指定编译目标为 ES2015
}
},
{
test: /.css$/, // 匹配 CSS 文件
use: ['style-loader', 'css-loader'] // 使用 style-loader 和 css-loader 加载 CSS
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js'] // 解析文件扩展名
},
devtool: 'source-map' // 启用 source map 以便调试
};
Rspack
www.rspack.dev/zh/guide/st…[1]
我们创建 Rspack 的原因,是为了解决在字节跳动维护构建工具时遇到的各种性能问题。由于字节跳动内部存在许多巨石应用,它们都具有复杂的构建配置,生产环境的构建需要耗费十几分钟,甚至超过半小时;开发环境的耗时也超过十几分钟。
我们在 webpack 上尝试了多种方法来优化这些巨石应用,但是效果甚微。我们意识到在 webpack 上的优化已经难以为继,必须要从底层改造,才能适应我们的需求。
Rspack 是字节跳动技术团队为了解决构建性能使用 Rust 开发的 bundler
使用 Rust 编写,并且将大量的 loader 内置,带来了显著的性能提升和配置简化 配置基于 webpack 设计实现,开发者可以非常轻松地将项目从 webpack 迁移至 rspack 虽然 Rspack 内置了一些常见的加载器,但其生态系统的插件和加载器数量不如 Webpack 丰富 作为一个新兴的构建工具,社区支持和文档资源相对较少 与现有工具链和流行框架的集成度不如 Webpack
Rspack 相对 Turbopack 还是很有潜力,但目前在成长期,尤其是作为国人发布的产品,海外的参与度在前期可能有限,考虑到社区支持和文档资源,建议观望
Respack 2024.08.28 发布了 v1.0[2],新项目可以尝试一下了
const path = require('path');
module.exports = {
entry: './src/index.tsx',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
{
test: /.(ts|tsx|js)$/,
loader: 'rspack-loader',
options: {
loader: 'tsx',
target: 'es2015'
}
},
{
test: /.css$/,
use: ['style-loader', 'css-loader']
}
]
},
devtool: 'source-map'
};
Turbopack
Turbopack 是 Webpack 的作者使用 Rust 语言开发一个前端模块化的工具,目标是取代 Webpack,目前 Turbopack 仍然处于 AIpha 阶段,离正式运用到生产环境还有不少时间。
快确实是快,但主要 提升来自于 SWC Turbopack 提供了一些基础插件和扩展,能够支持常见的文件处理和优化任务,但仍然与 Webpack 和其他成熟工具的插件生态系统有差距 作为新兴工具,Turbopack 的社区相对来说还在发展初期,社区规模和活跃度与 Webpack 等工具相比还不大
const path = require('path');
module.exports = {
entry: './src/index.tsx', // 入口文件
output: {
path: path.resolve(__dirname, 'dist'), // 输出目录
filename: 'bundle.js', // 输出文件名
},
resolve: {
extensions: ['.ts', '.tsx', '.js'], // 自动解析扩展名
alias: {
'@': path.resolve(__dirname, 'src'), // 别名配置
},
},
module: {
rules: [
{
test: /.tsx?$/, // 匹配 .ts 或 .tsx 文件
use: 'ts-loader', // 使用 ts-loader 处理
exclude: /node_modules/, // 排除 node_modules 目录
},
{
test: /.css$/, // 匹配 .css 文件
use: ['style-loader', 'css-loader'], // 依次使用 style-loader 和 css-loader
}
],
},
devServer: {
contentBase: path.join(__dirname, 'public'), // 指定内容目录
compress: true, // 启用 gzip 压缩
port: 3000, // 端口号
hot: true, // 启用 HMR(热模块替换)
open: true, // 自动打开浏览器
},
mode: 'development', // 设置开发模式
};
Turbopack 被设计为 Next.js 的一个未来核心构建工具,以替代 Webpack 和其他构建工具。这种紧密集成在 Next.js 项目中有一定的优势,其它项目不建议使用
Rollup
Rollup 从一开始就设计为打包 JavaScript 库,因此在构建库文件时有很多优化措施。例如,输出更干净的代码结构、更少的开销(boilerplate)等,顺便说一句 Rollup 是第一个广泛应用和推广 Tree Shaking 的 JavaScript 模块打包工具
Rollup 原生支持多种模块格式(如 ES6、CommonJS、UMD、AMD 等),这使得它在发布兼容性库时非常方便。图表四兄弟 D3.js、Three.js、Chart.js、Highcharts 都使用 rollup 进行打包,Echarts、LodashES、Preact、Svelte、dayjs、date-fns 等也在使用 rollup,当然 vite 目前底层还在使用 Rollup 在生产阶段构建(使用 Rust 写的 rolldown[3] 已经开源了,未来可能替换掉 Rollup)
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import postcss from 'rollup-plugin-postcss';
import { terser } from 'rollup-plugin-terser';
export default {
input: 'src/index.js', // 入口文件
output: {
file: 'dist/bundle.js', // 输出文件
format: 'iife', // 立即调用函数表达式(IIFE)格式适合浏览器环境
sourcemap: true // 生成sourcemap文件以便调试
},
plugins: [
resolve(), // 处理模块路径
commonjs(), // 转换CommonJS模块为ES6
babel({
exclude: 'node_modules/**', // 排除node_modules目录
babelHelpers: 'bundled'
}),
postcss({
extract: true // 将CSS提取到单独的文件
}),
terser() // 压缩输出文件
]
};
Rollup 其实没有太多和 Webpack 对比的必要,插件的生态的丰富度和配置灵活性肯定不及 Webpack,但 Rollup 更适合于开发和打包 JavaScript 库,尤其是希望生成干净、体积小的可重用模块时
SWC
虽然我们对 SWC 的理解主要是作为代码转译工具使用,但 SWC/swcpack 也有 bundler 的能力
SWC can be used for both compilation and bundling. For compilation, it takes JavaScript / TypeScript files using modern JavaScript features and outputs valid code that is supported by all major browsers.
但不幸的是 SWC 作者主要精力在 Turbopack 上
This feature is still under construction. Also, the main author of SWC works for Turbopack(opens in a new tab)[4] by Vercel, so this feature is not something that will be actively developed.
建议目前不要使用,反而希望 SWC 在代码转译生态上发发力
本文转载于稀土掘金技术社区,作者:谦行
原文链接:https://juejin.cn/post/7390815289993216054