模块打包工具的作用和原理。
// 问题:
// 1. 模块数量多,HTTP请求多
// 2. 浏览器兼容性问题
// 3. 代码压缩和优化
// 4. 资源处理(CSS、图片等)
// 5. 开发体验(热更新、调试)
// 打包工具的作用:
// 1. 模块打包:合并多个模块
// 2. 代码转换:ES6+转ES5
// 3. 代码压缩:减小体积
// 4. 资源处理:处理非JS资源
// 5. 开发服务器:本地开发
// 6. 代码分割:按需加载
// Webpack
// - 功能最全面
// - 生态最成熟
// - 配置复杂
// Rollup
// - 适合库开发
// - Tree-shaking优秀
// - 配置简单
// Vite
// - 开发体验好
// - 基于ES Modules
// - 构建使用Rollup
// Parcel
// - 零配置
// - 开箱即用
// - 适合小型项目
// esbuild
// - 极快的速度
// - Go语言编写
// - 现代工具链
最流行的模块打包工具。
// webpack.config.js
const path = require("path");
module.exports = {
// 入口
entry: "./src/index.js",
// 输出
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
clean: true
},
// 模式
mode: "development", // development | production | none
// 模块规则
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: "babel-loader"
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.(png|jpg|gif)$/,
type: "asset"
}
]
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
// 开发服务器
devServer: {
static: "./dist",
hot: true,
port: 3000
}
};
// babel-loader: 转换ES6+
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
}
}
// css-loader + style-loader: 处理CSS
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
// sass-loader: 处理Sass
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
// file-loader: 处理文件
{
test: /\.(png|jpg|gif)$/,
type: "asset/resource"
}
// url-loader: 小文件转base64
{
test: /\.(png|jpg|gif)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb以下转base64
}
}
}
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
plugins: [
// 清理dist目录
new CleanWebpackPlugin(),
// 生成HTML
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html"
}),
// 提取CSS
new MiniCssExtractPlugin({
filename: "css/[name].[contenthash].css"
})
]
};
module.exports = {
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all"
}
}
}
}
};
// 动态导入
import("./module.js").then(module => {
module.init();
});
// 魔法注释
import(
/* webpackChunkName: "user" */
"./user.js"
);
适合库开发的打包工具。
// rollup.config.js
export default {
input: "src/index.js",
output: [
{
file: "dist/bundle.js",
format: "cjs" // CommonJS
},
{
file: "dist/bundle.esm.js",
format: "esm" // ES Modules
},
{
file: "dist/bundle.umd.js",
format: "umd",
name: "MyLibrary" // UMD
}
]
};
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import babel from "@rollup/plugin-babel";
import terser from "@rollup/plugin-terser";
export default {
input: "src/index.js",
output: {
file: "dist/bundle.js",
format: "esm"
},
plugins: [
resolve(),
commonjs(),
babel({ babelHelpers: "bundled" }),
terser()
]
};
// Rollup的Tree-shaking非常优秀
// utils.js
export function used() {
console.log("使用");
}
export function unused() {
console.log("未使用");
}
// main.js
import { used } from "./utils.js";
used();
// 打包后只包含used函数
新一代前端构建工具。
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
root: "src",
build: {
outDir: "../dist",
sourcemap: true
},
server: {
port: 3000,
open: true
}
});
// Vite特点:
// 1. 开发服务器极快启动
// 2. 基于ES Modules,无需打包
// 3. HMR快速更新
// 4. 生产构建使用Rollup
// 开发模式:直接使用ES Modules
// 生产模式:打包优化
// 支持多种格式
import "./style.css";
import logo from "./logo.png";
import data from "./data.json";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"@": path.resolve(__dirname, "src")
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/variables.scss";`
}
}
},
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ["vue", "vue-router"],
utils: ["lodash", "axios"]
}
}
}
}
});
极速的JavaScript打包器。
const esbuild = require("esbuild");
// 直接构建
esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
outfile: "dist/bundle.js",
minify: true,
sourcemap: true,
target: ["es2020"]
});
// API调用
async function build() {
const result = await esbuild.build({
entryPoints: ["src/index.js"],
bundle: true,
write: false
});
console.log(result.outputFiles[0].text);
}
// esbuild特点:
// 1. 极快的速度(Go编写)
// 2. 内置支持TypeScript
// 3. 内置支持JSX
// 4. Tree-shaking
// 5. 代码分割
// 限制:
// 1. 不支持完整的TypeScript类型检查
// 2. 插件生态较小
// 3. 某些高级功能不支持
优化打包结果的方法。
// 1. Tree-shaking
// 使用ES Modules语法
export { used };
import { used } from "./utils";
// 2. 代码压缩
mode: "production" // 自动启用
// 3. 按需加载
const Module = lazy(() => import("./Module"));
// 4. 外部依赖
externals: {
react: "React",
"react-dom": "ReactDOM"
}
// 5. 分析工具
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
plugins: [new BundleAnalyzerPlugin()]
// 1. 缓存
cache: {
type: "filesystem"
}
// 2. 多线程
module: {
rules: [{
test: /\.js$/,
use: [{
loader: "thread-loader"
}, {
loader: "babel-loader"
}]
}]
}
// 3. 缩小范围
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
include: path.resolve("src")
}]
}
// 4. DLL预编译
// webpack.dll.config.js
new webpack.DllPlugin({
name: "[name]",
path: path.join(__dirname, "[name]-manifest.json")
});
掌握了模块打包工具后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:模块打包工具是现代前端工程化的核心,Webpack功能全面、Rollup适合库开发、Vite开发体验极佳。在 db-w.cn,我们帮你掌握前端工程化工具链!