@epxing/cli 0.5.0-beta.0 → 0.5.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/API.md CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  独立工程命令行工具,终端命令名为 epxing。/vite 提供产品构建插件,根入口不提供业务运行时。
4
4
 
5
- 本页对应包版本 `0.5.0-beta.0`。导出名、子路径和签名从当前源码、package.json 与类型声明生成。
5
+ 本页对应包版本 `0.5.0-beta.10`。导出名、子路径和签名从当前源码、package.json 与类型声明生成。
6
6
 
7
7
  ## 安装与使用
8
8
 
9
9
 
10
10
  ```sh
11
- npm install -g @epxing/cli
11
+ npm install -g @epxing/cli@0.5.0-beta.10
12
12
  ```
13
13
 
14
14
 
@@ -18,13 +18,13 @@ epxing --version
18
18
  epxing dev --port 3000
19
19
  epxing build --mode prd
20
20
  epxing lib
21
- epxing create my-product --packages-version 5.3.0-beta.1
22
- epxing migrate . --packages-version 5.3.0-beta.1
21
+ epxing create my-product
22
+ epxing migrate .
23
23
  ```
24
24
 
25
25
  ## 接入约定
26
26
 
27
- 工程命令使用当前项目已安装的依赖和脚本。--dir 指定项目目录;创建/迁移时用 --packages-version 指定 @epxing 平台包版本;--epx-frame 保留旧聚合模式,两者互斥。CLI 采用自己的版本号,独立于其余平台包。完整参数、迁移与发布说明见本包 README。
27
+ 工程命令使用当前项目已安装的依赖和脚本。--dir 指定项目目录;创建/迁移默认使用 @epxing 独立包,版本留空查询最新 beta 并固定到具体版本,没有 beta 时使用 latest。--packages-version 可指定数字版本或标签;--epx-frame 仅显式保留旧聚合模式,两者互斥。CLI 采用自己的版本号,独立于其余平台包。创建和升级在可识别的应用入口预留默认注释的 installLegacyFrame 导入与调用;需要旧远程库共享桥时手动启用,要求 core 5.3.0-beta.5 或以上。升级保留已有启用状态,重复升级不重复插入。完整参数、迁移与发布说明见本包 README。
28
28
 
29
29
  ## 稳定子路径
30
30
 
package/README.md CHANGED
@@ -1,96 +1,119 @@
1
- # @epxing/cli
2
-
3
- [完整公开 API、导入方式与示例](./API.md)
4
-
5
- 独立的工程开发工具,包含交互菜单、开发服务、产品库构建、创建、Vue3 迁移、静态检查和升级技能安装。0.5 测试版新增 `@epxing/*` 独立包产品:用 `--packages-version` 指定平台包版本,CLI 使用自己的版本号。创建和升级会生成产品使用说明;`@epxing/cli/vite` 提供产品构建插件,不依赖聚合包中的构建工具。
6
-
7
- 本批测试版本:`@epxing/cli@0.5.0-beta.0`,平台包 `5.3.0-beta.1`,均使用 npm 公网 `beta` 标签。完整流程见文档站“CLI 创建、升级与产品使用”;各包公开 API 随安装包的 `API.md` 提供。
8
-
9
- ```powershell
10
- npm install -g @epxing/cli@beta --registry https://registry.npmjs.org/
11
- epxing # ↑↓ + Enter 选择;Esc / Ctrl+C 取消
12
- epxing dev --port 3000
13
- epxing build --mode prd
14
- epxing lib # 产品默认懒加载;平台目录构建完整聚合组件库
15
- epxing lib --full # 产品完整打包
16
- epxing lib --lazy # 显式选择懒加载,兼容已有命令
17
- epxing create my-product --packages-version 5.3.0-beta.1
18
- epxing migrate E:/products/old-product --packages-version 5.3.0-beta.1
19
- epxing migrate E:/products/old-product --packages-version 5.3.0-beta.1 --apply
20
- epxing migrate E:/products/old-product --packages-version 5.3.0-beta.1 --transform-vue --to-vite --apply
21
- epxing skill install --dir E:/products/my-product
22
- ```
23
-
24
- 从 0.4.0 起终端命令为 `epxing`,可与旧聚合 CLI 的 `epx` 共存。新产品直接依赖 `@epxing/core`、`@epxing/component`、`@epxing/utils` 等包。创建后进入目录安装依赖,再运行 `npm run dev`;默认端口 8080。工具安装阶段不会运行迁移或改产品文件。
25
-
26
- `--epx-frame <版本或spec>` 保留旧聚合产品模式,与 `--packages-version` 互斥;需要独立包时使用新参数。无参数交互引导默认使用独立包。迁移遇到动态旧接口等无法确定的内容时返回 2,报告人工清单并保留原包模式;不会只切换一半导入。已有业务路由、store 和 install 注册代码保留;已有自定义 `PRODUCT-GUIDE.md` 会保留,另写 `EPXING-PACKAGES-GUIDE.md`。
27
-
28
- ```js
29
- // vite.config.mjs:由创建模板自动配置;远程库构建启用共享映射。
30
- import { frameDeps, epxShared, lazyLib } from '@epxing/cli/vite'
31
- import epxIcons from '@epxing/icons'
32
- // plugins: [frameDeps(), epxShared(), lazyLib({ root, enabled, glob, pkgName })]
33
- ```
34
-
35
- 开发和独立应用直接使用 npm 包。远程库构建通过宿主共享 core、组件、工具和 Vue;宿主需要同版本包并完成组件组安装。`epxing lib` 默认按需构建,`--full` 完整构建;按需部署必须上传整个 `lib/` 目录。`npm run build:app` 构建新模板的独立应用到 `dist/`。实体组件需要配置后端、元数据和权限。
36
-
37
- 使用 fnm/nvm 时,不同 Node 版本的全局包分别安装。切换到日常使用的 Node 版本后更新 CLI,再用 `epxing help` 确认开头为 `@epxing/cli`、`epxing --version` 确认版本。旧仓库的 `pnpm epx` 仍是该仓库自己的脚本。
38
-
39
- ## 命令
40
-
41
- | 命令 | 行为 |
42
- | --- | --- |
43
- | `epxing` / `epxing menu` | 交互选择操作、工程目录、环境、端口和构建方式;管道支持数字输入 |
44
- | `epxing dev` / `epxing serve` | 使用工程 `dev`、`serve` 或 `start` 脚本启动服务 |
45
- | `epxing build` | 使用工程的构建脚本;只有 `build:lib` 的产品自动构建产品库 |
46
- | `epxing lib` / `epxing build --lib` / `epxing lib --lazy` | 产品默认懒加载,优先 `build:lib:lazy`,否则使用 `build:lib` / `lib`;平台聚合库仍完整构建 |
47
- | `epxing lib --full` / `epxing build --lib --full` | 产品完整打包,明确设置 `LAZY_LIB=false`;兼容旧 `--target lib` 脚本 |
48
- | `epxing preview` | 使用 `preview` / `vite:preview`;没有脚本时使用工程本地 Vite |
49
- | `epxing create` | 无参数进入创建引导,也可用参数直接创建 |
50
- | `epxing migrate` / `epxing upgrade` | 无参数引导:目标版本、迁移范围、预览、确认应用 |
51
- | `epxing skill install` | 安装技能,支持自定义目录和明确覆盖 |
52
- | `epxing scan` / `epxing verify` | 迁移风险扫描 / 本地与线上组件清单校验 |
53
- | `epxing theme [目录] [--apply]` | 补修产品/项目主题样式,默认只读预览;迁移时自动执行 |
54
- | `epxing lint [--fix]` / `epxing circular` | 执行工程已有的代码检查、循环依赖检查脚本 |
55
- | `epxing remote` / `epxing pkg <包名\|all>` | 使用平台已有 `build:remote` / `build:pkg` / `build:pkgs` 脚本 |
56
- | `epxing help` / `epxing --version` | 帮助 / 工具版本 |
57
-
58
- 工程命令支持 `--dir <目录>`,默认从当前目录向上找到最近的 `package.json`;不会改为 CLI 全局安装目录。没有项目脚本时,dev/build/preview 可使用项目已安装的 Vite,不会自动下载构建工具。工程仍需先安装自身依赖。
59
-
60
- 产品懒加载构建需要 Vite 库配置(`build.lib`)、Vue 3 编译器和入口中的 `import.meta.glob('./产品目录/**/*.vue', { eager: true })`。CLI 使用产品本地 Vite 加载原配置;未接入按需插件时通过临时配置补入共享插件,不修改产品源码或原配置。已有按需插件保留其 eager 等自定义设置。构建后验证本次生成的 `index.manifest.json`、组件 chunks 和 `index.full.js`,缺少或沿用旧产物会报错,避免完整包被误判为懒加载成功。部署时上传整个输出目录(包含 CSS、chunks 和兜底包)。`--full` 会关闭按需插件;`--full` 与 `--lazy` 互斥。旧 webpack 产品先迁移到 Vite,或使用 `--full` 完整打包。自定义非 Vite 脚本须自行生成标准 `lib/` 按需产物。直接执行 `npm run build:lib` 仍由产品原脚本决定构建方式。
61
-
62
- 0.3.1 同时支持 `{ eager: true, import: 'default' }` 的直接组件入口写法。未显式设置 `assetsInlineLimit` 时,组件拆分保持 Vite 库模式的默认资源内联行为,避免图片改成平台根路径引用。
63
-
64
- `--mode/-m`、`--port/-p` 支持旧的 `-mprd`、`-p3000` 写法。build 优先匹配 `build:<mode>`;`localize` 也匹配 `build:local`,其余情况向构建脚本传入 `--mode`。平台 `build:component` 包含多步构建,不追加 `--mode`,环境由工程脚本统一配置。
65
-
66
- 平台 `epxing build` 保留 `--thin`、`--no-designer`、`--no-dashboard`;产品工程不接受平台裁剪选项。需向工程脚本透传其他参数时使用 `--`,如 `epxing dev -- --host 0.0.0.0`。脚本原有的 pre/post 生命周期、自定义环境和多步构建会保留,失败退出码向上传递。
67
-
68
- `create` 和 `migrate --apply` 自动写入 `runtime: "vue3"`。带参数直接调用时指定 `--packages-version`(独立包)或 `--epx-frame`(旧聚合模式)。迁移默认预览;apply 要求目标 Git 工作树干净。实际执行 `.vue` 转换时才按需安装并缓存 gogocode。标识表示迁移目标,仍需完成转换、构建和业务复测。
69
-
70
- 0.4.0 的迁移会同步适配平台主题:常见静态字号(12/14/16/20px)、圆角(2/4/8px,包括多角简写)和明确的语义颜色改为平台 CSS 变量,保留原值兜底。覆盖 Vue 样式块、template/JSX/render 内联样式和 src 中的 CSS/SCSS/Less;不改 scoped,不导入全局主题,不改圆形、胶囊、图标、打印及动画中的固定设计。动态样式、特殊字号/圆角、缩进式 Sass/Stylus 等列入复核清单,需按技能 E2 继续分析。返回码 2 表示有待复核项;不代表自动修复没有写入。已有 Vue3 工程可运行 `epxing theme <目录>` 预览,审查后加 `--apply`;无须重跑依赖迁移。最终产物须验证平台字号、圆角、明暗与密度切换、懒加载和样式隔离。
71
-
72
- `epxing scan <目录>` 扫描静态风险,`epxing verify <目录> --online <地址|文件>` 对照组件清单。技能安装到 `.claude/skills/epxing-frontend-vue3-migrate/`,可用 `--skills-dir` 指定其他客户端要求的位置。已有技能默认不覆盖;确认替换使用 `--force`。平台基类源码分析仍需准备对应版本源码或文档。
73
-
74
- 在框架源码仓库发布工具,不需要构建平台 `lib/`:
75
-
76
- ```powershell
77
- cd frontend/frame/packages/cli
78
- npm login --registry https://registry.npmjs.org/
79
- # 发布前调整为未发布过的新版本
80
- # npm version <新的CLI版本> --no-git-tag-version
81
- $previousPublicPublish = $env:EPX_PUBLISH_PUBLIC
82
- try {
83
- $env:EPX_PUBLISH_PUBLIC = '1'
84
- npm publish --access public --registry https://registry.npmjs.org/
85
- } finally {
86
- $env:EPX_PUBLISH_PUBLIC = $previousPublicPublish
87
- }
88
- ```
89
-
90
- 发布账号需要拥有 `@epxing` 名称空间的发布权限,并完成 npm 要求的发布身份验证。`publishConfig` 固定公开发布到 npm 公网;上面的命令仅为这次操作启用共享守卫的显式公开发布开关,并在结束后恢复原值。`prepack` 自动构建工具并带入当前技能文件。可在框架根执行 `pnpm build:cli`,或在这里运行 `npm pack` 生成可独立安装的 tgz。技能与 CLI 同版本交付,平台升级不要求工具同步发版;工具规则、模板或技能更新时才发布新 CLI。新平台若改变接口或构建约定,仍需验证并更新相应工具规则。
91
-
92
- 在框架根运行 `npm --prefix packages/cli test`,验证真实 tgz 的离线安装、无平台依赖运行、创建、迁移、扫描和技能安装。
93
-
94
- 首次发布前,需创建或加入 npm 的 `epxing` 组织。可用 `npm org ls epxing --json --registry https://registry.npmjs.org/` 核对组织角色。若发布返回 `403 Two-factor authentication or granular access token with bypass 2fa enabled is required`,表示当前发布凭据未满足 npm 要求;仅 `npm whoami` 成功不代表可以发布。可在 npm 网站创建具有目标 scope 发布权限、启用 `Bypass 2FA` 的细粒度令牌,并配置到本机用户 npm 设置;令牌不写入项目或发布包。参见 [npm 发布身份验证要求](https://docs.npmjs.com/requiring-2fa-for-package-publishing-and-settings-modification/)。
95
-
96
- 令牌的 `Packages and scopes` 权限应选择 `Read and write (publish and stage)`,范围覆盖 `@epxing`;`Read and write (stage only)` 无法直接发布。`Organizations` 里的读写权限只管理组织、团队和成员,不授予组织包的发布权限。首次创建包时需覆盖相应 scope。参见 [npm 令牌权限说明](https://docs.npmjs.com/creating-and-viewing-access-tokens/)。
1
+ # @epxing/cli
2
+
3
+ [完整公开 API、导入方式与示例](./API.md)
4
+
5
+ 独立的工程开发工具,包含交互菜单、开发服务、产品库构建、创建、Vue3 迁移、静态检查和升级技能安装。创建和升级默认使用 `@epxing/*` 独立包,版本留空时查询最新 `beta` 并固定到具体版本,没有 `beta` 时使用 `latest`;可用 `--packages-version` 指定版本或标签。CLI 使用自己的版本号。创建和升级会生成产品使用说明;`@epxing/cli/vite` 提供产品构建插件,不依赖聚合包中的构建工具。
6
+
7
+ 本批测试版本:`@epxing/cli@0.5.0-beta.10`,平台包 `5.3.0-beta.5`,均使用 npm 公网 `beta` 标签。CLI 与平台独立版本,本次不升级平台包。完整流程见文档站“CLI 创建、升级与产品使用”;各包公开 API 随安装包的 `API.md` 提供。
8
+
9
+ `0.5.0-beta.10` 关闭产品库构建的 public 目录复制,避免旧 cmaps 和 index.html 混入 lib。创建模板、已有库配置迁移及 CLI 库构建保持一致;应用构建和源 public 文件保留。动态或展开的库配置仍报告人工核对。修复直接执行 npm 库构建时异步懒加载插件进入自身嵌套构建的问题。
10
+
11
+ `0.5.0-beta.9` 补齐已有标准库入口携带 `--full` 的迁移:升级后 `build:lib` 为 `node build-lib.mjs`,全量构建保留在 `build:lib:full`。预览不改文件,自定义构建命令和自定义入口文件继续保留并报告待接入。
12
+
13
+ `0.5.0-beta.8` 修复 Node 命令行扫描 HTML 实体时的 `document is not defined`:迁移、日期与主题扫描使用 Node 版 Vue 解析器,保留模板中的实体与原格式。旧版本遇到该问题时更新 CLI 后重新执行预览,不删除实体或添加假的 document。
14
+
15
+ `0.5.0-beta.7` 合并薪酬升级中的对象回显、必填校验和 ID 序列化注意事项,随技能交付参数路径修复脚本。创建与升级的标准工程默认懒加载,使用 `npm run build:lib --full` 或 `npm run build:lib:full` 全量构建。`epxing skill install` 安装该版本技能;已有技能默认受到保护,更新前先比较并保留产品自定义内容。保留主题及全局 CSS 变量逐组件验收与跨会话缺陷回归要求。
16
+
17
+ 创建和升级会在可识别的独立包应用入口中预留默认注释的 `import { installLegacyFrame } from '@epxing/core'` 与 `installLegacyFrame(app)`。仅在需要加载依赖 `window.frame` 的旧远程库时手动取消两处注释,要求 core 5.3.0-beta.5 或以上版本;调用放在所需组件包安装后、远程库加载前。升级保留产品自定义代码及已经启用的调用,重复升级不重复添加提示。
18
+
19
+ 平台包从 `5.3.0-beta.2` 起自动加载自身样式,产品无需手动引入各包的 `style.css`。创建和迁移使用此版本时,CLI 不再添加这些导入;指定旧版本时仍保留显式样式以兼容旧包。标签会先解析成具体版本再选择模板。已有显式导入可以保留,产品覆盖样式放在框架导入之后。
20
+
21
+ ```powershell
22
+ npm install -g @epxing/cli@beta --registry https://registry.npmjs.org/
23
+ epxing # ↑↓ + Enter 选择;Esc / Ctrl+C 取消
24
+ epxing dev --port 3000
25
+ epxing build --mode prd
26
+ epxing lib # 产品默认懒加载;平台目录构建完整聚合组件库
27
+ epxing lib --full # 产品完整打包
28
+ npm run build:lib # 新建或升级后的标准工程:默认懒加载
29
+ npm run build:lib --full # 标准工程:显式全量(也可用 build:lib:full)
30
+ epxing lib --lazy # 显式选择懒加载,兼容已有命令
31
+ epxing create my-product
32
+ epxing migrate ./old-product
33
+ epxing migrate ./old-product --apply
34
+ epxing migrate ./old-product --transform-vue --to-vite --apply
35
+ # 指定固定版本时:epxing create my-product --packages-version 5.3.0-beta.2
36
+ epxing skill install --dir E:/products/my-product
37
+ ```
38
+
39
+ 从 0.4.0 起终端命令为 `epxing`,可与旧聚合 CLI 的 `epx` 共存。新产品直接依赖 `@epxing/core`、`@epxing/components`、`@epxing/utils` 等包。创建后进入目录安装依赖,再运行 `npm run dev`;默认端口 8080。工具安装阶段不会运行迁移或改产品文件。
40
+
41
+ 新建产品的 `src/main.js` 使用 `createApp({ router: createFrameRouter() })`,安装 Components、Business 和产品插件,默认运行平台登录、菜单与系统首页。先在 `.env.development.local` 配置实际后端和应用参数。产品组件放入自动收集目录,`src/index.js` 仍是独立产品库入口,不包含本地应用启动代码。
42
+
43
+ 从 `0.5.0-beta.4` 起,旧 CLI 生成的计数欢迎页在 main.js 与 App.vue 都保持原始模板时可由 upgrade 自动修复;自定义入口不覆盖。`epxing scan` 的 R4 提示尚未修复的原始欢迎页。升级技能区分 Vue2/webpack、Vue3 聚合包及已有独立包工程,报告补充平台启动验收。
44
+
45
+ 组件校验 `epxing verify` 优先读取 lib 的清单或产物,无产物时按产品收集入口列源码候选,支持常规静态 glob 与 require.context;无法确定的动态规则要求先构建。源码候选不能代替产物及真实平台验收。
46
+
47
+ 升级 CLI 后可用 `epxing skill install --dir <产品目录>` 安装新版升级技能。已有技能会受保护而退出;确认并保留产品自定义内容后,才使用 `--force` 替换。技能和命令随同一 CLI 版本交付。
48
+
49
+ `--epx-frame <版本或spec>` 仅用于显式选择旧聚合产品模式,与 `--packages-version` 互斥。普通命令与无参数交互引导均默认使用独立包,版本输入可直接回车。显式数字版本不查询网络;默认版本与标签需查询 npm,查询失败会退出,可通过固定版本离线生成。迁移遇到动态旧接口等无法确定的内容时返回 2,报告人工清单并保留原包模式;不会只切换一半导入。已有业务路由、store 和 install 注册代码保留;已有自定义 `PRODUCT-GUIDE.md` 会保留,另写 `EPXING-PACKAGES-GUIDE.md`。
50
+
51
+ ```js
52
+ // vite.config.mjs:由创建模板自动配置;远程库构建启用共享映射。
53
+ import { frameDeps, epxShared, lazyLib } from '@epxing/cli/vite'
54
+ import epxIcons from '@epxing/icons'
55
+ // plugins: [frameDeps(), epxShared(), lazyLib({ root, enabled, glob, pkgName })]
56
+ ```
57
+
58
+ 开发和独立应用直接使用 npm 包。远程库构建通过宿主共享 core、组件、工具和 Vue;宿主需要同版本包并完成组件组安装。`epxing lib` 默认按需构建,`--full` 完整构建;按需部署必须上传整个 `lib/` 目录。`npm run build:app` 构建新模板的独立应用到 `dist/`。实体组件需要配置后端、元数据和权限。
59
+
60
+ 使用 fnm/nvm 时,不同 Node 版本的全局包分别安装。切换到日常使用的 Node 版本后更新 CLI,再用 `epxing help` 确认开头为 `@epxing/cli`、`epxing --version` 确认版本。旧仓库的 `pnpm epx` 仍是该仓库自己的脚本。
61
+
62
+ ## 命令
63
+
64
+ | 命令 | 行为 |
65
+ | --- | --- |
66
+ | `epxing` / `epxing menu` | 交互选择操作、工程目录、环境、端口和构建方式;管道支持数字输入 |
67
+ | `epxing dev` / `epxing serve` | 使用工程 `dev`、`serve` 或 `start` 脚本启动服务 |
68
+ | `epxing build` | 使用工程的构建脚本;只有 `build:lib` 的产品自动构建产品库 |
69
+ | `epxing lib` / `epxing build --lib` / `epxing lib --lazy` | 产品默认懒加载,优先 `build:lib:lazy`,否则使用 `build:lib` / `lib`;平台聚合库仍完整构建 |
70
+ | `epxing lib --full` / `epxing build --lib --full` | 产品完整打包,明确设置 `LAZY_LIB=false`;兼容旧 `--target lib` 脚本 |
71
+ | `epxing preview` | 使用 `preview` / `vite:preview`;没有脚本时使用工程本地 Vite |
72
+ | `epxing create` | 无参数进入创建引导,也可用参数直接创建 |
73
+ | `epxing migrate` / `epxing upgrade` | 无参数引导:目标版本、迁移范围、预览、确认应用 |
74
+ | `epxing skill install` | 安装技能,支持自定义目录和明确覆盖 |
75
+ | `epxing scan` / `epxing verify` | 迁移风险扫描 / 本地与线上组件清单校验 |
76
+ | `epxing theme [目录] [--apply]` | 补修产品/项目主题样式,默认只读预览;迁移时自动执行 |
77
+ | `epxing lint [--fix]` / `epxing circular` | 执行工程已有的代码检查、循环依赖检查脚本 |
78
+ | `epxing remote` / `epxing pkg <包名\|all>` | 使用平台已有 `build:remote` / `build:pkg` / `build:pkgs` 脚本 |
79
+ | `epxing help` / `epxing --version` | 帮助 / 工具版本 |
80
+
81
+ 工程命令支持 `--dir <目录>`,默认从当前目录向上找到最近的 `package.json`;不会改为 CLI 全局安装目录。没有项目脚本时,dev/build/preview 可使用项目已安装的 Vite,不会自动下载构建工具。工程仍需先安装自身依赖。
82
+
83
+ 产品懒加载构建需要 Vite 库配置(`build.lib`)、Vue 3 编译器和入口中的 `import.meta.glob('./产品目录/**/*.vue', { eager: true })`。CLI 使用产品本地 Vite 加载原配置;未接入按需插件时通过临时配置补入共享插件,不修改产品源码或原配置。已有按需插件保留其 eager 等自定义设置。构建后验证本次生成的 `index.manifest.json`、组件 chunks 和 `index.full.js`,缺少或沿用旧产物会报错,避免完整包被误判为懒加载成功。部署时上传整个输出目录(包含 CSS、chunks 和兜底包)。`--full` 会关闭按需插件;`--full` 与 `--lazy` 互斥。旧 webpack 产品先迁移到 Vite,或使用 `--full` 完整打包。自定义非 Vite 脚本须自行生成标准 `lib/` 按需产物。直接执行 `npm run build:lib` 仍由产品原脚本决定构建方式。
84
+
85
+ 0.3.1 同时支持 `{ eager: true, import: 'default' }` 的直接组件入口写法。未显式设置 `assetsInlineLimit` 时,组件拆分保持 Vite 库模式的默认资源内联行为,避免图片改成平台根路径引用。
86
+
87
+ `--mode/-m`、`--port/-p` 支持旧的 `-mprd`、`-p3000` 写法。build 优先匹配 `build:<mode>`;`localize` 也匹配 `build:local`,其余情况向构建脚本传入 `--mode`。平台 `build:component` 包含多步构建,不追加 `--mode`,环境由工程脚本统一配置。
88
+
89
+ 平台 `epxing build` 保留 `--thin`、`--no-designer`、`--no-dashboard`;产品工程不接受平台裁剪选项。需向工程脚本透传其他参数时使用 `--`,如 `epxing dev -- --host 0.0.0.0`。脚本原有的 pre/post 生命周期、自定义环境和多步构建会保留,失败退出码向上传递。
90
+
91
+ `create` 和 `migrate --apply` 自动写入 `runtime: "vue3"`。省略版本默认选择最新独立包;`--packages-version` 可固定版本,`--epx-frame` 显式选择旧聚合模式。迁移默认预览;apply 要求目标 Git 工作树干净。实际执行 `.vue` 转换时才按需安装并缓存 gogocode。标识表示迁移目标,仍需完成转换、构建和业务复测。
92
+
93
+ 0.4.0 的迁移会同步适配平台主题:常见静态字号(12/14/16/20px)、圆角(2/4/8px,包括多角简写)和明确的语义颜色改为平台 CSS 变量,保留原值兜底。覆盖 Vue 样式块、template/JSX/render 内联样式和 src 中的 CSS/SCSS/Less;不改 scoped,不导入全局主题,不改圆形、胶囊、图标、打印及动画中的固定设计。动态样式、特殊字号/圆角、缩进式 Sass/Stylus 等列入复核清单,需按技能 E2 继续分析。返回码 2 表示有待复核项;不代表自动修复没有写入。已有 Vue3 工程可运行 `epxing theme <目录>` 预览,审查后加 `--apply`;无须重跑依赖迁移。最终产物须验证平台字号、圆角、明暗与密度切换、懒加载和样式隔离。
94
+
95
+ `epxing scan <目录>` 扫描静态风险,`epxing verify <目录> --online <地址|文件>` 对照组件清单。技能安装到 `.claude/skills/epxing-frontend-vue3-migrate/`,可用 `--skills-dir` 指定其他客户端要求的位置。已有技能默认不覆盖;确认替换使用 `--force`。平台基类源码分析仍需准备对应版本源码或文档。
96
+
97
+ 在框架源码仓库发布工具,不需要构建平台 `lib/`:
98
+
99
+ ```powershell
100
+ cd frontend/frame/packages/cli
101
+ npm login --registry https://registry.npmjs.org/
102
+ # 发布前调整为未发布过的新版本
103
+ # npm version <新的CLI版本> --no-git-tag-version
104
+ $previousPublicPublish = $env:EPX_PUBLISH_PUBLIC
105
+ try {
106
+ $env:EPX_PUBLISH_PUBLIC = '1'
107
+ npm publish --access public --registry https://registry.npmjs.org/
108
+ } finally {
109
+ $env:EPX_PUBLISH_PUBLIC = $previousPublicPublish
110
+ }
111
+ ```
112
+
113
+ 发布账号需要拥有 `@epxing` 名称空间的发布权限,并完成 npm 要求的发布身份验证。`publishConfig` 固定公开发布到 npm 公网;上面的命令仅为这次操作启用共享守卫的显式公开发布开关,并在结束后恢复原值。`prepack` 自动构建工具并带入当前技能文件。可在框架根执行 `pnpm build:cli`,或在这里运行 `npm pack` 生成可独立安装的 tgz。技能与 CLI 同版本交付,平台升级不要求工具同步发版;工具规则、模板或技能更新时才发布新 CLI。新平台若改变接口或构建约定,仍需验证并更新相应工具规则。
114
+
115
+ 在框架根运行 `npm --prefix packages/cli test`,验证真实 tgz 的离线安装、无平台依赖运行、创建、迁移、扫描和技能安装。
116
+
117
+ 首次发布前,需创建或加入 npm 的 `epxing` 组织。可用 `npm org ls epxing --json --registry https://registry.npmjs.org/` 核对组织角色。若发布返回 `403 Two-factor authentication or granular access token with bypass 2fa enabled is required`,表示当前发布凭据未满足 npm 要求;仅 `npm whoami` 成功不代表可以发布。可在 npm 网站创建具有目标 scope 发布权限、启用 `Bypass 2FA` 的细粒度令牌,并配置到本机用户 npm 设置;令牌不写入项目或发布包。参见 [npm 发布身份验证要求](https://docs.npmjs.com/requiring-2fa-for-package-publishing-and-settings-modification/)。
118
+
119
+ 令牌的 `Packages and scopes` 权限应选择 `Read and write (publish and stage)`,范围覆盖 `@epxing`;`Read and write (stage only)` 无法直接发布。`Organizations` 里的读写权限只管理组织、团队和成员,不授予组织包的发布权限。首次创建包时需覆盖相应 scope。参见 [npm 令牌权限说明](https://docs.npmjs.com/creating-and-viewing-access-tokens/)。
package/dist/cli.mjs CHANGED
@@ -6,6 +6,7 @@ import { spawnSync } from 'node:child_process'
6
6
  import { fileURLToPath, pathToFileURL } from 'node:url'
7
7
  import { findProject, runProject } from './project.mjs'
8
8
  import { Prompts } from './prompts.mjs'
9
+ import { resolvePlatformVersion } from './platform-version.mjs'
9
10
 
10
11
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
11
12
  const payload = path.join(packageRoot, 'dist')
@@ -31,8 +32,7 @@ function requireTarget (args) {
31
32
  const packagesVersion = takeOption(args, '--packages-version')
32
33
  const target = takeOption(args, '--epx-frame')
33
34
  if (packagesVersion && target) throw new Error('--packages-version 与 --epx-frame 不能同时指定')
34
- if (!target && !packagesVersion) throw new Error('请用 --packages-version 指定 @epxing 包版本;--epx-frame 仅用于旧聚合模式。CLI 与平台分别版本。')
35
- return { value: packagesVersion || target, independent: Boolean(packagesVersion) }
35
+ return { value: packagesVersion || target, independent: !target }
36
36
  }
37
37
 
38
38
  function runTool (script, args, cwd) {
@@ -48,14 +48,17 @@ function installSkill (args, cwd) {
48
48
  const unknown = args.filter(arg => arg !== '--force')
49
49
  if (unknown.length) throw new Error(`不支持的参数:${unknown.join(' ')}`)
50
50
  const dest = path.join(custom ? path.resolve(dir, custom) : path.join(dir, '.claude/skills'), skillName)
51
- const files = ['SKILL.md', 'pitfalls.md']
51
+ const files = ['SKILL.md', 'pitfalls.md', 'scripts/fix-eval-paths.cjs']
52
52
  if (!force && files.some(file => fs.existsSync(path.join(dest, file)))) {
53
53
  throw new Error(`技能已存在:${dest}。如需替换,核对自定义内容后使用 --force。`)
54
54
  }
55
55
  // 先读齐资源,再写入,避免缺少发布资源时只安装一半。
56
56
  const contents = files.map(file => fs.readFileSync(path.join(payload, 'skills', skillName, file)))
57
57
  fs.mkdirSync(dest, { recursive: true })
58
- files.forEach((file, index) => fs.writeFileSync(path.join(dest, file), contents[index]))
58
+ files.forEach((file, index) => {
59
+ fs.mkdirSync(path.dirname(path.join(dest, file)), { recursive: true })
60
+ fs.writeFileSync(path.join(dest, file), contents[index])
61
+ })
59
62
  console.log(`✓ 已安装技能:${dest}`)
60
63
  return 0
61
64
  }
@@ -76,7 +79,7 @@ async function interactive (cwd, action) {
76
79
  if (!action) {
77
80
  action = await prompts.select('选择操作', choices([
78
81
  ['dev 启动开发服务', 'dev'], ['build 工程打包', 'build'], ['lib 产品库 / 平台组件库打包', 'lib'],
79
- ['preview 预览构建结果', 'preview'], ['create 创建产品 / 项目', 'create'], ['migrate 升级到 Vue 3', 'migrate'],
82
+ ['preview 预览构建结果', 'preview'], ['create 创建产品 / 项目', 'create'], ['migrate 产品升级 / Vue 3 迁移', 'migrate'],
80
83
  ['skill 安装升级技能', 'skill'], ['check 风险扫描 / 组件校验 / 代码检查', 'check'],
81
84
  ['advanced 平台独立包 / 远程模块构建', 'advanced'], ['help 查看命令帮助', 'help'], ['exit 退出', 'exit']
82
85
  ]))
@@ -85,13 +88,13 @@ async function interactive (cwd, action) {
85
88
  if (action === 'help') return dispatch(['help'])
86
89
  if (action === 'create') {
87
90
  const name = await prompts.required('产品名或目标路径')
88
- const target = await prompts.required('目标 @epxing 包版本', '5.3.0-beta.1')
91
+ const target = await prompts.text('目标 @epxing 包版本(留空使用最新 beta)')
89
92
  const dir = await prompts.text('生成目录', name)
90
- return dispatch(['create', name, '--dir', dir, '--packages-version', target])
93
+ return dispatch(['create', name, '--dir', dir, ...(target ? ['--packages-version', target] : [])])
91
94
  }
92
95
  if (action === 'migrate') {
93
96
  const dir = await prompts.required('待升级工程目录', '.')
94
- const target = await prompts.required('目标 @epxing 包版本', '5.3.0-beta.1')
97
+ const target = await resolvePlatformVersion(await prompts.text('目标 @epxing 包版本(留空使用最新 beta)'))
95
98
  const flags = await prompts.select('迁移范围', choices([
96
99
  ['依赖与入口迁移', []], ['依赖、入口与 Vue 组件转换', ['--transform-vue']],
97
100
  ['依赖、Vue 组件及 Vite 构建迁移', ['--transform-vue', '--to-vite']]
@@ -175,8 +178,8 @@ export async function main (argv = process.argv.slice(2), cwd = process.env.INIT
175
178
  epxing lib [--full | --lazy] [-m <模式>] [--dir <目录>] 产品默认懒加载,--full 完整打包;平台聚合库保持完整
176
179
  epxing build --lib 同 epxing lib
177
180
  epxing preview [-p <端口>] [--dir <目录>]
178
- epxing create <名称|路径> --packages-version <平台包版本> [--dir <目录>]
179
- epxing migrate [项目目录] --packages-version <平台包版本> [--apply] [--transform-vue] [--to-vite]
181
+ epxing create <名称|路径> [--packages-version <平台包版本>] [--dir <目录>]
182
+ epxing migrate [项目目录] [--packages-version <平台包版本>] [--apply] [--transform-vue] [--to-vite]
180
183
  epxing scan [项目目录]
181
184
  epxing theme [项目目录] [--apply] 主题变量补修,默认只读;迁移时自动执行
182
185
  epxing verify [项目目录] [--online <线上JS地址|文件>]
@@ -189,9 +192,12 @@ export async function main (argv = process.argv.slice(2), cwd = process.env.INIT
189
192
 
190
193
  dev / build / lib 等执行当前工程的 package.json 脚本,使用工程本地依赖。
191
194
  工程命令可用 -- 后的参数透传给脚本;serve / upgrade 分别是 dev / migrate 的别名。
192
- create、migrate 不带参数时进入独立包引导;直接带参数时 --packages-version 必填。
195
+ create、migrate 默认使用 @epxing/core、@epxing/components 等独立包。
196
+ 版本留空时查询最新 beta 并固定具体版本;没有 beta 时使用 latest。可用 --packages-version 固定版本或指定标签。
193
197
  --epx-frame <版本或spec> 保留旧聚合模式,与 --packages-version 互斥。
194
198
  创建和升级自动写入 runtime: "vue3"。迁移默认 dry-run,--apply 才落盘。
199
+ create 默认启动平台系统;upgrade 可修复原始计数欢迎页入口,自定义入口保留。
200
+ Vue 3 工程通常无需 --transform-vue;升级后验证平台登录、菜单、首页和产品组件,再交付 lib/。
195
201
  工具不会自动安装平台依赖;.vue 转换工具仅在执行 --apply --transform-vue 时下载并缓存。`)
196
202
  return 0
197
203
  }
@@ -207,11 +213,12 @@ create、migrate 不带参数时进入独立包引导;直接带参数时 --pac
207
213
  const target = requireTarget(args)
208
214
  const chosenDir = takeOption(args, '--dir')
209
215
  const nameOrPath = args.shift()
210
- if (!nameOrPath || args.length || nameOrPath.startsWith('-')) throw new Error('用法:epxing create <名称|路径> --epx-frame <目标版本> [--dir <目录>]')
216
+ if (!nameOrPath || args.length || nameOrPath.startsWith('-')) throw new Error('用法:epxing create <名称|路径> [--packages-version <版本>] [--dir <目录>]')
211
217
  const dir = path.resolve(cwd, chosenDir || nameOrPath)
212
218
  const name = /[\\/]/.test(nameOrPath) ? path.basename(path.resolve(cwd, nameOrPath)) : nameOrPath
213
219
  const { scaffold } = await import(pathToFileURL(path.join(payload, 'tools/epx-create/scaffold.mjs')).href)
214
220
  const cliVersion = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')).version
221
+ if (target.independent) target.value = await resolvePlatformVersion(target.value)
215
222
  scaffold({ name, dir, ...(target.independent ? { packagesVersion: target.value } : { epxFrameSpec: target.value }), cliVersion })
216
223
  return 0
217
224
  }
@@ -221,6 +228,7 @@ create、migrate 不带参数时进入独立包引导;直接带参数时 --pac
221
228
  if (dirs.length > 1) throw new Error('一次迁移一个项目目录')
222
229
  const dir = dirs[0] || '.'
223
230
  const cliVersion = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')).version
231
+ if (target.independent) target.value = await resolvePlatformVersion(target.value)
224
232
  return runTool('epx-migrate/migrate.mjs', [path.resolve(cwd, dir), ...args.filter(arg => arg !== dir), target.independent ? '--packages-version' : '--epx-frame', target.value, ...(target.independent ? ['--cli-version', cliVersion] : [])], cwd)
225
233
  }
226
234
  if (command === 'theme') {
package/dist/lazy-lib.mjs CHANGED
@@ -1,54 +1,54 @@
1
- import h from"node:fs";import y from"node:path";import{build as B}from"epxing:project-vite";import j from"node:fs";import v from"node:path";import{parse as V,babelParse as T}from"epxing:project-sfc";function W(e){return j.readFileSync(e,"utf8").split(`\r
1
+ import h from"node:fs";import y from"node:path";import{build as B}from"epxing:project-vite";import j from"node:fs";import v from"node:path";import{parse as T,babelParse as U}from"epxing:project-sfc";function W(e){return j.readFileSync(e,"utf8").split(`\r
2
2
  `).join(`
3
3
  `)}function G(e){let s=e.split(`\r
4
4
  `).join(`
5
- `),n="";try{let{descriptor:r}=V(s);n=r.script&&r.script.content||r.scriptSetup&&r.scriptSetup.content||""}catch{return null}if(!n)return null;try{let i=T(n,{sourceType:"module",plugins:["jsx","typescript","decorators-legacy"]}).program.body,t=l=>{if(!l||l.type!=="ObjectExpression")return null;for(let u of l.properties){if(u.type!=="ObjectProperty"||u.computed)continue;if((u.key.type==="Identifier"?u.key.name:u.key.type==="StringLiteral"?u.key.value:null)==="name"&&u.value.type==="StringLiteral")return u.value.value}return null},a=i.find(l=>l.type==="ExportDefaultDeclaration");if(!a)return null;let o=t(a.declaration);if(o)return o;if(a.declaration.type==="Identifier"){let l=a.declaration.name;for(let u of i)if(u.type==="VariableDeclaration"){for(let m of u.declarations)if(m.id.type==="Identifier"&&m.id.name===l){let b=t(m.init);if(b)return b}}}if(a.declaration.type==="CallExpression")for(let l of a.declaration.arguments){let u=t(l);if(u)return u}return null}catch{return null}}function K(e){return e.replace(/(\.\/|\.vue|\/)/g,"")}function O(e,s){let n=v.resolve(e,s),r=[],i=t=>{let a=j.readdirSync(t,{withFileTypes:!0}).sort((o,l)=>o.name<l.name?-1:1);for(let o of a){let l=v.join(t,o.name);if(o.isDirectory())i(l);else if(o.name.endsWith(".vue")){let m="./"+v.relative(e,l).split(v.sep).join("/");r.push({globKey:m,file:l,key:G(W(l))||K(m)})}}};return j.existsSync(n)&&i(n),r.sort((t,a)=>t.globKey<a.globKey?-1:1)}function z(e){let s=new Map;for(let n of e){if(s.has(n.key))throw new Error(`[lazy-lib] \u7EC4\u4EF6\u6CE8\u518C\u540D\u51B2\u7A81\uFF1A'${n.key}' \u540C\u65F6\u6765\u81EA
6
- ${s.get(n.key)}
7
- ${n.file}
8
- \u5355\u4F53\u5F62\u6001\u4E0B\u662F\u540E\u8005\u9759\u9ED8\u8986\u76D6\u524D\u8005\uFF1B\u6309\u9700\u5F62\u6001\u4E0B\u4E24\u4E2A chunk \u62A2\u540C\u4E00\u4E2A\u540D\u5B57\uFF0C\u5FC5\u987B\u5148\u6539\u6389\u5176\u4E2D\u4E00\u4E2A\u7EC4\u4EF6\u7684 name\uFF08\u6216\u6587\u4EF6\u8DEF\u5F84\uFF09\u3002`);s.set(n.key,n.file)}return e}var U=[{test:e=>e==="vue",global:"window.frame && window.frame.Vue"},{test:e=>e==="vuex",global:"window.frame && window.frame.vuex"},{test:e=>e==="vue-router",global:"window.frame && window.frame.router"},{test:e=>e==="epx-frame"||e.startsWith("epx-frame/"),global:"window.epxFrame"}],L=/^[A-Za-z_$][\w$]*$/,R=(e,s)=>{if(!s)return null;let n=typeof s=="function"?s(e):s[e];return typeof n=="string"&&n?n:null};function q(e,s){let n=U.find(i=>i.test(e));if(n)return n.global;let r=R(e,s);if(r)return`window.${r}`;throw new Error(`[lazy-lib] external '${e}' \u6CA1\u6709\u5BF9\u5E94\u7684\u8FD0\u884C\u65F6\u5168\u5C40\u6620\u5C04\u3002
5
+ `),t="";try{let{descriptor:r}=T(s);t=r.script&&r.script.content||r.scriptSetup&&r.scriptSetup.content||""}catch{return null}if(!t)return null;try{let i=U(t,{sourceType:"module",plugins:["jsx","typescript","decorators-legacy"]}).program.body,n=l=>{if(!l||l.type!=="ObjectExpression")return null;for(let u of l.properties){if(u.type!=="ObjectProperty"||u.computed)continue;if((u.key.type==="Identifier"?u.key.name:u.key.type==="StringLiteral"?u.key.value:null)==="name"&&u.value.type==="StringLiteral")return u.value.value}return null},a=i.find(l=>l.type==="ExportDefaultDeclaration");if(!a)return null;let o=n(a.declaration);if(o)return o;if(a.declaration.type==="Identifier"){let l=a.declaration.name;for(let u of i)if(u.type==="VariableDeclaration"){for(let m of u.declarations)if(m.id.type==="Identifier"&&m.id.name===l){let b=n(m.init);if(b)return b}}}if(a.declaration.type==="CallExpression")for(let l of a.declaration.arguments){let u=n(l);if(u)return u}return null}catch{return null}}function K(e){return e.replace(/(\.\/|\.vue|\/)/g,"")}function O(e,s){let t=v.resolve(e,s),r=[],i=n=>{let a=j.readdirSync(n,{withFileTypes:!0}).sort((o,l)=>o.name<l.name?-1:1);for(let o of a){let l=v.join(n,o.name);if(o.isDirectory())i(l);else if(o.name.endsWith(".vue")){let m="./"+v.relative(e,l).split(v.sep).join("/");r.push({globKey:m,file:l,key:G(W(l))||K(m)})}}};return j.existsSync(t)&&i(t),r.sort((n,a)=>n.globKey<a.globKey?-1:1)}function z(e){let s=new Map;for(let t of e){if(s.has(t.key))throw new Error(`[lazy-lib] \u7EC4\u4EF6\u6CE8\u518C\u540D\u51B2\u7A81\uFF1A'${t.key}' \u540C\u65F6\u6765\u81EA
6
+ ${s.get(t.key)}
7
+ ${t.file}
8
+ \u5355\u4F53\u5F62\u6001\u4E0B\u662F\u540E\u8005\u9759\u9ED8\u8986\u76D6\u524D\u8005\uFF1B\u6309\u9700\u5F62\u6001\u4E0B\u4E24\u4E2A chunk \u62A2\u540C\u4E00\u4E2A\u540D\u5B57\uFF0C\u5FC5\u987B\u5148\u6539\u6389\u5176\u4E2D\u4E00\u4E2A\u7EC4\u4EF6\u7684 name\uFF08\u6216\u6587\u4EF6\u8DEF\u5F84\uFF09\u3002`);s.set(t.key,t.file)}return e}var R=[{test:e=>e==="vue",global:"window.frame && window.frame.Vue"},{test:e=>e==="vuex",global:"window.frame && window.frame.vuex"},{test:e=>e==="vue-router",global:"window.frame && window.frame.router"},{test:e=>e==="epx-frame"||e.startsWith("epx-frame/"),global:"window.epxFrame"}],L=/^[A-Za-z_$][\w$]*$/,q=(e,s)=>{if(!s)return null;let t=typeof s=="function"?s(e):s[e];return typeof t=="string"&&t?t:null};function Z(e,s){let t=R.find(i=>i.test(e));if(t)return t.global;let r=q(e,s);if(r)return`window.${r}`;throw new Error(`[lazy-lib] external '${e}' \u6CA1\u6709\u5BF9\u5E94\u7684\u8FD0\u884C\u65F6\u5168\u5C40\u6620\u5C04\u3002
9
9
  ESM chunk \u91CC\u7684\u88F8\u8BF4\u660E\u7B26\u6D4F\u89C8\u5668\u89E3\u6790\u4E0D\u4E86\uFF0C\u5FC5\u987B\u7ECF shim \u6865\u5230 window \u4E0A\u7684\u5168\u5C40\u3002
10
10
  \u5E73\u53F0\u5185\u7F6E\u6620\u5C04\uFF1Avue \u2192 window.frame.Vue\uFF1Bvuex \u2192 window.frame.vuex\uFF1B
11
11
  vue-router \u2192 window.frame.router\uFF1Bepx-frame\uFF08\u542B\u5B50\u8DEF\u5F84\uFF09\u2192 window.epxFrame\u3002
12
12
  \u4E09\u6761\u51FA\u8DEF\uFF1A
13
13
  \u2460 \u5B83\u7531**\u4EA7\u54C1\u9879\u76EE**\u77E5\u9053\u5168\u5C40\u540D \u2192 \u5728 vite.config.mjs \u7684 output.globals \u91CC\u7ED9 '${e}' \u914D\u4E0A\uFF08\u63A8\u8350\uFF09\uFF1B
14
14
  \u2461 \u5B83\u7531**\u5E73\u53F0**\u63D0\u4F9B \u2192 \u53BB build/lazy-lib/gen-shims.mjs \u7684 GLOBALS \u8865\u4E00\u6761\u6620\u5C04\uFF1B
15
- \u2462 \u5B83\u4E0D\u8BE5\u88AB external\uFF08\u7EC4\u4EF6\u771F\u7684\u9700\u8981\u628A\u5B83\u6253\u8FDB\u4EA7\u7269\uFF09\u2192 \u4ECE external \u5217\u8868\u91CC\u53BB\u6389\u5B83\u3002`)}function S(e){return"shims/"+e.replace(/[^\w.-]/g,"_")+".js"}function D(e){let s=new Map;for(let n of e){let r=S(n);if(s.has(r)&&s.get(r)!==n)throw new Error(`[lazy-lib] shim \u6587\u4EF6\u540D\u51B2\u7A81\uFF1A'${n}' \u548C '${s.get(r)}' \u90FD\u751F\u6210 '${r}'\u3002
15
+ \u2462 \u5B83\u4E0D\u8BE5\u88AB external\uFF08\u7EC4\u4EF6\u771F\u7684\u9700\u8981\u628A\u5B83\u6253\u8FDB\u4EA7\u7269\uFF09\u2192 \u4ECE external \u5217\u8868\u91CC\u53BB\u6389\u5B83\u3002`)}function S(e){return"shims/"+e.replace(/[^\w.-]/g,"_")+".js"}function D(e){let s=new Map;for(let t of e){let r=S(t);if(s.has(r)&&s.get(r)!==t)throw new Error(`[lazy-lib] shim \u6587\u4EF6\u540D\u51B2\u7A81\uFF1A'${t}' \u548C '${s.get(r)}' \u90FD\u751F\u6210 '${r}'\u3002
16
16
  \u5F53\u524D\u7F16\u7801\u65B9\u6848\uFF08/ \u548C\u975E\u6CD5\u5B57\u7B26\u66FF\u6362\u4E3A _\uFF09\u5728 GLOBALS \u7684\u5C01\u95ED\u96C6\u5185\u662F\u5B89\u5168\u7684\u3002
17
- \u5C06\u6765\u82E5\u771F\u9700\u8981\u652F\u6301\u4F1A\u78B0\u649E\u7684\u8BF4\u660E\u7B26\uFF0C\u518D\u6362\u7F16\u7801\u65B9\u6848\uFF08\u5982 hash \u540E\u7F00\uFF09\u3002`);s.set(r,n)}}function F(e,s,n){let r=q(e,n),i=[...s],t=i.filter(o=>o!=="default"&&L.test(o)).sort();for(let o of i)if(o!=="default"&&!L.test(o))throw new Error(`[lazy-lib] \u65E0\u6CD5\u4E3A external '${e}' \u751F\u6210 shim\uFF1Aimport binding '${o}' \u4E0D\u662F\u5408\u6CD5 JS \u6807\u8BC6\u7B26\u3002
17
+ \u5C06\u6765\u82E5\u771F\u9700\u8981\u652F\u6301\u4F1A\u78B0\u649E\u7684\u8BF4\u660E\u7B26\uFF0C\u518D\u6362\u7F16\u7801\u65B9\u6848\uFF08\u5982 hash \u540E\u7F00\uFF09\u3002`);s.set(r,t)}}function F(e,s,t){let r=Z(e,t),i=[...s],n=i.filter(o=>o!=="default"&&L.test(o)).sort();for(let o of i)if(o!=="default"&&!L.test(o))throw new Error(`[lazy-lib] \u65E0\u6CD5\u4E3A external '${e}' \u751F\u6210 shim\uFF1Aimport binding '${o}' \u4E0D\u662F\u5408\u6CD5 JS \u6807\u8BC6\u7B26\u3002
18
18
  \u539F\u56E0\uFF1A'*' \u6765\u81EA import * as ns from '...' \u7C7B\u547D\u540D\u7A7A\u95F4\u5BFC\u5165\uFF1Bshim \u65E0\u6CD5\u9759\u6001\u679A\u4E3E\u4F7F\u7528\u65B9\u4F1A\u8BBF\u95EE\u54EA\u4E9B\u540D\u5B57\u3002
19
- \u6539\u6CD5\uFF1A\u6539\u7528\u5177\u540D\u5BFC\u5165\uFF0C\u5982 import { someExport } from ... \u800C\u975E import * as ns from ...`);return[`// \u6784\u5EFA\u671F\u751F\u6210\uFF08epx-frame lazy-lib\uFF09\uFF1A\u8FD0\u884C\u65F6\u4ECE ${r} \u53D6\u5E73\u53F0\u5355\u4F8B\uFF0C\u52FF\u624B\u6539\u3002`,`const S = ${r}`,...t.map(o=>`export const ${o} = S[${JSON.stringify(o)}]`),"export default (S && S.default) || S"].join(`
19
+ \u6539\u6CD5\uFF1A\u6539\u7528\u5177\u540D\u5BFC\u5165\uFF0C\u5982 import { someExport } from ... \u800C\u975E import * as ns from ...`);return[`// \u6784\u5EFA\u671F\u751F\u6210\uFF08epx-frame lazy-lib\uFF09\uFF1A\u8FD0\u884C\u65F6\u4ECE ${r} \u53D6\u5E73\u53F0\u5355\u4F8B\uFF0C\u52FF\u624B\u6539\u3002`,`const S = ${r}`,...n.map(o=>`export const ${o} = S[${JSON.stringify(o)}]`),"export default (S && S.default) || S"].join(`
20
20
  `)+`
21
- `}function N(e){let s=new Map;for(let n in e){let r=e[n];if(r.type==="chunk")for(let i in r.importedBindings||{}){s.has(i)||s.set(i,new Set);for(let t of r.importedBindings[i])s.get(i).add(t)}}return s}import k from"node:path";var Z=(e,s)=>{let n=k.resolve(e),r=k.resolve(s);return n===r||n.startsWith(r+k.sep)||n.startsWith(r+"/")},E=e=>k.resolve(String(e).split("?")[0]);function A(e,s,n,r){let i=new Set((r||[]).map(E)),t=[...e()].filter(d=>Z(d,n)),a=new Set(t),o=new Map,l=[],u=[],m=d=>{let g=new Set;for(let f of d){let c=E(f);i.has(c)&&g.add(c)}return g.size},b=d=>{let g=o.get(d)||0;if(g===2)return;if(g===1){let c=[...l.slice(l.indexOf(d)),d];m(c)>=2&&u.push(c);return}o.set(d,1),l.push(d);let f=s(d)||{};for(let c of f.importedIds||[])a.has(c)&&b(c);l.pop(),o.set(d,2)};for(let d of t)b(d);return u}var $="\0epx-lazy-glob",I=/import\.meta\.glob\(\s*(['"])([^'"]+)\1\s*,\s*\{\s*(?:import\s*:\s*['"]default['"]\s*,\s*)?eager\s*:\s*true\s*(?:,\s*import\s*:\s*['"]default['"]\s*)?,?\s*\}\s*\)/;function X(e={}){let{enabled:s=!1,glob:n,eager:r=[],pkgName:i}=e,t=null,a=null,o=[],l=new Set,u="",m="",b="",d="",g=[];return{name:"epx-lazy-lib",apply:"build",enforce:"pre",config(f){return s?(g=(Array.isArray(f.plugins)?f.plugins.flat(1/0):[]).filter(c=>c&&c.name!=="epx-lazy-lib"),{build:{emptyOutDir:!1}}):null},configResolved(f){t=f,m=y.resolve(f.root,f.build.outDir);let c=f.build.lib&&f.build.lib.entry;b=Array.isArray(c)?c[0]:typeof c=="object"?Object.values(c)[0]:c,u=y.dirname(b),d=i||y.basename(f.root)},async buildStart(){if(!s)return;n||this.error("[lazy-lib] \u7F3A\u5C11 glob \u9009\u9879\uFF08\u5F62\u5982 './<\u4EA7\u54C1\u540D>/**/*.vue'\uFF09");let f=Y(t.root,m);f&&this.error(f);let c=n.replace(/^\.\//,"").split("/")[0];o=z(O(u,c)),o.length||this.error(`[lazy-lib] \u6309 glob \u4E00\u4E2A .vue \u90FD\u6CA1\u626B\u5230\uFF0C\u65E0\u6CD5\u6309\u9700\u62C6\u5305\u3002
22
- glob \u9009\u9879\uFF1A${n}
21
+ `}function N(e){let s=new Map;for(let t in e){let r=e[t];if(r.type==="chunk")for(let i in r.importedBindings||{}){s.has(i)||s.set(i,new Set);for(let n of r.importedBindings[i])s.get(i).add(n)}}return s}import k from"node:path";var X=(e,s)=>{let t=k.resolve(e),r=k.resolve(s);return t===r||t.startsWith(r+k.sep)||t.startsWith(r+"/")},E=e=>k.resolve(String(e).split("?")[0]);function I(e,s,t,r){let i=new Set((r||[]).map(E)),n=[...e()].filter(d=>X(d,t)),a=new Set(n),o=new Map,l=[],u=[],m=d=>{let g=new Set;for(let f of d){let c=E(f);i.has(c)&&g.add(c)}return g.size},b=d=>{let g=o.get(d)||0;if(g===2)return;if(g===1){let c=[...l.slice(l.indexOf(d)),d];m(c)>=2&&u.push(c);return}o.set(d,1),l.push(d);let f=s(d)||{};for(let c of f.importedIds||[])a.has(c)&&b(c);l.pop(),o.set(d,2)};for(let d of n)b(d);return u}var $="\0epx-lazy-glob",A=/import\.meta\.glob\(\s*(['"])([^'"]+)\1\s*,\s*\{\s*(?:import\s*:\s*['"]default['"]\s*,\s*)?eager\s*:\s*true\s*(?:,\s*import\s*:\s*['"]default['"]\s*)?,?\s*\}\s*\)/;async function M(e){let s=(await Promise.all(e)).flat(1/0);return s.some(t=>t&&typeof t.then=="function")?M(s):s.filter(t=>t&&t.name!=="epx-lazy-lib")}function Y(e={}){let{enabled:s=!1,glob:t,eager:r=[],pkgName:i}=e,n=null,a=null,o=[],l=new Set,u="",m="",b="",d="",g=[];return{name:"epx-lazy-lib",apply:"build",enforce:"pre",config(f){return s?(g=(Array.isArray(f.plugins)?f.plugins.flat(1/0):[]).filter(c=>c&&c.name!=="epx-lazy-lib"),{build:{emptyOutDir:!1}}):null},configResolved(f){n=f,m=y.resolve(f.root,f.build.outDir);let c=f.build.lib&&f.build.lib.entry;b=Array.isArray(c)?c[0]:typeof c=="object"?Object.values(c)[0]:c,u=y.dirname(b),d=i||y.basename(f.root)},async buildStart(){if(!s)return;t||this.error("[lazy-lib] \u7F3A\u5C11 glob \u9009\u9879\uFF08\u5F62\u5982 './<\u4EA7\u54C1\u540D>/**/*.vue'\uFF09"),g=await M(g);let f=H(n.root,m);f&&this.error(f);let c=t.replace(/^\.\//,"").split("/")[0];o=z(O(u,c)),o.length||this.error(`[lazy-lib] \u6309 glob \u4E00\u4E2A .vue \u90FD\u6CA1\u626B\u5230\uFF0C\u65E0\u6CD5\u6309\u9700\u62C6\u5305\u3002
22
+ glob \u9009\u9879\uFF1A${t}
23
23
  \u5B9E\u9645\u626B\u63CF\u76EE\u5F55\uFF1A${y.join(u,c)}\uFF08= \u5165\u53E3\u6240\u5728\u76EE\u5F55 ${u} + glob \u7B2C\u4E00\u6BB5 ${c}\uFF09
24
24
  \u6700\u53EF\u80FD\u7684\u539F\u56E0\uFF1Aglob \u662F\u76F8\u5BF9**\u5165\u53E3\u6587\u4EF6\u6240\u5728\u76EE\u5F55**\u5199\u7684\uFF0C\u522B\u6309\u4ED3\u5E93\u6839\u591A\u5199\u4E00\u5C42 \`src/\`\u2014\u2014
25
- \u5165\u53E3\u662F src/index.js \u65F6\u5E94\u5199 './<\u4EA7\u54C1\u540D>/**/*.vue'\uFF0C\u4E0D\u662F './src/<\u4EA7\u54C1\u540D>/**/*.vue'\u3002`),l=new Set([...r,...Q(b,u,o)]),h.rmSync(m,{recursive:!0,force:!0}),h.mkdirSync(m,{recursive:!0});let x=o.filter(p=>!l.has(p.key));a=await te(t,g,x,m,u,o)},resolveId(f){return f===$?$:null},load(f){return f!==$?null:re({pkgName:d,entries:o,eagerKeys:l,manifest:a})},transform(f,c){if(!s||y.resolve(c.split("?")[0])!==y.resolve(b))return null;let x=I.exec(f);return x||this.error(`[lazy-lib] \u5165\u53E3\u91CC\u6CA1\u627E\u5230\u671F\u671B\u5F62\u6001\u7684 import.meta.glob\u3002
25
+ \u5165\u53E3\u662F src/index.js \u65F6\u5E94\u5199 './<\u4EA7\u54C1\u540D>/**/*.vue'\uFF0C\u4E0D\u662F './src/<\u4EA7\u54C1\u540D>/**/*.vue'\u3002`),l=new Set([...r,...ee(b,u,o)]),h.rmSync(m,{recursive:!0,force:!0}),h.mkdirSync(m,{recursive:!0});let x=o.filter(p=>!l.has(p.key));a=await ne(n,g,x,m,u,o)},resolveId(f){return f===$?$:null},load(f){return f!==$?null:se({pkgName:d,entries:o,eagerKeys:l,manifest:a})},transform(f,c){if(!s||y.resolve(c.split("?")[0])!==y.resolve(b))return null;let x=A.exec(f);return x||this.error(`[lazy-lib] \u5165\u53E3\u91CC\u6CA1\u627E\u5230\u671F\u671B\u5F62\u6001\u7684 import.meta.glob\u3002
26
26
  \u671F\u671B\uFF1Aconst files = import.meta.glob('./<\u4EA7\u54C1\u540D>/**/*.vue', { eager: true })
27
27
  \u6587\u4EF6\uFF1A${b}
28
- \uFF08\u4E0D\u505A\u9759\u9ED8\u964D\u7EA7\uFF1A\u90A3\u4F1A\u6084\u6084\u6253\u51FA\u4E00\u4E2A\u5355\u4F53\uFF0C\u800C\u4F60\u4EE5\u4E3A\u81EA\u5DF1\u5F00\u4E86\u6309\u9700\u3002\uFF09`),x[2]!==n&&this.error(`[lazy-lib] \u63D2\u4EF6\u7684 glob \u9009\u9879\u4E0E\u5165\u53E3\u91CC import.meta.glob \u7684\u5B57\u9762\u91CF\u4E0D\u4E00\u81F4\uFF0C\u4E24\u8FB9\u5FC5\u987B\u9010\u5B57\u76F8\u540C\u3002
29
- \u63D2\u4EF6\u9009\u9879\uFF1A${n}
28
+ \uFF08\u4E0D\u505A\u9759\u9ED8\u964D\u7EA7\uFF1A\u90A3\u4F1A\u6084\u6084\u6253\u51FA\u4E00\u4E2A\u5355\u4F53\uFF0C\u800C\u4F60\u4EE5\u4E3A\u81EA\u5DF1\u5F00\u4E86\u6309\u9700\u3002\uFF09`),x[2]!==t&&this.error(`[lazy-lib] \u63D2\u4EF6\u7684 glob \u9009\u9879\u4E0E\u5165\u53E3\u91CC import.meta.glob \u7684\u5B57\u9762\u91CF\u4E0D\u4E00\u81F4\uFF0C\u4E24\u8FB9\u5FC5\u987B\u9010\u5B57\u76F8\u540C\u3002
29
+ \u63D2\u4EF6\u9009\u9879\uFF1A${t}
30
30
  \u5165\u53E3\u5B57\u9762\u91CF\uFF1A${x[2]}
31
31
  \u6587\u4EF6\uFF1A${b}
32
32
  \uFF08\u4E0D\u4E00\u81F4\u65F6\u58F3\u7684\u952E\u96C6\u4F1A\u4E0E\u6574\u4F53\u5355\u4F53\u5206\u53C9\uFF0C\u964D\u7EA7\u515C\u5E95\u4F1A\u627E\u4E0D\u5230\u7EC4\u4EF6\u3002\uFF09`),{code:`import __epxLazyGlob from ${JSON.stringify($)}
33
- `+f.replace(I,/\bimport\s*:/.test(x[0])?"Object.fromEntries(Object.entries(__epxLazyGlob).map(([key, value]) => [key, value.default]))":"__epxLazyGlob"),map:null}},async closeBundle(){if(!s||!a)return;let f={};for(let c of o)f[c.key]=l.has(c.key)?null:a[c.key]||null;h.writeFileSync(y.join(m,"index.manifest.json"),JSON.stringify({v:1,pkgName:d,components:f,eager:[...l].sort()},null,2)+`
34
- `),ee(m),M(m,t.build.copyPublicDir===!1?"":t.publicDir||""),await ne(t,g,b,m,d),J(m,"index.deps.json"),H(m,t.build.assetsDir)}}}function Y(e,s){let n=y.resolve(e),r=y.resolve(s);return r===n||!r.startsWith(n+y.sep)?`[lazy-lib] build.outDir \u5FC5\u987B\u662F\u9879\u76EE\u6839**\u4E4B\u5185**\u7684\u5B50\u76EE\u5F55\uFF0C\u4E14\u4E0D\u80FD\u5C31\u662F\u9879\u76EE\u6839\u672C\u8EAB\u3002
35
- \u9879\u76EE\u6839\uFF1A${n}
33
+ `+f.replace(A,/\bimport\s*:/.test(x[0])?"Object.fromEntries(Object.entries(__epxLazyGlob).map(([key, value]) => [key, value.default]))":"__epxLazyGlob"),map:null}},async closeBundle(){if(!s||!a)return;let f={};for(let c of o)f[c.key]=l.has(c.key)?null:a[c.key]||null;h.writeFileSync(y.join(m,"index.manifest.json"),JSON.stringify({v:1,pkgName:d,components:f,eager:[...l].sort()},null,2)+`
34
+ `),te(m),P(m,n.build.copyPublicDir===!1?"":n.publicDir||""),await re(n,g,b,m,d),J(m,"index.deps.json"),Q(m,n.build.assetsDir)}}}function H(e,s){let t=y.resolve(e),r=y.resolve(s);return r===t||!r.startsWith(t+y.sep)?`[lazy-lib] build.outDir \u5FC5\u987B\u662F\u9879\u76EE\u6839**\u4E4B\u5185**\u7684\u5B50\u76EE\u5F55\uFF0C\u4E14\u4E0D\u80FD\u5C31\u662F\u9879\u76EE\u6839\u672C\u8EAB\u3002
35
+ \u9879\u76EE\u6839\uFF1A${t}
36
36
  outDir\uFF1A${r}
37
37
  \u539F\u56E0\uFF1A\u6309\u9700\u62C6\u5305\u7684\u4E09\u8D9F\u4EA7\u7269\u8981\u843D\u8FDB\u540C\u4E00\u4E2A\u76EE\u5F55\uFF0C\u672C\u63D2\u4EF6\u4F1A\u5728\u6784\u5EFA\u5F00\u59CB\u65F6\u628A outDir \u6574\u4E2A\u5220\u6389\u91CD\u5EFA
38
38
  \uFF08\u9012\u5F52\u3001\u5F3A\u5236\uFF09\uFF0C\u8FD9\u4E00\u6B65\u7ED5\u5F00\u4E86 vite \u81EA\u5DF1\u7684 emptyOutDir \u4FDD\u62A4\u3002outDir \u89E3\u6790\u6210\u9879\u76EE\u6839\u65F6\uFF0C
39
- \u8FD9\u4E00\u5220\u4F1A\u628A\u4EA7\u54C1\u7684\u6E90\u7801\u4E00\u8D77\u5220\u6389\u3002\u6539\u6CD5\uFF1A\u7ED9 build.outDir \u4E00\u4E2A\u771F\u6B63\u7684\u5B50\u76EE\u5F55\uFF0C\u5982 'lib'\u3002`:null}function M(e,s,n=""){for(let r of h.readdirSync(e,{withFileTypes:!0})){let i=y.join(e,r.name),t=n?n+"/"+r.name:r.name;if(r.isDirectory())M(i,s,t);else if(r.name.endsWith(".css")){if(s&&h.existsSync(y.join(s,t)))continue;h.rmSync(i,{force:!0})}}}function H(e,s){let n=y.join(e,s||"assets");if(!h.existsSync(n))return[];let r=h.readdirSync(n,{withFileTypes:!0}).filter(t=>t.isFile()).map(t=>t.name);if(!r.length){try{h.rmdirSync(n)}catch{}return[]}let i=s||"assets";return console.warn(["",`[lazy-lib] \u26A0\uFE0F \u4EA7\u51FA\u4E86 ${r.length} \u4E2A\u6587\u4EF6\u578B\u8D44\u6E90\u5230 ${i}/\uFF1A`,...r.map(t=>" "+t),` \u8FDC\u7A0B\u5E93\u5F62\u6001\u4E0B\u5B83\u4EEC\u4F1A\u88AB\u5F15\u7528\u4E3A**\u7EDD\u5BF9\u8DEF\u5F84**\uFF08/${i}/xxx\uFF09\uFF0C`," \u89E3\u6790\u5230\u5E73\u53F0\u9875\u9762\u7684 origin \u6839\u76EE\u5F55 \u2192 \u8FD0\u884C\u65F6 404\uFF0C\u6784\u5EFA\u671F\u770B\u4E0D\u51FA\u6765\u3002"," \u4FEE\u6CD5\uFF1A\u628A build.assetsInlineLimit \u8C03\u5927\u5230\u8986\u76D6\u5B83\u4EEC\uFF08\u4EA7\u54C1\u9879\u76EE\u666E\u904D\u8BBE 50*1024\uFF09\uFF0C"," \u6216\u628A\u8D85\u5927\u8D44\u6E90\u5355\u72EC\u4F20\u6587\u4EF6\u670D\u52A1\u5668\u3001\u4EE3\u7801\u91CC\u5199\u5B8C\u6574 URL\u3002",""].join(`
40
- `)),r}var C=e=>({assetsInlineLimit:e.assetsInlineLimit,assetsDir:e.assetsDir,target:e.target,cssTarget:e.cssTarget,sourcemap:e.sourcemap,minify:e.minify});function J(e,s,n=""){for(let r of h.readdirSync(e,{withFileTypes:!0})){let i=y.join(e,r.name),t=n?n+"/"+r.name:r.name;r.isDirectory()?J(i,s,t):r.name.endsWith(".deps.json")&&t!==s&&h.rmSync(i,{force:!0})}}function Q(e,s,n){let r=h.readFileSync(e,"utf8").split(`\r
39
+ \u8FD9\u4E00\u5220\u4F1A\u628A\u4EA7\u54C1\u7684\u6E90\u7801\u4E00\u8D77\u5220\u6389\u3002\u6539\u6CD5\uFF1A\u7ED9 build.outDir \u4E00\u4E2A\u771F\u6B63\u7684\u5B50\u76EE\u5F55\uFF0C\u5982 'lib'\u3002`:null}function P(e,s,t=""){for(let r of h.readdirSync(e,{withFileTypes:!0})){let i=y.join(e,r.name),n=t?t+"/"+r.name:r.name;if(r.isDirectory())P(i,s,n);else if(r.name.endsWith(".css")){if(s&&h.existsSync(y.join(s,n)))continue;h.rmSync(i,{force:!0})}}}function Q(e,s){let t=y.join(e,s||"assets");if(!h.existsSync(t))return[];let r=h.readdirSync(t,{withFileTypes:!0}).filter(n=>n.isFile()).map(n=>n.name);if(!r.length){try{h.rmdirSync(t)}catch{}return[]}let i=s||"assets";return console.warn(["",`[lazy-lib] \u26A0\uFE0F \u4EA7\u51FA\u4E86 ${r.length} \u4E2A\u6587\u4EF6\u578B\u8D44\u6E90\u5230 ${i}/\uFF1A`,...r.map(n=>" "+n),` \u8FDC\u7A0B\u5E93\u5F62\u6001\u4E0B\u5B83\u4EEC\u4F1A\u88AB\u5F15\u7528\u4E3A**\u7EDD\u5BF9\u8DEF\u5F84**\uFF08/${i}/xxx\uFF09\uFF0C`," \u89E3\u6790\u5230\u5E73\u53F0\u9875\u9762\u7684 origin \u6839\u76EE\u5F55 \u2192 \u8FD0\u884C\u65F6 404\uFF0C\u6784\u5EFA\u671F\u770B\u4E0D\u51FA\u6765\u3002"," \u4FEE\u6CD5\uFF1A\u628A build.assetsInlineLimit \u8C03\u5927\u5230\u8986\u76D6\u5B83\u4EEC\uFF08\u4EA7\u54C1\u9879\u76EE\u666E\u904D\u8BBE 50*1024\uFF09\uFF0C"," \u6216\u628A\u8D85\u5927\u8D44\u6E90\u5355\u72EC\u4F20\u6587\u4EF6\u670D\u52A1\u5668\u3001\u4EE3\u7801\u91CC\u5199\u5B8C\u6574 URL\u3002",""].join(`
40
+ `)),r}var C=e=>({assetsInlineLimit:e.assetsInlineLimit,assetsDir:e.assetsDir,target:e.target,cssTarget:e.cssTarget,sourcemap:e.sourcemap,minify:e.minify});function J(e,s,t=""){for(let r of h.readdirSync(e,{withFileTypes:!0})){let i=y.join(e,r.name),n=t?t+"/"+r.name:r.name;r.isDirectory()?J(i,s,n):r.name.endsWith(".deps.json")&&n!==s&&h.rmSync(i,{force:!0})}}function ee(e,s,t){let r=h.readFileSync(e,"utf8").split(`\r
41
41
  `).join(`
42
- `),i=[],t=/^\s*import\s+\w+\s+from\s+['"](\.[^'"]+\.vue)['"]/gm,a;for(;a=t.exec(r);){let o=y.resolve(y.dirname(e),a[1]),l=n.find(u=>y.resolve(u.file)===o);l&&i.push(l.key)}return i}function ee(e){let s=y.join(e,"index.deps.json"),n=y.join(e,"index.js");if(!h.existsSync(s)||!h.existsSync(n))return;let r=[],i=!1;try{let a=JSON.parse(h.readFileSync(s,"utf8"));r=Array.isArray(a.components)?a.components:[],i=!!a.all}catch{return}let t=`
42
+ `),i=[],n=/^\s*import\s+\w+\s+from\s+['"](\.[^'"]+\.vue)['"]/gm,a;for(;a=n.exec(r);){let o=y.resolve(y.dirname(e),a[1]),l=t.find(u=>y.resolve(u.file)===o);l&&i.push(l.key)}return i}function te(e){let s=y.join(e,"index.deps.json"),t=y.join(e,"index.js");if(!h.existsSync(s)||!h.existsSync(t))return;let r=[],i=!1;try{let a=JSON.parse(h.readFileSync(s,"utf8"));r=Array.isArray(a.components)?a.components:[],i=!!a.all}catch{return}let n=`
43
43
  /*__EPX_FRAME_DEPS__${JSON.stringify(r)}__*/
44
44
  `+(i?`/*__EPX_FRAME_DEPS_ALL__*/
45
- `:"");h.appendFileSync(n,t)}async function te(e,s,n,r,i,t){let a={};for(let p of n)a[p.key]=p.file;let o=new Set,l=(t||n).map(p=>p.file),u=await B({root:e.root,logLevel:"silent",configFile:!1,plugins:[...s,{name:"epx-lazy-lib-cycle-guard",buildEnd(){let p=A(()=>this.getModuleIds(),_=>this.getModuleInfo(_),i,l);p.length&&this.error(`[lazy-lib] \u5165\u53E3\u7EC4\u4EF6\u4E4B\u95F4\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56\uFF0C\u6309\u9700\u62C6\u5305\u4F1A\u5728\u8FD0\u884C\u65F6\u89E6\u53D1 TDZ\uFF08Cannot access ... before initialization\uFF09\u5E76\u767D\u5C4F\uFF1A
45
+ `:"");h.appendFileSync(t,n)}async function ne(e,s,t,r,i,n){let a={};for(let p of t)a[p.key]=p.file;let o=new Set,l=(n||t).map(p=>p.file),u=await B({root:e.root,logLevel:"silent",configFile:!1,plugins:[...s,{name:"epx-lazy-lib-cycle-guard",buildEnd(){let p=I(()=>this.getModuleIds(),_=>this.getModuleInfo(_),i,l);p.length&&this.error(`[lazy-lib] \u5165\u53E3\u7EC4\u4EF6\u4E4B\u95F4\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56\uFF0C\u6309\u9700\u62C6\u5305\u4F1A\u5728\u8FD0\u884C\u65F6\u89E6\u53D1 TDZ\uFF08Cannot access ... before initialization\uFF09\u5E76\u767D\u5C4F\uFF1A
46
46
  `+p.map(_=>" "+_.join(`
47
47
  -> `)).join(`
48
48
  `)+`
49
49
  \u4E00\u4E2A .vue = \u4E00\u4E2A chunk\uFF0C\u6210\u73AF\u7684\u4E24\u4E2A\u7EC4\u4EF6\u8DE8 chunk \u540E\u521D\u59CB\u5316\u987A\u5E8F\u65AD\u88C2\u3002\u4E24\u6761\u51FA\u8DEF\uFF1A
50
50
  \u2460 \u628A\u73AF\u62C6\u6389\uFF1A\u62BD\u51FA\u53CC\u65B9\u90FD\u8981\u7684\u90A3\u90E8\u5206\u5230\u72EC\u7ACB\u6A21\u5757\uFF0C\u6539\u6210\u4E24\u4E2A\u7EC4\u4EF6\u90FD import \u5B83\uFF1B
51
51
  \u2461 \u8FD9\u4E2A\u5E93\u6682\u65F6\u4E0D\u7528\u6309\u9700\u5F62\u6001\uFF0C\u56DE\u5230\u6574\u4F53\u5355\u4F53\uFF08\u4E0D\u8BBE LAZY_LIB / enabled:false\uFF09\u3002
52
- \uFF08eager \u9009\u9879\u5E2E\u4E0D\u4E0A\u5FD9\uFF1A\u5B83\u53EA\u628A .vue \u4ECE\u7B2C\u2460\u8D9F\u7684 input \u91CC\u62FF\u6389\uFF0C\u7EC4\u4EF6\u4ECD\u5728\u6A21\u5757\u56FE\u91CC\uFF0C\u73AF\u8FD8\u5728\u3002\uFF09`)}}],css:e.css,resolve:e.resolve,define:e.define,publicDir:!1,build:{outDir:r,emptyOutDir:!1,cssCodeSplit:!1,...C(e.build),rollupOptions:{input:a,external:e.build.rollupOptions.external,preserveEntrySignatures:"strict",output:{format:"es",entryFileNames:"chunks/[name]-[hash].js",chunkFileNames:"chunks/[name]-[hash].js",paths:p=>(o.add(p),"./"+S(p))}}}}),m=Array.isArray(u)?u[0]:u,b=m.output.reduce((p,_)=>(p[_.fileName]=_,p),{}),d=e.build.rollupOptions.output&&e.build.rollupOptions.output.globals,g=N(b),f=new Map([...o].map(p=>["./"+S(p),p])),c=new Map;for(let[p,_]of g){let w=f.get(p);if(w){c.has(w)||c.set(w,new Set);for(let P of _)c.get(w).add(P)}}D([...o]);for(let[p,_]of c){let w=y.join(r,"chunks",S(p));h.mkdirSync(y.dirname(w),{recursive:!0}),h.writeFileSync(w,F(p,_,d))}let x={};for(let p of m.output)p.type==="chunk"&&p.isEntry&&(x[p.name]=p.fileName);return x}async function ne(e,s,n,r,i){await B({root:e.root,logLevel:"silent",configFile:!1,plugins:s,css:e.css,resolve:e.resolve,define:e.define,publicDir:!1,build:{outDir:r,emptyOutDir:!1,cssCodeSplit:!1,...C(e.build),lib:{entry:n,name:`__epxFullLibs__.${i}`,formats:["umd"],fileName:()=>"index.full.js"},rollupOptions:{external:e.build.rollupOptions.external,output:{globals:e.build.rollupOptions.output&&e.build.rollupOptions.output.globals,exports:"default",assetFileNames:t=>(t.names||[t.name]).some(a=>String(a).endsWith(".css"))?"index.css":"assets/[name]-[hash][extname]"}}}})}function re({pkgName:e,entries:s,eagerKeys:n,manifest:r}){let i=s.filter(o=>n.has(o.key)),t=[];i.forEach((o,l)=>{t.push(`import __eager${l} from ${JSON.stringify(o.file.split(y.sep).join("/"))}`)});let a={};for(let o of s)n.has(o.key)||(a[o.key]=r[o.key]);return t.push(""),t.push("// \u6784\u5EFA\u671F\u751F\u6210\uFF08epx-frame lazy-lib\uFF09\uFF1A\u628A import.meta.glob \u7684 eager \u7ED3\u679C\u6362\u6210\u6309\u9700 wrapper\u3002"),t.push(`const __pkg = ${JSON.stringify(e)}`),t.push(`const __manifest = ${JSON.stringify(a,null,2)}`),t.push("const __frame = (typeof window !== 'undefined' && window.frame) || {}"),t.push("const __cur = (typeof document !== 'undefined' && document.currentScript && document.currentScript.src) || ''"),t.push("const __base = __cur ? __cur.slice(0, __cur.lastIndexOf('/') + 1) : ''"),t.push("let __lazy = {}"),t.push("if (typeof __frame.registerLazyLibrary === 'function') {"),t.push(" __lazy = __frame.registerLazyLibrary(__pkg, { base: __base, components: __manifest, full: 'index.full.js' })"),t.push("} else if (__frame.Vue && __frame.Vue.defineAsyncComponent) {"),t.push(" // \u964D\u7EA7\u2461\uFF1A\u5E73\u53F0\u6CA1\u6709\u8BE5 API\uFF08\u65E7\u7248\u5E73\u53F0\uFF09\u65F6\u58F3\u81EA\u5EFA wrapper\uFF0C\u529F\u80FD\u7B49\u4EF7\uFF0C\u65E0\u96C6\u4E2D\u9884\u53D6\u3002"),t.push(" for (const k in __manifest) {"),t.push(" const f = __manifest[k]"),t.push(" const w = __frame.Vue.defineAsyncComponent(() => import(/* @vite-ignore */ __base + f))"),t.push(" w.name = k"),t.push(" __lazy[k] = w"),t.push(" }"),t.push("} else {"),t.push(" console.error('[frame.lazy] \u5E73\u53F0\u65E2\u6CA1\u6709 registerLazyLibrary \u4E5F\u6CA1\u6709 Vue \u2014\u2014 \u8BF7\u5347\u7EA7\u5E73\u53F0\uFF0C\u6216\u6539\u7528\u6574\u4F53\u5355\u4F53\u5F62\u6001\u6784\u5EFA\u672C\u5E93', __pkg)"),t.push("}"),t.push("const __out = {}"),s.forEach(o=>{let l=i.indexOf(o),u=l>=0?`__eager${l}`:`__lazy[${JSON.stringify(o.key)}]`;t.push(`__out[${JSON.stringify(o.globKey)}] = { default: ${u} }`)}),t.push("export default __out"),t.join(`
52
+ \uFF08eager \u9009\u9879\u5E2E\u4E0D\u4E0A\u5FD9\uFF1A\u5B83\u53EA\u628A .vue \u4ECE\u7B2C\u2460\u8D9F\u7684 input \u91CC\u62FF\u6389\uFF0C\u7EC4\u4EF6\u4ECD\u5728\u6A21\u5757\u56FE\u91CC\uFF0C\u73AF\u8FD8\u5728\u3002\uFF09`)}}],css:e.css,resolve:e.resolve,define:e.define,publicDir:!1,build:{outDir:r,emptyOutDir:!1,cssCodeSplit:!1,...C(e.build),rollupOptions:{input:a,external:e.build.rollupOptions.external,preserveEntrySignatures:"strict",output:{format:"es",entryFileNames:"chunks/[name]-[hash].js",chunkFileNames:"chunks/[name]-[hash].js",paths:p=>(o.add(p),"./"+S(p))}}}}),m=Array.isArray(u)?u[0]:u,b=m.output.reduce((p,_)=>(p[_.fileName]=_,p),{}),d=e.build.rollupOptions.output&&e.build.rollupOptions.output.globals,g=N(b),f=new Map([...o].map(p=>["./"+S(p),p])),c=new Map;for(let[p,_]of g){let w=f.get(p);if(w){c.has(w)||c.set(w,new Set);for(let V of _)c.get(w).add(V)}}D([...o]);for(let[p,_]of c){let w=y.join(r,"chunks",S(p));h.mkdirSync(y.dirname(w),{recursive:!0}),h.writeFileSync(w,F(p,_,d))}let x={};for(let p of m.output)p.type==="chunk"&&p.isEntry&&(x[p.name]=p.fileName);return x}async function re(e,s,t,r,i){await B({root:e.root,logLevel:"silent",configFile:!1,plugins:s,css:e.css,resolve:e.resolve,define:e.define,publicDir:!1,build:{outDir:r,emptyOutDir:!1,cssCodeSplit:!1,...C(e.build),lib:{entry:t,name:`__epxFullLibs__.${i}`,formats:["umd"],fileName:()=>"index.full.js"},rollupOptions:{external:e.build.rollupOptions.external,output:{globals:e.build.rollupOptions.output&&e.build.rollupOptions.output.globals,exports:"default",assetFileNames:n=>(n.names||[n.name]).some(a=>String(a).endsWith(".css"))?"index.css":"assets/[name]-[hash][extname]"}}}})}function se({pkgName:e,entries:s,eagerKeys:t,manifest:r}){let i=s.filter(o=>t.has(o.key)),n=[];i.forEach((o,l)=>{n.push(`import __eager${l} from ${JSON.stringify(o.file.split(y.sep).join("/"))}`)});let a={};for(let o of s)t.has(o.key)||(a[o.key]=r[o.key]);return n.push(""),n.push("// \u6784\u5EFA\u671F\u751F\u6210\uFF08epx-frame lazy-lib\uFF09\uFF1A\u628A import.meta.glob \u7684 eager \u7ED3\u679C\u6362\u6210\u6309\u9700 wrapper\u3002"),n.push(`const __pkg = ${JSON.stringify(e)}`),n.push(`const __manifest = ${JSON.stringify(a,null,2)}`),n.push("const __frame = (typeof window !== 'undefined' && window.frame) || {}"),n.push("const __cur = (typeof document !== 'undefined' && document.currentScript && document.currentScript.src) || ''"),n.push("const __base = __cur ? __cur.slice(0, __cur.lastIndexOf('/') + 1) : ''"),n.push("let __lazy = {}"),n.push("if (typeof __frame.registerLazyLibrary === 'function') {"),n.push(" __lazy = __frame.registerLazyLibrary(__pkg, { base: __base, components: __manifest, full: 'index.full.js' })"),n.push("} else if (__frame.Vue && __frame.Vue.defineAsyncComponent) {"),n.push(" // \u964D\u7EA7\u2461\uFF1A\u5E73\u53F0\u6CA1\u6709\u8BE5 API\uFF08\u65E7\u7248\u5E73\u53F0\uFF09\u65F6\u58F3\u81EA\u5EFA wrapper\uFF0C\u529F\u80FD\u7B49\u4EF7\uFF0C\u65E0\u96C6\u4E2D\u9884\u53D6\u3002"),n.push(" for (const k in __manifest) {"),n.push(" const f = __manifest[k]"),n.push(" const w = __frame.Vue.defineAsyncComponent(() => import(/* @vite-ignore */ __base + f))"),n.push(" w.name = k"),n.push(" __lazy[k] = w"),n.push(" }"),n.push("} else {"),n.push(" console.error('[frame.lazy] \u5E73\u53F0\u65E2\u6CA1\u6709 registerLazyLibrary \u4E5F\u6CA1\u6709 Vue \u2014\u2014 \u8BF7\u5347\u7EA7\u5E73\u53F0\uFF0C\u6216\u6539\u7528\u6574\u4F53\u5355\u4F53\u5F62\u6001\u6784\u5EFA\u672C\u5E93', __pkg)"),n.push("}"),n.push("const __out = {}"),s.forEach(o=>{let l=i.indexOf(o),u=l>=0?`__eager${l}`:`__lazy[${JSON.stringify(o.key)}]`;n.push(`__out[${JSON.stringify(o.globKey)}] = { default: ${u} }`)}),n.push("export default __out"),n.join(`
53
53
  `)+`
54
- `}export{Y as checkOutDir,X as default,M as rmCssFiles,J as rmStrayDepsJson,H as warnEmittedAssets,ee as writeFrameDepsMarker};
54
+ `}export{H as checkOutDir,Y as default,P as rmCssFiles,J as rmStrayDepsJson,Q as warnEmittedAssets,te as writeFrameDepsMarker};
@@ -25,6 +25,7 @@ export async function configureLibrary (env, options) {
25
25
  const plugins = await flatten(config.plugins)
26
26
  const root = path.resolve(projectRoot, config.root || '.')
27
27
  if (!config.build?.lib) throw new Error('当前 Vite 配置没有 build.lib,请为产品配置远程库入口。')
28
+ config.build.copyPublicDir = false
28
29
  if (!lazy) {
29
30
  config.plugins = plugins.filter(plugin => plugin.name !== 'epx-lazy-lib')
30
31
  } else {
@@ -0,0 +1,48 @@
1
+ /* eslint-disable no-console -- 输出已选择的平台版本 */
2
+ import http from 'node:http'
3
+ import https from 'node:https'
4
+
5
+ // Node 20 的双栈自动连接在部分 Windows 网络超时,查询 npm 时固定使用 IPv4。
6
+ function readMetadata (url) {
7
+ return new Promise((resolve, reject) => {
8
+ const client = url.protocol === 'http:' ? http : https
9
+ const request = client.get(url, {
10
+ family: 4,
11
+ headers: { accept: 'application/vnd.npm.install-v1+json', 'cache-control': 'no-cache' },
12
+ timeout: 15000
13
+ }, response => {
14
+ if (response.statusCode !== 200) {
15
+ response.resume()
16
+ reject(new Error(`npm 返回 HTTP ${response.statusCode}`))
17
+ return
18
+ }
19
+ let body = ''
20
+ response.setEncoding('utf8')
21
+ response.on('data', chunk => { body += chunk })
22
+ response.on('error', reject)
23
+ response.on('end', () => {
24
+ try { resolve(JSON.parse(body)) } catch (error) { reject(error) }
25
+ })
26
+ })
27
+ request.on('timeout', () => request.destroy(new Error('npm 请求超时')))
28
+ request.on('error', reject)
29
+ })
30
+ }
31
+
32
+ // 测试阶段默认使用 beta;显式版本不访问网络,标签解析后固定到具体版本。
33
+ export async function resolvePlatformVersion (spec, registry = process.env.npm_config_registry || 'https://registry.npmjs.org/') {
34
+ if (spec && !/^(?:[~^]?\d+\.\d+\.\d+(?:-[\w.-]+)?|[a-z][\w.-]*)$/.test(spec)) throw new Error('--packages-version 需要 npm 版本、版本范围或标签')
35
+ if (spec && /^[~^]?\d/.test(spec)) return spec
36
+ const tag = spec || 'beta'
37
+ try {
38
+ const metadata = await readMetadata(new URL('@epxing%2fcore', registry.endsWith('/') ? registry : registry + '/'))
39
+ const tags = metadata['dist-tags'] || {}
40
+ const selectedTag = tags[tag] ? tag : !spec ? 'latest' : tag
41
+ const version = tags[selectedTag]
42
+ if (!version || !/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(version)) throw new Error(`npm 中没有可用的 ${tag} 版本`)
43
+ console.log(`平台独立包版本:${version}(${selectedTag})`)
44
+ return version
45
+ } catch (error) {
46
+ throw new Error(`无法查询 @epxing/core 的 ${tag} 版本:${error.message}。请检查 npm 源和网络,或用 --packages-version 指定具体版本。`)
47
+ }
48
+ }