
Company News
Jerod Santo Joins Socket as Head of Media
Allow myself to introduce... myself.
@heisea/navim
Advanced tools
面向 single-spa + Vue 2 场景的前端打包工具库。当前实现已经统一到三套引擎:
webpackvitersbuild文档按当前仓库实现编写,重点说明可用命令、配置 schema、引擎差异和兼容行为。本文中把体积分析能力统一称为 analyze,当前 CLI 命令名仍保留为 analyzer,用于兼容既有项目。
>= 20.0.0pnpm 9.15.9single-spanavim.config.js 驱动 Navim推荐把 @heisea/navim 安装到项目依赖中,再通过 npm scripts 或 npx 调用。
pnpm add -D @heisea/navim
或:
npm install -D @heisea/navim
{
"scripts": {
"dev": "navim-service dev --engine webpack",
"dev:vite": "navim-service dev --engine vite",
"dev:rsbuild": "navim-service dev --engine rsbuild",
"build": "navim-service build --engine webpack",
"build:vite": "navim-service build --engine vite",
"build:rsbuild": "navim-service build --engine rsbuild",
"analyze": "navim-service analyzer --engine webpack",
"inspect": "navim-service inspect --engine webpack",
"single-spa:doctor": "navim-service single-spa doctor"
}
}
Navim 依赖一些固定文件位置,缺少这些文件时命令会直接失败。
your-project/
├── build/
│ └── config.js
├── public/
│ └── index.html
├── src/
│ ├── main.js
│ ├── styles/
│ │ └── variables.less
│ └── plugins/
├── .env
├── .env.local
├── .env.development
├── .env.production
└── navim.config.js
关键约定:
navim.config.jsbuild/config.js 必须存在,哪怕只导出空对象public/index.htmlsrc/styles/variables.lesssrc/plugins统一入口是以下四类命令:
navim-service dev --engine webpack|vite|rsbuild
navim-service build --engine webpack|vite|rsbuild
navim-service analyzer --engine webpack|rsbuild
navim-service inspect --engine webpack|vite|rsbuild
说明:
dev 默认引擎是 webpackbuild 默认引擎是 webpackanalyzer 默认引擎是 webpackinspect 默认引擎是 webpackdev 固定按开发模式运行build 只接受 production、pre、test 三种环境值,默认 productionanalyzer 语义上对应 analyzedevnavim-service dev --engine webpack
navim-service dev --engine vite
navim-service dev --engine rsbuild
navim-service dev --engine webpack --micro
navim-service dev --engine webpack --mode sit
公共参数:
--engine <engine>:webpack、vite、rsbuild--micro:微前端模式,主要影响 webpack 和 rsbuild 的 externals 策略--mode <type>:额外读取 .env.<type>buildnavim-service build
navim-service build test
navim-service build pre
navim-service build production --mode sit
navim-service build --engine vite
navim-service build --engine rsbuild
行为说明:
productionproduction、test、pre--mode <type> 会额外读取 .env.<type>webpack、vite、rsbuild 都支持构建analyzernavim-service analyzer
navim-service analyzer --engine webpack
navim-service analyzer --engine rsbuild
说明:
analyzeranalyze 能力webpack 使用 webpack-bundle-analyzerrsbuild 会启用 bundleAnalyzevite 当前不支持分析命令inspectnavim-service inspect
navim-service inspect --engine vite
navim-service inspect --engine rsbuild --env production
navim-service inspect --micro
用途:
entry、alias、proxy、html、output 和 styles 的最终值以下旧命令仍然保留:
navim-service start 等价于 navim-service dev --engine webpacknavim-service vite start 等价于 navim-service dev --engine vitenavim-service single-spa doctor 仍然可用build/config.js(代理配置)build/config.js 是默认的代理配置文件,需导出代理表(路径 → 目标)。如果没有代理需求,也请至少导出空对象:
module.exports = {};
常见写法:
module.exports = {
"/api": {
target: "http://localhost:8080",
changeOrigin: true,
},
};
自
1.2.0起,代理文件路径可通过common.dev.proxy自定义(默认仍为./build/config.js),三引擎(webpack/vite/rsbuild)通用。适用于代理表不在build/config.js、或build/config.js已被业务代码占用的项目:module.exports = { common: { dev: { proxy: "./build/proxy.dev.js" }, }, };
navim.config.jsnavim.config.js 是 Navim 的核心配置文件,支持对象形式和函数形式。当前实现同时兼容两种 schema:
legacy:顶层使用 webpack、vite、rsbuildcurrent:顶层使用 common,再加上 webpack、vite、rsbuild 作为引擎覆盖项vite 和 rsbuild 的 dev / build / inspect 直接消费 commonwebpack 的 dev / build / analyzer 仍然走 legacy webpack 配置块single-spa doctor 也仍然只面向 legacy webpack 配置块webpack 和 vite / rsbuild,当前需要保留一份 legacy webpack 字段,并与 common 中的对应值保持同步common 而不写 legacy webpack.entry、webpack.library、webpack.publicPath,当前并不足以驱动 webpack 实际构建函数会收到两个参数:
NODE_ENVextraInfo
extraInfo.navim_hashmodule.exports = (NODE_ENV, extraInfo) => {
const entry = NODE_ENV === "development" ? "./src/main.dev.js" : "./src/main.js";
const publicPath = NODE_ENV === "development" ? "//localhost:9000/" : "/demo/";
return {
common: {
entry: {
app: entry,
},
output: {
outDir: "dist",
publicPath,
library: {
name: "demo-app",
format: "umd",
},
},
dev: {
host: "127.0.0.1",
port: 9000,
open: false,
headers: {
"Access-Control-Allow-Origin": "*",
},
},
html: {
template: "./public/index.html",
rootElementId: "app",
},
resolve: {
alias: {
"@": "./src",
},
},
styles: {
extract: true,
resources: ["./src/styles/variables.less"],
less: {
javascriptEnabled: true,
},
},
assets: {
copy: [],
},
define: {},
externals: {
dev: {
react: "React",
"react-dom": "ReactDOM",
},
micro: {
vue: "Vue",
"vue-router": "VueRouter",
"element-ui": "ELEMENT",
},
},
micro: {
enabled: false,
type: "single-spa",
cssExtractDoctor: true,
},
},
webpack: {
// webpack 运行时当前仍然依赖这组 legacy 字段
entry: {
app: entry,
},
library: "demo-app",
publicPath,
isExtractCss: true,
styleResourcesLoaderPatterns: ["./src/styles/variables.less"],
extraPlugins: [],
htmlWebpackPlugin: {},
htmlWebpackTagsPlugin: {},
copyWebpackPluginPatterns: [],
},
vite: {
entry: "./src/main.js",
rootElementId: "app",
optimizeDeps: {
include: ["@heisea/brick"],
exclude: ["vue-router", "vuex"],
},
staticCopyTargets: [],
plugins: [],
},
rsbuild: {
plugins: [],
tools: {},
config: {},
},
};
};
如果你不想迁移,旧的顶层写法仍然可用。
module.exports = {
webpack: {
entry: {
app: "./src/main.js",
},
library: "demo-app",
publicPath: "/demo/",
},
vite: {
entry: "./src/main.js",
rootElementId: "app",
},
rsbuild: {
plugins: [],
},
};
common 配置common 是推荐的 normalized 公共配置层,但当前只有一部分字段真正进入了运行时。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
entry | object | {} | 入口定义(构建入口) |
output.outDir | string | dist | 输出目录 |
output.publicPath | string | 无 | 资源前缀 |
output.library.name | string | 无 | UMD 库名(webpack 引擎;rsbuild 引擎在 micro.enabled 时生效) |
output.library.format | string | umd | 输出格式(webpack 引擎;rsbuild 引擎在 micro.enabled 时生效) |
dev.host | string | 127.0.0.1 | 开发服务 host |
dev.port | number | 9000 | 开发服务端口 |
dev.open | boolean | false | 是否自动打开浏览器 |
dev.headers | object | CORS 头 | 开发服务响应头 |
dev.proxy | string | ./build/config.js | 代理配置文件路径(导出代理表);三引擎通用,自 1.2.0 起可自定义 |
dev.entry | object/string | 无 | dev 命令下的入口覆盖(不设则用 common.entry);三引擎通用,自 1.2.0 起支持 |
html.template | string | ./public/index.html | HTML 模板 |
html.rootElementId | string | app | 根节点 id |
html.tags | object | {} | HTML tag 扩展数据 |
resolve.alias | object | 内置别名 | 路径别名 |
resolve.extensions | string[] | 内置扩展 | 解析扩展名 |
styles.extract | boolean | false | 主要给 webpack 的 CSS 抽离开关 |
styles.resources | string[] | [] | Less 全局注入文件 |
styles.less.javascriptEnabled | boolean | true | Less loader 选项 |
assets.copy | Array | [] | 复制静态资源 |
define | object | {} | 常量注入 |
externals.dev | object | react / react-dom | 开发态 externals |
externals.micro | object | 微前端 externals | 微前端外部依赖 |
micro.enabled | boolean | false | 微前端开关 |
micro.type | string | single-spa | 微前端类型 |
micro.cssExtractDoctor | boolean | true | CSS 抽离提示开关 |
vite 和 rsbuild 运行时直接生效:entry、output.publicPath、output.outDir、dev.host、dev.port、dev.open、html.template、resolve.alias、resolve.extensions、styles.resources、styles.less.javascriptEnabled、definevite 运行时直接生效:html.rootElementIdrsbuild 运行时直接生效:dev.headers、assets.copy、externals.dev、externals.micro1.1.0 起在 rsbuild 运行时生效:output.library.name、output.library.format、micro.enabled(开启后产出 single-spa 微前端 UMD 产物:库名 + 入口 app.js + css/app.css 无 hash + 初始不分包)html.tags、styles.extract(rsbuild 生产构建默认抽离 CSS)、micro.type、micro.cssExtractDoctor如果你当前仍然依赖 webpack 命令,请继续在 webpack 配置块里显式声明这些 legacy 字段:
entrylibrarypublicPathisExtractCssstyleResourcesLoaderPatternscopyWebpackPluginPatternshtmlWebpackPluginhtmlWebpackTagsPluginextraPlugins当前实现内置了这些别名:
@ -> ./src~@ -> ./src/plugins -> ./src/pluginsimages -> ./imagesvue -> vue/dist/vue.esm.jsvue$ -> vue/dist/vue.common.js~element-ui -> ./node_modules/element-ui当前实现默认会解析:
.js .json .css .less .vue .mjs .mts .ts .jsx .tsx
webpack 配置webpack 仍然是能力最完整的引擎,也是当前默认引擎。但要注意,当前 webpack 运行时还没有切到 common 驱动模型,仍然直接读取 legacy webpack 配置块。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
extraPlugins | Array | [] | 额外追加到 webpack 配置中的插件实例 |
htmlWebpackPlugin | object | {} | html-webpack-plugin 的配置 |
htmlWebpackTagsPlugin | object | {} | html-webpack-tags-plugin 的配置 |
copyWebpackPluginPatterns | Array | [] | copy-webpack-plugin 的 patterns |
常见示例:
const path = require("path");
const webpack = require("webpack");
module.exports = {
webpack: {
entry: {
app: "./src/main.js",
},
library: "navbar",
publicPath: "/navbar/",
isExtractCss: true,
styleResourcesLoaderPatterns: ["./src/styles/variables.less"],
copyWebpackPluginPatterns: [
{
from: path.resolve(__dirname, "src/static"),
to: path.resolve(__dirname, "dist/static"),
},
],
htmlWebpackPlugin: {
title: "Navim Demo",
},
htmlWebpackTagsPlugin: {
tags: ["https://example.com/runtime.js"],
append: false,
},
extraPlugins: [
new webpack.DefinePlugin({
__BUILD_NAME__: JSON.stringify("navim-demo"),
}),
],
},
};
webpack 内置行为:
dist/dist/app.jsdist/static/js/dist/static/images/dist/static/fonts/libraryTarget 固定为 umd.vue、.css、.less、.styl、.js、.jsxcommon.output.library.*、common.styles.extract、common.assets.copy 等字段目前不会直接驱动 webpack 运行时vite 配置vite 现在同时支持开发和构建。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
entry | string | 自动从 common.entry 兜底 | HTML 入口文件 |
rootElementId | string | app | HTML loading 插件替换的根节点 id |
optimizeDeps | object | include @heisea/brick / exclude vue-router, vuex | Vite 预构建配置 |
staticCopyTargets | Array | 内置主题 CSS 和 element-ui 字体 | 复制静态资源 |
plugins | Array | [] | 额外 Vite 插件 |
内置行为:
configFile=false,不会读取项目自己的 vite.config.*@vitejs/plugin-vue2 和 @vitejs/plugin-vue2-jsxbuild/config.jscommon.output.publicPath 会映射到 Vite 的 basecommon.output.outDir 会映射到 Vite 的 build.outDircommon.resolve.alias 和 common.resolve.extensions 会参与 Vite 解析common.styles.resources 会通过 Less hack 注入@heisea/brick 的主题 CSS 和 element-ui 字体文件示例:
module.exports = {
vite: {
entry: "./src/main.js",
rootElementId: "app",
optimizeDeps: {
include: ["@heisea/brick"],
exclude: ["vue-router", "vuex"],
},
},
};
rsbuild 配置rsbuild 已接入统一 schema,并支持 dev、build、analyze 三条路径。自 1.1.0 起,
rsbuild 引擎的能力已与 webpack 引擎对齐:less/stylus、Vue 2 JSX、@heisea/brick-loader、
微前端 UMD 产物等均由引擎内建,项目通常只需编写 common 配置。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
plugins | Array | [] | 额外 Rsbuild 插件(会与内建插件合并) |
tools | object | {} | Rsbuild tools 合并配置 |
config | object | {} | 最终运行时配置覆盖 |
内置行为:
common.entry 会映射到 source.entrycommon.output.publicPath 会映射到 output.assetPrefixcommon.output.outDir 会映射到 output.distPath.rootcommon.dev.host、common.dev.port、common.dev.open、common.dev.headers 会映射到 servercommon.resolve.alias 和 common.resolve.extensions 会参与解析common.styles.resources 会通过 @rsbuild/plugin-less 的 lessLoaderOptions.additionalData 注入(等价 webpack 的 style-resources-loader)common.assets.copy 会映射到 output.copycommon.externals.dev / common.externals.micro 会按当前命令和微前端状态切换@rsbuild/plugin-vue2、@rsbuild/plugin-less、@rsbuild/plugin-stylus、@rsbuild/plugin-babel(Vue 2 JSX,使用 @vue/babel-preset-jsx,覆盖 .js/.jsx 与 .vue 的 <script> 块).vue 应用 @heisea/brick-loader(仅处理主 .vue 请求,并关闭 vue-loader 的 experimentalInlineMatchResource 以避免冲突);为匹配项目的 @heisea/brick / vue 版本,优先从消费方项目解析 @heisea/brick-loadermodule.parser.javascript.exportsPresence 默认设为 warn(与 webpack 行为一致:导入不存在的命名导出仅告警,不中断构建)index.html当 common.micro.enabled === true(微前端模式,single-spa)时,额外开启:
common.output.library.name,格式取 common.output.library.format(默认 umd)app.js,异步 chunk 输出到 js/splitChunks.chunks: 'async',仅对动态 import() 拆分)css/app.css 且不带 hash(对齐 single-spa-css 加载约定)依赖要求:
@rsbuild/core 以及 @rsbuild/plugin-vue2/plugin-less/plugin-stylus/plugin-babel、@vue/babel-preset-jsx、@heisea/brick-loader 均已作为 Navim 的依赖随包提供,消费方无需单独安装vue 版本匹配的 vue-template-compiler(vue-loader 编译 .vue 必需,版本不一致会报 Vue packages version mismatch)@heisea/brick,建议项目内安装与之匹配的 @heisea/brick-loader(Navim 会优先用项目内版本)示例(single-spa + Vue 2 微前端,最简配置):
module.exports = (NODE_ENV) => ({
common: {
entry: {
app: "./src/main.js",
},
output: {
publicPath: "/demo/",
library: { name: "demo-app", format: "umd" },
},
html: {
template: "./public/index.html",
},
styles: {
// 全局注入 less 变量(等价 style-resources-loader)
resources: ["./src/styles/variables.less"],
},
define: {
"process.env.NODE_ENV": JSON.stringify(NODE_ENV),
},
// 开启微前端产物:UMD + 入口 app.js + css/app.css(无 hash) + 初始不分包
micro: { enabled: true },
},
});
single-spa doctorsingle-spa doctor 仍然是 webpack / legacy 配置链路下的升级工具,不属于三引擎统一能力。
执行边界:
single-spa-vuewebpack.entry 中存在多个入口,会直接退出webpack.entrysingle-spa-css,命令会尝试执行 pnpm add single-spa-css@^2.0.0single-spa-css 相关逻辑vite 和 rsbuild 当前没有对应的 doctor 流程Navim 通过 dotenv + dotenv-expand 加载环境变量。
加载优先级从高到低如下:
.env.[NODE_ENV].local.env.[mode].env.[NODE_ENV].env.local.env说明:
NODE_ENV 由 Navim 命令自身设置mode 来自 --mode <type>开发服务相关变量:
PORT:开发服务端口HOST:开发服务 hostwebpack 构建时会通过 DefinePlugin 注入:
process.env.NODE_ENVprocess.env.navim_hashNAVIM_ 开头的变量,例如 NAVIM_API_BASE示例:
PORT=9000
HOST=127.0.0.1
NAVIM_API_BASE=/api
业务代码中可直接读取:
console.log(process.env.NODE_ENV);
console.log(process.env.navim_hash);
console.log(process.env.NAVIM_API_BASE);
webpack / vite / rsbuild 配置common + 引擎覆盖的写法,但如果仍要跑 webpack,请保留 legacy webpack 字段start、vite start、analyzer、single-spa doctor 都保留为兼容入口inspect 是当前用于查看翻译后运行时配置的推荐命令navim.config.js 必须位于项目根目录build/config.js 必须存在;如果没有代理需求,也请导出空对象public/index.html 必须存在vite 和 rsbuild 都已经支持构建,不再只是开发服务webpack 当前仍然依赖 legacy webpack 配置,不是完全由 common 驱动single-spa doctor 会改写源码,执行前建议先提交或备份single-spa doctor 只支持使用 single-spa-vue 的单入口 webpack 项目single-spa-cssFAQs

Company News
Allow myself to introduce... myself.

Research
/Security News
A Twitch browser extension on Chrome and Firefox forwards users’ live OAuth session tokens through proxies controlled by a Russian bot service.

Security News
Anthropic found biased reasoning and recklessness drove Claude Mythos 5 to publish malware on PyPI and compromise a security vendor.