webpack-common
v2.0.0
Published
webpack 前端构建工具
Readme
webpack-common
让 webpack 拥有 Vite 级别的开发体验 —— 零配置、可扩展、即插即用。
v2.0 重大更新:编译器由
esbuild-loader切换为swc-loader(Rust 原生,性能更强);React Fast Refresh 从核心包拆出,迁移到独立的webpack-plugin-react;新增presetsAPI,支持插件式扩展配置。详见 迁移指南。
特性
- SWC 编译:Rust 原生编译器,替代 esbuild-loader,支持 ES2022、TypeScript、JSX
- Plugin 扩展:全新
presetsAPI,支持webpack-plugin-react、webpack-plugin-vue等可插拔插件 - 开发体验:React Fast Refresh(通过
webpack-plugin-react)、错误 overlay、简洁日志 - 构建输出:Vite 风格的构建信息展示(gzip 大小、文件类型彩色、超大文件警告)
- 生产优化:contenthash 命名、deterministic ids、runtimeChunk、文件系统缓存
- CSS 支持:CSS Modules、PostCSS、Less、Sass;支持
cssCodeSplit控制 - 资源策略:统一 asset,
assetsInlineLimit内联阈值 - import.meta.env:自动注入 MODE/DEV/PROD/BASE_URL/SSR 及用户前缀变量(Vite 迁移零改动)
- 配置能力:异步 defineConfig、多页面 pages、库模式 build.lib、envPrefix/loadEnv/envDir
- Vite 对标:alias、define、publicDir、server、extensions、build.target/minify/cssCodeSplit/watch/chunkSizeWarningLimit/terserOptions
- 框架支持:Vue SFC(可选)、Svelte(可选)
- 工程扩展:proxy 便捷配置、bundle analyzer、Module Federation
- 兼容 ESM/CJS:同时提供
dist/index.mjs与dist/index.cjs
安装
npm i webpack-common -DReact 项目额外安装 webpack-plugin-react(含 SWC JSX + Fast Refresh):
npm i webpack-plugin-react -D快速开始
CommonJS + React(webpack.config.js)
const { defineConfig } = require('webpack-common');
const react = require('webpack-plugin-react');
module.exports = defineConfig({
presets: [react()], // SWC JSX + Fast Refresh
server: { port: 3000, open: true },
});CommonJS + Vue(webpack.config.js)
const { defineConfig } = require('webpack-common');
const vue = require('webpack-plugin-vue');
module.exports = defineConfig({
presets: [vue()],
server: { port: 3000, open: true },
});CommonJS 无框架(webpack.config.js)
const { defineConfig } = require('webpack-common');
module.exports = defineConfig({
server: { port: 3000, open: true },
});ESM(webpack.config.mjs 或 package.json "type":"module")
import { defineConfig, loadEnv } from 'webpack-common';
import react from 'webpack-plugin-react';
export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, ['APP_']);
return {
env,
presets: [react()],
server: { port: 3000, open: true },
build: command === 'build' ? { target: 'es2020' } : {},
};
});TypeScript 配置文件(webpack.config.ts)
需要在 devDependencies 中添加 @swc/register,供 webpack-cli 自动加载 TS 配置:
npm i @swc/register -Dimport { defineConfig } from 'webpack-common';
import react from 'webpack-plugin-react';
export default defineConfig({
presets: [react()],
server: { port: 3000 },
});注意:
webpack.config.ts所在项目不应设置"type":"module"(保持默认 CJS),否则需要使用webpack.config.mts并相应调整加载方式。
主要配置项
| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| base | string | / | 公共路径,支持绝对路径、./、auto、https URL |
| outputDir | string | dist | 构建输出目录 |
| assetsDir | string | assets | 静态资源子目录 |
| publicDir | string | false | 'public' | 静态文件目录(同 Vite publicDir),false 禁用 |
| sourcemap | boolean | 'inline' | 'hidden' | false | 生产 source map |
| envPrefix | string | string[] | 'APP_' | 注入 process.env 的变量前缀 |
| envDir | string | cwd() | .env 文件的查找目录(同 Vite envDir)|
| assetsInlineLimit | number | 4096 | 图片内联阈值(字节),超过则输出为文件 |
| presets | WebpackPresetPlugin[] | [] | v2.0 新增:插件式配置扩展,如 [react(), h5()] |
| reactRefresh | boolean | false | 旧 API,v2.0 起默认关闭;React 项目推荐改用 presets: [react()] |
| css | CSSOptions | {} | CSS 相关配置(见下文) |
| alias | object | array | — | 手动路径别名,与自动生成的 @ 别名合并 |
| define | object | — | 全局常量替换(同 Vite define) |
| extensions | string[] | — | 额外的文件扩展名(追加到默认列表) |
| server | ServerShortcuts | — | DevServer 便捷配置(port/host/open/https) |
| proxy | object | — | DevServer 代理便捷配置 |
| build | BuildOptions | — | 构建选项(见下文) |
| pages | object | array | — | 多页面配置(见下文) |
| vue | boolean | object | — | Vue SFC 支持(需安装 vue-loader) |
| svelte | boolean | object | — | Svelte 支持(需安装 svelte-loader) |
| analyze | boolean | object | — | 打包分析(需安装 webpack-bundle-analyzer) |
| federation | object | — | Module Federation 配置 |
BuildOptions
| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| lib | LibBuildOptions | — | Library 构建模式(见下文) |
| target | string | string[] | 'es2015' | SWC 编译目标,如 'es2020'、'es2022' |
| minify | boolean | 'terser' | 'esbuild' | true | 是否压缩及压缩器,false 禁用 |
| terserOptions | object | — | 自定义 Terser 配置(与默认配置合并,仅 minify='terser' 时生效) |
| cssCodeSplit | boolean | true | true 提取 CSS 到独立文件;false 内联到 JS |
| chunkSizeWarningLimit | number | 500 | 块体积警告阈值(KB),0 关闭 |
| emptyOutDir | boolean | true | 构建前是否清空输出目录 |
| watch | boolean | false | 开启 webpack watch 增量构建 |
| externals | object | — | 手动指定 externals(同 webpack externals 对象格式) |
| externalPeerDeps | boolean | true | 自动将 peerDependencies 设为 external(仅 lib 模式下生效) |
CSSOptions
| 选项 | 类型 | 说明 |
|------|------|------|
| modules | object | false | CSS Modules 配置;false 全局禁用 |
| postcss | string | object | PostCSS 配置,路径字符串或配置对象 |
| preprocessorOptions | object | 预处理器选项,键名为 less 或 scss |
| devSourcemap | boolean | 开发时启用 CSS source map |
import.meta.env
构建时自动注入以下变量,Vite 项目迁移无需修改源码:
import.meta.env.MODE // 'development' | 'production'
import.meta.env.DEV // boolean — 开发模式为 true
import.meta.env.PROD // boolean — 生产模式为 true
import.meta.env.BASE_URL // 归一化后的 base 路径,如 '/'、'/app/'
import.meta.env.SSR // false(当前不支持 SSR)
import.meta.env.APP_* // 来自 .env 文件(由 envPrefix 过滤)同时保留 process.env 注入(兼容现有代码),process.env.NODE_ENV 始终注入。
别名与全局常量
export default defineConfig({
// 对象格式(推荐)
alias: {
'@utils': 'src/utils',
'@components': 'src/components',
'lodash-es': 'lodash',
},
// 数组格式(适合需要精确控制顺序的场景)
// alias: [
// { find: '@utils', replacement: 'src/utils' },
// { find: '@', replacement: 'src' },
// ],
define: {
__APP_VERSION__: JSON.stringify('1.0.0'),
__DEV__: JSON.stringify(process.env.NODE_ENV !== 'production'),
__BUILD_TIME__: JSON.stringify(new Date().toISOString()),
},
// 额外扩展名(追加到内置列表)
// 内置默认:.js .jsx .ts .tsx .mjs .json .vue .svelte
extensions: ['.mdx', '.graphql'],
});注意:alias 数组格式中
find仅支持字符串,不支持正则表达式(webpackresolve.alias本身不支持正则键)。
DevServer 便捷配置
export default defineConfig({
// server 字段等价于 devServer 的常用选项,更简洁
server: {
port: 3000,
host: '0.0.0.0', // 允许局域网访问
open: true, // 启动后自动打开浏览器
https: false, // true 启用 HTTPS
},
// 高级 devServer 配置可直接传(与 server 合并,devServer 优先级更高)
devServer: {
historyApiFallback: true,
client: { overlay: { errors: true, warnings: false } },
},
});Proxy 配置
export default defineConfig({
proxy: {
// 字符串简写:代理到目标地址
'/upload': 'http://localhost:4000',
// 对象格式:更多选项
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
pathRewrite: { '^/api': '' },
},
},
});构建选项
export default defineConfig({
build: {
target: 'es2020', // esbuild 编译目标(字符串或数组)
minify: 'esbuild', // 'terser'(默认)| 'esbuild' | false
terserOptions: { // 自定义 Terser 参数(minify='terser' 时生效)
compress: { drop_console: true },
},
cssCodeSplit: true, // true 提取 CSS 到独立文件(默认)
chunkSizeWarningLimit: 500, // 块体积警告阈值 KB(默认 500,0=关闭)
emptyOutDir: true, // 构建前清空 outputDir(默认 true)
watch: false, // true 开启 watch 增量构建
},
});CSS 配置
export default defineConfig({
css: {
// CSS Modules — 自动识别 .module.css / .module.less / .module.scss
modules: {
localIdentName: '[local]_[hash:base64:8]', // 类名格式
exportLocalsConvention: 'camelCase', // 导出转驼峰
},
// modules: false, // 禁用 CSS Modules
// 自定义 PostCSS 配置(路径字符串或配置对象)
postcss: './postcss.config.js',
// postcss: {
// plugins: [require('tailwindcss'), require('autoprefixer')],
// },
// 预处理器选项(直接传给 less-loader / sass-loader)
// lessOptions / sassOptions 与默认值深合并,其余选项透传至 loader 顶层
preprocessorOptions: {
less: {
lessOptions: {
// 与默认 { javascriptEnabled: true } 深合并,默认值不会丢失
modifyVars: { '@primary-color': '#1890ff' },
},
// 其他 less-loader 顶层选项
additionalData: '@primary: red;',
},
scss: {
// 与默认 { includePaths: ['node_modules'] } 深合并
sassOptions: { outputStyle: 'expanded' },
// sass-loader 顶层选项
additionalData: '@use "src/styles/variables" as *;',
},
// sass: { ... }, // 也支持 .sass(缩进语法)文件
},
devSourcemap: true, // 开发时启用 CSS source map
},
build: {
cssCodeSplit: false, // false 将所有 CSS 内联到 JS(单文件场景)
},
});多页面
// 对象格式(简洁)
export default defineConfig({
pages: {
main: 'src/main.tsx',
admin: {
entry: 'src/admin.tsx',
template: 'public/admin.html', // 自定义 HTML 模板
filename: 'admin.html', // 输出文件名
},
},
});
// 数组格式(更多 HtmlWebpackPlugin 选项)
export default defineConfig({
pages: [
{
name: 'main',
entry: 'src/main.tsx',
html: { template: 'index.html', title: '主应用' },
},
{
name: 'admin',
entry: 'src/admin.tsx',
html: {
template: 'public/admin.html',
filename: 'admin.html',
title: '管理后台',
},
},
],
});Library 构建模式
export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
name: 'MyLib', // UMD 全局变量名(umd 格式必填)
formats: ['umd', 'esm'], // 默认 ['umd', 'esm'],也支持 'cjs'
fileName: 'mylib', // 输出文件名(不含后缀)
// fileName: (format) => `mylib.${format}`, // 函数形式
},
// 手动指定 externals(不打包进产物)
externals: {
react: 'React',
'react-dom': 'ReactDOM',
},
// 自动将 package.json 中 peerDependencies 设为 external(默认 true)
externalPeerDeps: true,
minify: true, // 是否压缩库产物
target: 'es5', // 编译目标
},
});输出规则:
umd→fileName.js,附带library.name全局变量esm→fileName.mjs,启用experiments.outputModulecjs→fileName.cjs
多格式构建:formats 含多项时,defineConfig 返回配置数组,webpack CLI 逐一独立构建。各格式共享同一
output.path,CleanWebpackPlugin自动排除,不会互相删除产物。
类型声明:webpack 原生不生成.d.ts,建议另行运行tsc --emitDeclarationOnly。
Vue 支持
npm i vue-loader vue -Dexport default defineConfig({
vue: true,
// 或传入 vue-loader options
// vue: { hotReload: true, transformAssetUrls: { img: 'src', source: 'src' } }
});Svelte 支持
npm i svelte-loader svelte -Dexport default defineConfig({
svelte: true,
// 或传入 svelte-loader options
// svelte: { emitCss: true, preprocess: require('svelte-preprocess')() }
});打包体积分析
npm i webpack-bundle-analyzer -Dexport default defineConfig({
// 通过环境变量按需开启,避免影响正常构建速度
analyze: !!process.env.ANALYZE,
// 或自定义参数
// analyze: { analyzerMode: 'static', reportFilename: 'report.html', openAnalyzer: false },
});ANALYZE=true npx webpack buildModule Federation
webpack 5 内置,无需额外安装:
// 宿主应用(Host)
export default defineConfig({
federation: {
name: 'host',
remotes: {
app1: 'app1@http://localhost:3001/remoteEntry.js',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
},
});
// 远程应用(Remote)
export default defineConfig({
federation: {
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button',
'./utils': './src/utils/index',
},
shared: {
react: { singleton: true },
},
},
});环境变量
自动加载以下文件(优先级从高到低):.env.[mode].local、.env.[mode]、.env.local、.env。
仅注入以 envPrefix 指定前缀的键到 process.env 和 import.meta.env,NODE_ENV 始终注入。
import { loadEnv } from 'webpack-common';
export default defineConfig(({ mode }) => {
// 手动加载 .env 文件,适用于在 webpack config 中访问变量
const env = loadEnv(mode, ['APP_', 'VITE_'], process.cwd());
console.log(env.APP_API_URL); // 构建时可用
return {
env, // 注入到 DefinePlugin
define: {
__API_URL__: JSON.stringify(env.APP_API_URL || 'http://localhost:3000'),
},
};
});.env 文件示例
# .env
APP_TITLE=My App
# .env.development
APP_API_URL=http://localhost:8080/api
# .env.production
APP_API_URL=https://api.example.com路径配置
export default defineConfig({
base: '/app/', // 绝对路径(部署到子目录)
// base: './', // 相对路径(Electron / 离线场景)
// base: 'auto', // webpack 自动计算
// base: 'https://cdn.example.com/v2/', // CDN 地址
});自动 @ 别名
src/ 下的每个直接子目录会自动生成对应别名:
src/ → @
src/utils/ → @utils
src/components/ → @components
src/hooks/ → @hooks如需覆盖或扩充,可通过 alias 选项手动指定。
默认 resolve.extensions
内置识别以下扩展名(无需在导入时写后缀):
.js .jsx .ts .tsx .mjs .json .vue .svelte通过 extensions 选项追加更多:
export default defineConfig({
extensions: ['.mdx', '.graphql'],
});构建输出
生产构建时自动输出 Vite 风格的构建信息,无需额外配置:
✓ 67 modules transformed.
computing gzip size...
dist/index.html 0.45 kB │ gzip: 0.28 kB
dist/assets/179.8ad6fc18.js 140.81 kB │ gzip: 45.21 kB
dist/assets/main.3e5055c1.js 1.53 kB │ gzip: 0.66 kB
dist/assets/main.47965963.css 0.64 kB │ gzip: 0.36 kB
dist/assets/react.f4beffb2..svg 3.74 kB │ gzip: 1.85 kB
✓ built in 2321ms文件名按类型着色:.js 青色、.css 紫色、.html 绿色、图片黄色、字体蓝色。超过 500 kB 的文件以黄色显示并附 ⚠ 警告。
开发日志
开发服务器就绪后自动打印 Local 与 Network 地址:
➜ Local: http://localhost:3000/
➜ Network: http://192.168.1.100:3000/支持 HTTPS、0.0.0.0 监听、CDN base 路径场景,重新编译后仅在 host/port/base 发生变化时重新打印。
兼容性
- Node >= 16(推荐 Node 18+)
- webpack 5
示例
demo/:CommonJS 项目示例(React + TypeScript,单页面)demo-esm/:ESM 项目示例(React + TypeScript,多页面,函数形式 defineConfig)
示例依赖主库的 node_modules,运行前需先在根目录执行 npm install,再 cd demo && npm run start。
从 v1.x 迁移到 v2.0
1. 编译器从 esbuild 换为 SWC
v2.0 移除了 esbuild-loader 和 EsbuildPlugin,改用 swc-loader。
- npm i esbuild esbuild-loader -D
+ npm i @swc/core swc-loader -D如果你之前在 build.minify 使用了 'esbuild',建议改为 'terser'(生产默认):
- build: { minify: 'esbuild' }
+ build: { minify: 'terser' } // 或直接省略(默认即 true)2. React Fast Refresh 从核心包拆出
v1.x 的 reactRefresh: true 会自动注入 @pmmmwh/react-refresh-webpack-plugin。v2.0 起该功能移动到独立包:
- npm i webpack-common -D
+ npm i webpack-common webpack-plugin-react -D- const { defineConfig } = require('webpack-common');
- module.exports = defineConfig({ reactRefresh: true });
+ const { defineConfig } = require('webpack-common');
+ const react = require('webpack-plugin-react');
+ module.exports = defineConfig({ presets: [react()] });3. plugins → presets
UserConfig.plugins 重命名为 UserConfig.presets,避免与 webpack 原生的 plugins 数组冲突:
- module.exports = defineConfig({ plugins: [myPreset()] });
+ module.exports = defineConfig({ presets: [myPreset()] });原生 webpack plugins 数组仍然可以通过 defineConfig 的额外字段传入,会与生成配置 merge:
module.exports = defineConfig({
presets: [react()],
plugins: [new HtmlWebpackPlugin()], // 原生 webpack plugins,正常工作
});4. 可用的官方 presets
| 包名 | 用途 |
|------|------|
| webpack-plugin-react | React JSX(SWC)+ Fast Refresh |
| webpack-plugin-vue | Vue 3 SFC 支持 |
| webpack-plugin-svelte | Svelte SFC 支持 |
| webpack-plugin-vanilla | 纯 TypeScript/JavaScript(无框架) |
| webpack-plugin-h5 | H5/移动端:viewport 适配、flexible、PostCSS |
| webpack-plugin-mf | Module Federation 微前端 |
5. TypeScript 配置文件
v1.x 推荐使用 tsx,v2.0 统一改为 @swc/register(更轻量,兼容 webpack-cli 的注册机制):
- npm i tsx -D
+ npm i @swc/register -D无需改动 webpack.config.ts 文件本身,webpack-cli 5+ 会自动检测并调用 @swc/register。
许可证
ISC
