
Security News
Frontier AI Is Now Critical Infrastructure
The Fable shutdown shows how quickly model access can become a business continuity risk for AI-dependent engineering teams.
@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
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Fable shutdown shows how quickly model access can become a business continuity risk for AI-dependent engineering teams.

Security News
AI agents are pulling packages into environments no scanner is watching, creating exposure before security teams can see it.

Security News
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.