SWC 打包功能 #
打包基础 #
什么是打包? #
打包是将多个模块和依赖合并成一个或多个文件的过程:
text
┌─────────────────────────────────────────────────────────────┐
│ 打包过程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ src/ │
│ ├── index.js │
│ ├── utils.js │
│ └── components/ │
│ ├── Button.js │
│ └── Input.js │
│ │
│ │ │
│ ▼ │
│ │
│ dist/ │
│ └── bundle.js │
│ │
└─────────────────────────────────────────────────────────────┘
spack 简介 #
spack 是 SWC 内置的打包器,提供:
- 极快的打包速度
- Tree-shaking 支持
- 代码分割
- 多入口支持
安装 #
bash
npm install --save-dev @swc/cli @swc/core @swc/spack
基本配置 #
创建配置文件 #
javascript
// spack.config.js
module.exports = {
entry: {
main: './src/index.js'
},
output: {
path: './dist',
name: 'bundle.js'
}
};
运行打包 #
bash
npx spack
配置详解 #
完整配置结构 #
javascript
module.exports = {
mode: 'production',
entry: {
main: './src/index.js'
},
output: {
path: './dist',
name: '[name].js',
format: 'esm'
},
module: {},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
},
options: {
jsc: {
parser: {
syntax: 'ecmascript',
jsx: true
},
target: 'es2015'
}
}
};
entry 配置 #
单入口 #
javascript
module.exports = {
entry: {
main: './src/index.js'
}
};
多入口 #
javascript
module.exports = {
entry: {
main: './src/index.js',
admin: './src/admin.js',
login: './src/login.js'
}
};
数组入口 #
javascript
module.exports = {
entry: {
main: ['./src/polyfills.js', './src/index.js']
}
};
output 配置 #
基本输出 #
javascript
module.exports = {
output: {
path: './dist',
name: 'bundle.js'
}
};
使用占位符 #
javascript
module.exports = {
entry: {
main: './src/index.js',
admin: './src/admin.js'
},
output: {
path: './dist',
name: '[name].[hash].js'
}
};
输出格式 #
javascript
module.exports = {
output: {
path: './dist',
name: 'bundle.js',
format: 'esm' // 'esm' | 'cjs' | 'iife'
}
};
resolve 配置 #
javascript
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
alias: {
'@': './src',
'@utils': './src/utils',
'@components': './src/components'
}
}
};
module 配置 #
javascript
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|jpg|gif)$/,
use: ['file-loader']
}
]
}
};
代码分割 #
动态导入 #
javascript
// src/index.js
async function loadModule() {
const { heavyFunction } = await import('./heavy.js');
heavyFunction();
}
loadModule();
javascript
// spack.config.js
module.exports = {
entry: {
main: './src/index.js'
},
output: {
path: './dist',
name: '[name].js'
}
};
打包结果:
text
dist/
├── main.js
└── heavy.[hash].js
手动分割 #
javascript
module.exports = {
entry: {
main: './src/index.js',
vendor: ['lodash', 'axios']
},
output: {
path: './dist',
name: '[name].js'
}
};
SplitChunks 配置 #
javascript
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};
Tree-shaking #
启用 Tree-shaking #
javascript
// spack.config.js
module.exports = {
mode: 'production',
options: {
jsc: {
target: 'es2015'
}
}
};
Tree-shaking 示例 #
javascript
// utils.js
export function used() {
return 'used';
}
export function unused() {
return 'unused';
}
// index.js
import { used } from './utils';
console.log(used());
打包后只包含 used 函数。
副作用标记 #
json
// package.json
{
"sideEffects": false
}
或指定有副作用的文件:
json
{
"sideEffects": ["*.css", "*.scss"]
}
外部依赖 #
排除依赖 #
javascript
module.exports = {
external: ['lodash', 'axios', 'react', 'react-dom']
};
函数形式 #
javascript
module.exports = {
external: (id) => {
return id.includes('node_modules');
}
};
全局变量映射 #
javascript
module.exports = {
external: ['lodash', 'jquery'],
output: {
globals: {
lodash: '_',
jquery: '$'
}
}
};
Source Map #
启用 Source Map #
javascript
module.exports = {
options: {
sourceMaps: true
}
};
内联 Source Map #
javascript
module.exports = {
options: {
sourceMaps: 'inline'
}
};
开发模式 #
开发配置 #
javascript
// spack.config.js
const isDev = process.env.NODE_ENV !== 'production';
module.exports = {
mode: isDev ? 'development' : 'production',
entry: {
main: './src/index.js'
},
output: {
path: './dist',
name: '[name].js'
},
options: {
jsc: {
parser: {
syntax: 'ecmascript',
jsx: true
},
target: 'es2015'
},
sourceMaps: isDev ? 'inline' : true
}
};
监听模式 #
bash
npx spack watch
TypeScript 支持 #
TypeScript 配置 #
javascript
module.exports = {
entry: {
main: './src/index.ts'
},
output: {
path: './dist',
name: '[name].js'
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true
},
target: 'es2015'
}
}
};
React 项目 #
React 配置 #
javascript
module.exports = {
entry: {
main: './src/index.jsx'
},
output: {
path: './dist',
name: '[name].js',
format: 'iife'
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
},
options: {
jsc: {
parser: {
syntax: 'ecmascript',
jsx: true
},
transform: {
react: {
runtime: 'automatic'
}
},
target: 'es2015'
}
}
};
库打包 #
库配置 #
javascript
module.exports = {
entry: {
main: './src/index.ts'
},
output: [
{
path: './dist',
name: 'my-lib.cjs.js',
format: 'cjs'
},
{
path: './dist',
name: 'my-lib.esm.js',
format: 'esm'
}
],
external: ['lodash'],
options: {
jsc: {
parser: {
syntax: 'typescript'
},
target: 'es2015',
externalHelpers: true,
keepClassNames: true
}
}
};
JavaScript API #
编程式使用 #
javascript
const { bundle } = require('@swc/spack');
async function build() {
const result = await bundle({
entry: {
main: './src/index.js'
},
output: {
path: './dist',
name: 'bundle.js'
}
});
console.log(result);
}
build();
自定义构建 #
javascript
const { bundle } = require('@swc/spack');
const fs = require('fs');
async function build() {
const result = await bundle({
entry: {
main: './src/index.js'
},
output: {
path: './dist',
name: 'bundle.js'
},
options: {
jsc: {
parser: {
syntax: 'ecmascript'
},
target: 'es2015'
},
minify: true,
sourceMaps: true
}
});
for (const [filename, content] of Object.entries(result.output)) {
fs.writeFileSync(`./dist/${filename}`, content.code);
if (content.map) {
fs.writeFileSync(`./dist/${filename}.map`, JSON.stringify(content.map));
}
}
}
build();
与其他工具对比 #
spack vs Webpack #
| 特性 | spack | Webpack |
|---|---|---|
| 速度 | 极快 | 较慢 |
| 配置 | 简单 | 复杂 |
| 插件生态 | 🔄 发展中 | ✅ 成熟 |
| 代码分割 | ✅ 支持 | ✅ 强大 |
| HMR | ⚠️ 有限 | ✅ 完善 |
spack vs Rollup #
| 特性 | spack | Rollup |
|---|---|---|
| 速度 | 极快 | 快 |
| Tree-shaking | ✅ 支持 | ✅ 优秀 |
| 输出格式 | 多种 | 多种 |
| 插件 | SWC 插件 | JS 插件 |
| 适用场景 | 应用/库 | 库开发 |
实战示例 #
完整项目配置 #
javascript
// spack.config.js
const isDev = process.env.NODE_ENV !== 'production';
const isProd = !isDev;
module.exports = {
mode: isProd ? 'production' : 'development',
entry: {
main: './src/index.tsx'
},
output: {
path: './dist',
name: isProd ? '[name].[contenthash].js' : '[name].js',
format: 'iife'
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
alias: {
'@': './src',
'@components': './src/components',
'@utils': './src/utils'
}
},
external: {
react: 'React',
'react-dom': 'ReactDOM'
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
decorators: true
},
transform: {
react: {
runtime: 'automatic'
}
},
target: 'es2015',
minify: isProd ? {
compress: {
defaults: true,
drop_console: isProd,
drop_debugger: isProd
},
mangle: isProd
} : false
},
sourceMaps: true,
minify: isProd
}
};
npm scripts #
json
{
"scripts": {
"build": "spack",
"build:prod": "NODE_ENV=production spack",
"build:watch": "spack watch",
"dev": "spack watch"
}
}
常见问题 #
问题一:模块解析失败 #
解决方案:
javascript
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
}
};
问题二:CSS 文件不处理 #
解决方案:
javascript
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
问题三:外部依赖未排除 #
解决方案:
javascript
module.exports = {
external: ['react', 'react-dom', 'lodash']
};
下一步 #
现在你已经掌握了 SWC 的打包功能,接下来学习 插件开发 了解如何扩展 SWC!
最后更新:2026-03-28