@epxing/cli 0.3.1 → 0.5.0-beta.0
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 +90 -0
- package/README.md +49 -30
- package/dist/THIRD_PARTY_NOTICES.txt +25 -0
- package/dist/cli.mjs +43 -31
- package/dist/lib-build.mjs +1 -1
- package/dist/lib-vite-config.mjs +1 -1
- package/dist/project.mjs +6 -6
- package/dist/skills/epxing-frontend-vue3-migrate/SKILL.md +17 -2
- package/dist/skills/epxing-frontend-vue3-migrate/pitfalls.md +498 -381
- package/dist/tools/chunks/AMQWUBTZ.mjs +2 -0
- package/dist/tools/chunks/H4POBCHI.mjs +1 -0
- package/dist/tools/chunks/PP5RD4RH.mjs +4 -0
- package/dist/tools/chunks/SH6LMMHZ.mjs +32 -0
- package/dist/tools/epx-create/scaffold.mjs +216 -5
- package/dist/tools/epx-migrate/detect-vue3-risks.mjs +1 -1
- package/dist/tools/epx-migrate/fix-date-formats.mjs +2 -0
- package/dist/tools/epx-migrate/fix-theme-styles.mjs +2 -0
- package/dist/tools/epx-migrate/migrate.mjs +270 -65
- package/dist/tools/epx-migrate/verify-components.mjs +5 -5
- package/dist/vite.d.ts +5 -0
- package/dist/vite.mjs +2 -0
- package/package.json +13 -3
package/API.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @epxing/cli API
|
|
2
|
+
|
|
3
|
+
独立工程命令行工具,终端命令名为 epxing。/vite 提供产品构建插件,根入口不提供业务运行时。
|
|
4
|
+
|
|
5
|
+
本页对应包版本 `0.5.0-beta.0`。导出名、子路径和签名从当前源码、package.json 与类型声明生成。
|
|
6
|
+
|
|
7
|
+
## 安装与使用
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install -g @epxing/cli
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
epxing help
|
|
17
|
+
epxing --version
|
|
18
|
+
epxing dev --port 3000
|
|
19
|
+
epxing build --mode prd
|
|
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
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 接入约定
|
|
26
|
+
|
|
27
|
+
工程命令使用当前项目已安装的依赖和脚本。--dir 指定项目目录;创建/迁移时用 --packages-version 指定 @epxing 平台包版本;--epx-frame 保留旧聚合模式,两者互斥。CLI 采用自己的版本号,独立于其余平台包。完整参数、迁移与发布说明见本包 README。
|
|
28
|
+
|
|
29
|
+
## 稳定子路径
|
|
30
|
+
|
|
31
|
+
下表按实际 package.json 的公开入口列出。default 使用默认导入,其他名称使用具名导入;类型接口用 import type。
|
|
32
|
+
|
|
33
|
+
| 导入路径 | 完整导出名 | 用途 / 详细说明 |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `@epxing/cli/vite` | `frameDeps`、`epxShared`、`lazyLib`、`LazyLibOptions`(类型) | 对应 `vite` 模块。 |
|
|
36
|
+
|
|
37
|
+
## 子路径补充导出
|
|
38
|
+
|
|
39
|
+
本节列出仅在稳定子路径中提供的具名 API;从本节标题对应路径导入。
|
|
40
|
+
|
|
41
|
+
### @epxing/cli/vite
|
|
42
|
+
|
|
43
|
+
| 导出 / 调用签名 | 用途 | 详细接口 |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| `frameDeps(): Plugin<any>` | Vite 构建插件:生成产品远程库依赖清单,供宿主在执行产品代码前加载组件。 | 见声明及接入约定 |
|
|
46
|
+
| `epxShared(): Plugin<any>` | Vite 构建插件:将产品的公开平台/Vue 导入映射到宿主共享命名空间,仅在构建时启用。 | 见声明及接入约定 |
|
|
47
|
+
| `lazyLib(options?: LazyLibOptions): Promise<Plugin<any>>` | 异步创建产品按需库构建插件,使用产品自己的 Vite 和 SFC 编译器,支持 enabled/root/glob/pkgName/eager。 | 见声明及接入约定 |
|
|
48
|
+
|
|
49
|
+
## 导出的 TypeScript 类型
|
|
50
|
+
|
|
51
|
+
以下名称仅存在于类型系统,用 import type 导入,不作为运行时对象使用。
|
|
52
|
+
|
|
53
|
+
### LazyLibOptions
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
interface LazyLibOptions { enabled?: boolean; root?: string; glob?: string; pkgName?: string; eager?: string[] }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 命令完整目录
|
|
60
|
+
|
|
61
|
+
| 命令 | 行为 |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `epxing` / `epxing menu` | 交互选择操作、工程目录、环境、端口和构建方式;管道支持数字输入 |
|
|
64
|
+
| `epxing dev` / `epxing serve` | 使用工程 `dev`、`serve` 或 `start` 脚本启动服务 |
|
|
65
|
+
| `epxing build` | 使用工程的构建脚本;只有 `build:lib` 的产品自动构建产品库 |
|
|
66
|
+
| `epxing lib` / `epxing build --lib` / `epxing lib --lazy` | 产品默认懒加载,优先 `build:lib:lazy`,否则使用 `build:lib` / `lib`;平台聚合库仍完整构建 |
|
|
67
|
+
| `epxing lib --full` / `epxing build --lib --full` | 产品完整打包,明确设置 `LAZY_LIB=false`;兼容旧 `--target lib` 脚本 |
|
|
68
|
+
| `epxing preview` | 使用 `preview` / `vite:preview`;没有脚本时使用工程本地 Vite |
|
|
69
|
+
| `epxing create` | 无参数进入创建引导,也可用参数直接创建 |
|
|
70
|
+
| `epxing migrate` / `epxing upgrade` | 无参数引导:目标版本、迁移范围、预览、确认应用 |
|
|
71
|
+
| `epxing skill install` | 安装技能,支持自定义目录和明确覆盖 |
|
|
72
|
+
| `epxing scan` / `epxing verify` | 迁移风险扫描 / 本地与线上组件清单校验 |
|
|
73
|
+
| `epxing theme [目录] [--apply]` | 补修产品/项目主题样式,默认只读预览;迁移时自动执行 |
|
|
74
|
+
| `epxing lint [--fix]` / `epxing circular` | 执行工程已有的代码检查、循环依赖检查脚本 |
|
|
75
|
+
| `epxing remote` / `epxing pkg <包名\|all>` | 使用平台已有 `build:remote` / `build:pkg` / `build:pkgs` 脚本 |
|
|
76
|
+
| `epxing help` / `epxing --version` | 帮助 / 工具版本 |
|
|
77
|
+
|
|
78
|
+
无参数的 create/migrate 提供交互引导;migrate/theme 默认预览,审阅后加 --apply 写入。完整参数请运行 epxing help 或阅读 README。
|
|
79
|
+
|
|
80
|
+
## 源码兼容与其他入口
|
|
81
|
+
|
|
82
|
+
package.json 供构建工具读取包元数据;本包不提供 /src/* 兼容路径。
|
|
83
|
+
|
|
84
|
+
| 公开路径模式 | 实际目标 |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `@epxing/cli/package.json` | `./package.json` |
|
|
87
|
+
|
|
88
|
+
## 文档维护
|
|
89
|
+
|
|
90
|
+
本页由 build/gen-package-api-docs.mjs 生成。修改公开入口并更新构建产物和类型声明后,在框架根运行 `pnpm docs:api`;`pnpm docs:api:check` 检查清单、类型、包内文档与站点镜像是否同步,同时验证页面编译和文档链接。用途和示例维护在 build/package-api-notes.mjs,组件和源码方法的详细参考位于 docs/revision。
|
package/README.md
CHANGED
|
@@ -1,42 +1,59 @@
|
|
|
1
1
|
# @epxing/cli
|
|
2
2
|
|
|
3
|
-
|
|
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` 提供。
|
|
4
8
|
|
|
5
9
|
```powershell
|
|
6
|
-
npm install -g @epxing/cli@
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
17
22
|
```
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
从 0.4.0 起终端命令为 `epxing`,可与旧聚合 CLI 的 `epx` 共存。新产品直接依赖 `@epxing/core`、`@epxing/component`、`@epxing/utils` 等包。创建后进入目录安装依赖,再运行 `npm run dev`;默认端口 8080。工具安装阶段不会运行迁移或改产品文件。
|
|
20
25
|
|
|
21
|
-
|
|
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` 仍是该仓库自己的脚本。
|
|
22
38
|
|
|
23
39
|
## 命令
|
|
24
40
|
|
|
25
41
|
| 命令 | 行为 |
|
|
26
42
|
| --- | --- |
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
| `
|
|
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` | 帮助 / 工具版本 |
|
|
40
57
|
|
|
41
58
|
工程命令支持 `--dir <目录>`,默认从当前目录向上找到最近的 `package.json`;不会改为 CLI 全局安装目录。没有项目脚本时,dev/build/preview 可使用项目已安装的 Vite,不会自动下载构建工具。工程仍需先安装自身依赖。
|
|
42
59
|
|
|
@@ -46,11 +63,13 @@ epx skill install --dir E:/products/my-product
|
|
|
46
63
|
|
|
47
64
|
`--mode/-m`、`--port/-p` 支持旧的 `-mprd`、`-p3000` 写法。build 优先匹配 `build:<mode>`;`localize` 也匹配 `build:local`,其余情况向构建脚本传入 `--mode`。平台 `build:component` 包含多步构建,不追加 `--mode`,环境由工程脚本统一配置。
|
|
48
65
|
|
|
49
|
-
平台 `
|
|
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。标识表示迁移目标,仍需完成转换、构建和业务复测。
|
|
50
69
|
|
|
51
|
-
|
|
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`;无须重跑依赖迁移。最终产物须验证平台字号、圆角、明暗与密度切换、懒加载和样式隔离。
|
|
52
71
|
|
|
53
|
-
`
|
|
72
|
+
`epxing scan <目录>` 扫描静态风险,`epxing verify <目录> --online <地址|文件>` 对照组件清单。技能安装到 `.claude/skills/epxing-frontend-vue3-migrate/`,可用 `--skills-dir` 指定其他客户端要求的位置。已有技能默认不覆盖;确认替换使用 `--force`。平台基类源码分析仍需准备对应版本源码或文档。
|
|
54
73
|
|
|
55
74
|
在框架源码仓库发布工具,不需要构建平台 `lib/`:
|
|
56
75
|
|
|
@@ -19,3 +19,28 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
21
|
THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@vue/compiler-dom
|
|
25
|
+
|
|
26
|
+
The MIT License (MIT)
|
|
27
|
+
|
|
28
|
+
Copyright (c) 2018-present, Yuxi (Evan) You
|
|
29
|
+
|
|
30
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
31
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
32
|
+
in the Software without restriction, including without limitation the rights
|
|
33
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
34
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
35
|
+
furnished to do so, subject to the following conditions:
|
|
36
|
+
|
|
37
|
+
The above copyright notice and this permission notice shall be included in
|
|
38
|
+
all copies or substantial portions of the Software.
|
|
39
|
+
|
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
41
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
42
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
43
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
44
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
45
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
46
|
+
THE SOFTWARE.
|
package/dist/cli.mjs
CHANGED
|
@@ -28,9 +28,11 @@ function takeOption (args, name) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function requireTarget (args) {
|
|
31
|
+
const packagesVersion = takeOption(args, '--packages-version')
|
|
31
32
|
const target = takeOption(args, '--epx-frame')
|
|
32
|
-
if (
|
|
33
|
-
|
|
33
|
+
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) }
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
function runTool (script, args, cwd) {
|
|
@@ -83,18 +85,18 @@ async function interactive (cwd, action) {
|
|
|
83
85
|
if (action === 'help') return dispatch(['help'])
|
|
84
86
|
if (action === 'create') {
|
|
85
87
|
const name = await prompts.required('产品名或目标路径')
|
|
86
|
-
const target = await prompts.required('目标
|
|
88
|
+
const target = await prompts.required('目标 @epxing 包版本', '5.3.0-beta.1')
|
|
87
89
|
const dir = await prompts.text('生成目录', name)
|
|
88
|
-
return dispatch(['create', name, '--dir', dir, '--
|
|
90
|
+
return dispatch(['create', name, '--dir', dir, '--packages-version', target])
|
|
89
91
|
}
|
|
90
92
|
if (action === 'migrate') {
|
|
91
93
|
const dir = await prompts.required('待升级工程目录', '.')
|
|
92
|
-
const target = await prompts.required('目标
|
|
94
|
+
const target = await prompts.required('目标 @epxing 包版本', '5.3.0-beta.1')
|
|
93
95
|
const flags = await prompts.select('迁移范围', choices([
|
|
94
96
|
['依赖与入口迁移', []], ['依赖、入口与 Vue 组件转换', ['--transform-vue']],
|
|
95
97
|
['依赖、Vue 组件及 Vite 构建迁移', ['--transform-vue', '--to-vite']]
|
|
96
98
|
]))
|
|
97
|
-
const args = ['migrate', dir, '--
|
|
99
|
+
const args = ['migrate', dir, '--packages-version', target, ...flags]
|
|
98
100
|
const preview = await main(args, cwd)
|
|
99
101
|
if (preview !== 0 || !(await prompts.confirm('应用以上迁移?要求 Git 工作树干净;默认不修改'))) return preview
|
|
100
102
|
return dispatch([...args, '--apply'])
|
|
@@ -112,7 +114,7 @@ async function interactive (cwd, action) {
|
|
|
112
114
|
}
|
|
113
115
|
if (action === 'check') {
|
|
114
116
|
action = await prompts.select('检查类型', choices([
|
|
115
|
-
['源码迁移风险扫描', 'scan'], ['本地 / 线上组件清单核对', 'verify'], ['项目代码检查', 'lint'], ['项目循环依赖检查', 'circular']
|
|
117
|
+
['源码迁移风险扫描', 'scan'], ['本地 / 线上组件清单核对', 'verify'], ['项目代码检查', 'lint'], ['项目循环依赖检查', 'circular'], ['产品主题适配(预览)', 'theme']
|
|
116
118
|
]))
|
|
117
119
|
}
|
|
118
120
|
if (action === 'advanced') {
|
|
@@ -121,7 +123,7 @@ async function interactive (cwd, action) {
|
|
|
121
123
|
]))
|
|
122
124
|
}
|
|
123
125
|
const dir = await prompts.required('工程目录', '.')
|
|
124
|
-
if (
|
|
126
|
+
if (['scan', 'verify', 'theme'].includes(action)) {
|
|
125
127
|
const online = action === 'verify' ? await prompts.text('线上 JS 地址或文件(留空仅列本地组件)') : ''
|
|
126
128
|
return dispatch([action, dir, ...(online ? ['--online', online] : [])])
|
|
127
129
|
}
|
|
@@ -167,26 +169,28 @@ export async function main (argv = process.argv.slice(2), cwd = process.env.INIT
|
|
|
167
169
|
if (['help', '--help', '-h'].includes(command)) {
|
|
168
170
|
console.log(`@epxing/cli · 工程开发与升级工具(独立于平台版本)
|
|
169
171
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
172
|
+
epxing / epxing menu 交互菜单(↑↓ + Enter;管道支持数字输入)
|
|
173
|
+
epxing dev [-m <模式>] [-p <端口>] [--dir <工程目录>]
|
|
174
|
+
epxing build [-m <模式>] [--thin] [--no-designer] [--no-dashboard] [--dir <目录>]
|
|
175
|
+
epxing lib [--full | --lazy] [-m <模式>] [--dir <目录>] 产品默认懒加载,--full 完整打包;平台聚合库保持完整
|
|
176
|
+
epxing build --lib 同 epxing lib
|
|
177
|
+
epxing preview [-p <端口>] [--dir <目录>]
|
|
178
|
+
epxing create <名称|路径> --packages-version <平台包版本> [--dir <目录>]
|
|
179
|
+
epxing migrate [项目目录] --packages-version <平台包版本> [--apply] [--transform-vue] [--to-vite]
|
|
180
|
+
epxing scan [项目目录]
|
|
181
|
+
epxing theme [项目目录] [--apply] 主题变量补修,默认只读;迁移时自动执行
|
|
182
|
+
epxing verify [项目目录] [--online <线上JS地址|文件>]
|
|
183
|
+
epxing skill install [--dir <项目目录>] [--skills-dir <技能目录>] [--force]
|
|
184
|
+
epxing lint [--fix] [--dir <目录>]
|
|
185
|
+
epxing circular [--dir <目录>]
|
|
186
|
+
epxing remote [--dir <平台目录>]
|
|
187
|
+
epxing pkg <包名|all> [--dir <平台目录>]
|
|
188
|
+
epxing --version
|
|
186
189
|
|
|
187
190
|
dev / build / lib 等执行当前工程的 package.json 脚本,使用工程本地依赖。
|
|
188
191
|
工程命令可用 -- 后的参数透传给脚本;serve / upgrade 分别是 dev / migrate 的别名。
|
|
189
|
-
create、migrate
|
|
192
|
+
create、migrate 不带参数时进入独立包引导;直接带参数时 --packages-version 必填。
|
|
193
|
+
--epx-frame <版本或spec> 保留旧聚合模式,与 --packages-version 互斥。
|
|
190
194
|
创建和升级自动写入 runtime: "vue3"。迁移默认 dry-run,--apply 才落盘。
|
|
191
195
|
工具不会自动安装平台依赖;.vue 转换工具仅在执行 --apply --transform-vue 时下载并缓存。`)
|
|
192
196
|
return 0
|
|
@@ -196,18 +200,19 @@ create、migrate 不带参数时进入引导;直接带参数时 --epx-frame
|
|
|
196
200
|
return 0
|
|
197
201
|
}
|
|
198
202
|
if (command === 'skill') {
|
|
199
|
-
if (args.shift() !== 'install') throw new Error('用法:
|
|
203
|
+
if (args.shift() !== 'install') throw new Error('用法:epxing skill install [--dir <项目目录>]')
|
|
200
204
|
return installSkill(args, cwd)
|
|
201
205
|
}
|
|
202
206
|
if (command === 'create') {
|
|
203
207
|
const target = requireTarget(args)
|
|
204
208
|
const chosenDir = takeOption(args, '--dir')
|
|
205
209
|
const nameOrPath = args.shift()
|
|
206
|
-
if (!nameOrPath || args.length || nameOrPath.startsWith('-')) throw new Error('用法:
|
|
210
|
+
if (!nameOrPath || args.length || nameOrPath.startsWith('-')) throw new Error('用法:epxing create <名称|路径> --epx-frame <目标版本> [--dir <目录>]')
|
|
207
211
|
const dir = path.resolve(cwd, chosenDir || nameOrPath)
|
|
208
212
|
const name = /[\\/]/.test(nameOrPath) ? path.basename(path.resolve(cwd, nameOrPath)) : nameOrPath
|
|
209
213
|
const { scaffold } = await import(pathToFileURL(path.join(payload, 'tools/epx-create/scaffold.mjs')).href)
|
|
210
|
-
|
|
214
|
+
const cliVersion = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')).version
|
|
215
|
+
scaffold({ name, dir, ...(target.independent ? { packagesVersion: target.value } : { epxFrameSpec: target.value }), cliVersion })
|
|
211
216
|
return 0
|
|
212
217
|
}
|
|
213
218
|
if (command === 'migrate') {
|
|
@@ -215,15 +220,22 @@ create、migrate 不带参数时进入引导;直接带参数时 --epx-frame
|
|
|
215
220
|
const dirs = args.filter(arg => !arg.startsWith('-'))
|
|
216
221
|
if (dirs.length > 1) throw new Error('一次迁移一个项目目录')
|
|
217
222
|
const dir = dirs[0] || '.'
|
|
218
|
-
|
|
223
|
+
const cliVersion = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8')).version
|
|
224
|
+
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
|
+
}
|
|
226
|
+
if (command === 'theme') {
|
|
227
|
+
const apply = args.includes('--apply')
|
|
228
|
+
args = args.filter(arg => arg !== '--apply')
|
|
229
|
+
if (args.length > 1 || args.some(arg => arg.startsWith('-'))) throw new Error('用法:epxing theme [项目目录] [--apply]')
|
|
230
|
+
return runTool('epx-migrate/fix-theme-styles.mjs', [path.resolve(cwd, args[0] || '.'), ...(apply ? ['--apply'] : [])], cwd)
|
|
219
231
|
}
|
|
220
232
|
if (command === 'scan' || command === 'verify') {
|
|
221
233
|
const online = command === 'verify' ? takeOption(args, '--online') : null
|
|
222
|
-
if (args.length > 1 || args.some(arg => arg.startsWith('-'))) throw new Error(`用法:
|
|
234
|
+
if (args.length > 1 || args.some(arg => arg.startsWith('-'))) throw new Error(`用法:epxing ${command} [项目目录]${command === 'verify' ? ' [--online <地址|文件>]' : ''}`)
|
|
223
235
|
const script = command === 'scan' ? 'detect-vue3-risks.mjs' : 'verify-components.mjs'
|
|
224
236
|
return runTool('epx-migrate/' + script, [path.resolve(cwd, args[0] || '.'), ...(online ? ['--online', online] : [])], cwd)
|
|
225
237
|
}
|
|
226
|
-
throw new Error(`未知命令:${command},运行
|
|
238
|
+
throw new Error(`未知命令:${command},运行 epxing help 查看用法。`)
|
|
227
239
|
}
|
|
228
240
|
|
|
229
241
|
let isMain = false
|
package/dist/lib-build.mjs
CHANGED
|
@@ -38,7 +38,7 @@ function configInScript (script) {
|
|
|
38
38
|
function verifyLazy (outDir, previousStamp) {
|
|
39
39
|
const file = path.join(outDir, 'index.manifest.json')
|
|
40
40
|
if (!fs.existsSync(file) || manifestStamp(outDir) === previousStamp || !fs.existsSync(path.join(outDir, 'index.full.js'))) {
|
|
41
|
-
throw new Error('没有生成新的按需库清单和完整兜底包,不能视为懒加载构建成功。请检查构建脚本或使用
|
|
41
|
+
throw new Error('没有生成新的按需库清单和完整兜底包,不能视为懒加载构建成功。请检查构建脚本或使用 epxing lib --full。')
|
|
42
42
|
}
|
|
43
43
|
const manifest = JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
44
44
|
const entries = Object.entries(manifest.components || {})
|
package/dist/lib-vite-config.mjs
CHANGED
|
@@ -37,7 +37,7 @@ export async function configureLibrary (env, options) {
|
|
|
37
37
|
if (!file) throw new Error('无法确定产品库入口 build.lib.entry')
|
|
38
38
|
const source = fs.readFileSync(path.resolve(root, file), 'utf8')
|
|
39
39
|
const match = /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*\)/.exec(source)
|
|
40
|
-
if (!match) throw new Error('按需库需要入口中的 eager import.meta.glob;请先迁移产品入口,或使用
|
|
40
|
+
if (!match) throw new Error('按需库需要入口中的 eager import.meta.glob;请先迁移产品入口,或使用 epxing lib --full。')
|
|
41
41
|
config.plugins.push(lazyLib({ enabled: true, glob: match[2], pkgName }))
|
|
42
42
|
}
|
|
43
43
|
}
|
package/dist/project.mjs
CHANGED
|
@@ -34,7 +34,7 @@ function npmEntry () {
|
|
|
34
34
|
} catch (error) { /* 继续查找 */ }
|
|
35
35
|
}
|
|
36
36
|
const found = candidates.find(file => file && fs.existsSync(file))
|
|
37
|
-
if (!found) throw new Error('未找到 npm-cli.js。请使用带 npm 的 Node.js 环境运行
|
|
37
|
+
if (!found) throw new Error('未找到 npm-cli.js。请使用带 npm 的 Node.js 环境运行 epxing。')
|
|
38
38
|
return found
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -114,7 +114,7 @@ export function projectPlan (command, options, project) {
|
|
|
114
114
|
let libraryMode
|
|
115
115
|
const platform = project.pkg.name === 'epx-frame' || !!scripts['build:component']
|
|
116
116
|
if (options.lib) {
|
|
117
|
-
if (command !== 'build') throw new Error('--lib 用于
|
|
117
|
+
if (command !== 'build') throw new Error('--lib 用于 epxing build;也可直接使用 epxing lib')
|
|
118
118
|
command = 'lib'
|
|
119
119
|
}
|
|
120
120
|
if (command === 'build' && !scripts.build && scripts['build:lib']) command = 'lib'
|
|
@@ -124,7 +124,7 @@ export function projectPlan (command, options, project) {
|
|
|
124
124
|
if (options.port && !['dev', 'preview'].includes(command)) throw new Error('--port 仅用于 dev 或 preview')
|
|
125
125
|
if (options.lazy && command !== 'lib') throw new Error('--lazy 仅用于 lib 或 build --lib')
|
|
126
126
|
if (options.fix && command !== 'lint') throw new Error('--fix 仅用于 lint')
|
|
127
|
-
if ((options.thin || options.noDesigner || options.noDashboard) && (command !== 'build' || !platform)) throw new Error('平台裁剪选项仅用于平台源码中的
|
|
127
|
+
if ((options.thin || options.noDesigner || options.noDashboard) && (command !== 'build' || !platform)) throw new Error('平台裁剪选项仅用于平台源码中的 epxing build')
|
|
128
128
|
if (options.mode && !['dev', 'build', 'lib', 'preview'].includes(command)) throw new Error('--mode 仅用于 dev、build、lib 或 preview')
|
|
129
129
|
if (command === 'dev') {
|
|
130
130
|
script = pick('dev', 'serve', 'start')
|
|
@@ -146,19 +146,19 @@ export function projectPlan (command, options, project) {
|
|
|
146
146
|
env.LAZY_LIB = options.full ? 'false' : 'true'
|
|
147
147
|
script = options.full ? pick('build:lib:full', 'build:lib', 'lib', 'build:lib:lazy') : pick('build:lib:lazy', 'build:lib', 'lib')
|
|
148
148
|
if (!script && /--target(?:=|\s+)lib\b/.test(scripts.build || '')) {
|
|
149
|
-
if (!options.full) throw new Error('旧 webpack 产品请先迁移到 Vite,或使用
|
|
149
|
+
if (!options.full) throw new Error('旧 webpack 产品请先迁移到 Vite,或使用 epxing lib --full 完整打包')
|
|
150
150
|
script = 'build'
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
if (!script) throw new Error('当前工程缺少库构建脚本。产品请提供 build:lib(按需库可用 build:lib:lazy),平台使用 build:component。')
|
|
154
|
-
if (script === 'build:component' && options.mode) throw new Error('平台聚合库包含多步构建,请在 build:component 中配置环境;
|
|
154
|
+
if (script === 'build:component' && options.mode) throw new Error('平台聚合库包含多步构建,请在 build:component 中配置环境;epxing lib 不向该聚合脚本追加 --mode。')
|
|
155
155
|
} else if (command === 'preview') {
|
|
156
156
|
script = pick('preview', 'vite:preview')
|
|
157
157
|
if (!script) binary = 'vite'
|
|
158
158
|
} else if (command === 'remote') script = pick('build:remote')
|
|
159
159
|
else if (command === 'pkg') {
|
|
160
160
|
const name = options.positional[0]
|
|
161
|
-
if (!name || !/^[a-z][a-z0-9-]*$/.test(name)) throw new Error('用法:
|
|
161
|
+
if (!name || !/^[a-z][a-z0-9-]*$/.test(name)) throw new Error('用法:epxing pkg <包名|all> [--dir <平台目录>]')
|
|
162
162
|
script = name === 'all' ? pick('build:pkgs') : pick('build:pkg')
|
|
163
163
|
if (name !== 'all') env.PKG = name
|
|
164
164
|
} else if (command === 'lint') {
|
|
@@ -10,6 +10,8 @@ description: epx 产品/项目远程库 Vue2/webpack → Vue3/Vite 升级 + 按
|
|
|
10
10
|
epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK` 配 url、运行时加载)
|
|
11
11
|
从 Vue2/webpack 迁到 Vue3/Vite,并可选切到「清单 + 组件按需加载」形态的完整流程与踩坑清单。
|
|
12
12
|
|
|
13
|
+
独立 CLI 从 `@epxing/cli@0.4.0` 起使用 `epxing` 命令(包名不变,平台依赖仍为 `epx-frame`)。例如 `epxing migrate <产品目录> --epx-frame <目标版本> --apply`;同时执行日期格式和主题样式迁移。已升级工程可用 `epxing theme <目录> --apply` 单独补修。仓库原有 `pnpm epx` 是本地脚本,不等同于全局命令。
|
|
14
|
+
|
|
13
15
|
**核心判断:这条链上的失败几乎全是静默的。** 构建绿、控制台干净、组件就是不出来。
|
|
14
16
|
所以每一步都要有**判据**,别靠"看着没报错"。
|
|
15
17
|
|
|
@@ -41,7 +43,7 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
|
|
|
41
43
|
| ① 依赖迁移 | `MIGRATION-REPORT.md` 的人工清单**逐条看过**——里面写着的坑会真的咬人 |
|
|
42
44
|
| ② .vue 转换 | `npx eslint src --ext .js,.jsx,.vue` 能跑(迁移会删掉 eslint 生态,先修工具链) |
|
|
43
45
|
| ③ 切 Vite | `npm run build:lib` exit 0 **且** `lib/` 里有 `index.js`/`index.css`/`index.deps.json` |
|
|
44
|
-
| ④ dev 壳 | 浏览器里 `#app.__vue_app__._context.components` 能数到你的组件个数;对自定义页、继承组件和多分支 render
|
|
46
|
+
| ④ dev 壳 | 浏览器里 `#app.__vue_app__._context.components` 能数到你的组件个数;对自定义页、继承组件和多分支 render,核对实际 DOM 与 CSS 选择器是否匹配。样式隔离变更还须用最终产物通过 F15 的组件内、组件外及跨页面检查 |
|
|
45
47
|
| ⑤ 按需 | `index.manifest.json` 组件数 == `.vue` 文件数,**且路径兜底名 0 个** |
|
|
46
48
|
|
|
47
49
|
第⑤条那个"路径兜底名"是最容易漏的:注册名抽不到就退成 `hrcomponentsSearch` 这种,
|
|
@@ -55,6 +57,10 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
|
|
|
55
57
|
| `__epxInstalledLibs__` 有记录但 app 里 0 个组件 | 记账写在 install 之前,产品幂等守卫空转 |
|
|
56
58
|
| 注册名变成 `xxxcomponentsYyy` | `extractName` 没抽到 `name`(按需形态特有) |
|
|
57
59
|
| 组件出来了但完全没样式 | 先查样式表是否加载、实际 DOM 能否匹配选择器;常见原因是 CSS 与 chunk 不同批(`data-v` hash 对不上),或根节点漏了 `.epx-xxx` 样式命名空间(F19) |
|
|
60
|
+
| 隔离测试样式正常,实际页面中继承组件的图片/标题失去样式 | 检查平台包装组件及 Element Plus 插槽的完整渲染链;根有 `data-v-*` 不代表插槽内后代也有。按 F15 核对选择器与继承值,在有效专属容器内局部使用 `:deep()` |
|
|
61
|
+
| 升级后工具栏 `el-select` 把相邻按钮挤到下一行 | Element Plus 选择框默认宽度为 100%;Vue3 产品不再走旧 render 垫片的宽度兜底,按 F20 在产品工具栏显式设置宽度和布局 |
|
|
62
|
+
| 日期选择器显示错误日期,但绑定值/数据时点正确 | 控件还用 fecha 的 `yyyy-MM-dd`,Element Plus 使用 Day.js 的 `YYYY-MM-DD`;按 F21 自动修复产品/项目源码,原生 Vue3 包不依赖旧垫片 |
|
|
63
|
+
| 平台已切换字号、圆角或明暗,产品样式仍固定 | 按 E2 迁移硬编码及动态样式,消费平台主题变量;不在产品重新导入整套主题,不删除 scoped |
|
|
58
64
|
| 图片 404,路径是 `/assets/xxx.png` | 嵌套构建没继承 `assetsInlineLimit` |
|
|
59
65
|
| `Cannot read properties of undefined (reading 'i18n')` | recorder-core 执行序(模块图里没有那条边) |
|
|
60
66
|
| `[vuex] duplicate getter key` | 库被装了两次(本地 + 远程) |
|
|
@@ -71,7 +77,13 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
|
|
|
71
77
|
|
|
72
78
|
> **本轮新增(postAppoint 实证)**:
|
|
73
79
|
> - `fix-jsx-vue2` 除自动改 4 类 JSX 属性(`domProps*`/`nativeOn*`/`scopedSlots=`),现在还**报告** `<script>` 区的 `slot="xxx"` 具名插槽(第 5 类,需人工改 `v-slots`——因要重组 JSX 结构故不自动改;甄别见 F14);
|
|
74
|
-
> -
|
|
80
|
+
> - `detect-vue3-risks.mjs`(`node tools/epx-migrate/detect-vue3-risks.mjs <项目>`)仅提示待复核模式:R1 = extends+scoped+无 template+裸类选择器,退出码 2 可用于 CI 提醒复核。命中不证明样式失效,未命中也不证明隔离安全;不要为消除告警批量删 scoped 或替换成 `:deep()`,按 F15 用实际产物验证。
|
|
81
|
+
|
|
82
|
+
**样式隔离默认保留**:JSX/render、无 template 或继承组件均不能作为删除 scoped 的依据;隔离测试正常也不能排除实际页面中包装组件/插槽链造成的作用域失配。用最终产物检查实际页面的失效元素、祖先和选择器,确认后优先保留 scoped,在有对应作用域属性的专属容器内对必要后代使用 `:deep()`。若确须去掉 scoped,根命名空间、全部选择器隔离和组件外回归须同时完成,不可留下“先去 scoped、稍后补隔离”的中间结果。详见 F15。
|
|
83
|
+
|
|
84
|
+
**日期格式必须自动补修(产品和项目都适用,含已标识 `runtime: vue3` 的工程)**:迁移器会在不依赖 gogocode 的阶段修复日期控件 `format`、`value-format/valueFormat` 的静态旧 token,覆盖 template、JSX 和常见 render 写法,并将文件/行号写入报告。仅补日期问题时,在平台工程运行 `node tools/epx-migrate/fix-date-formats.mjs <目标工程> --apply`,不用重跑整个依赖迁移。默认不带 `--apply` 为只读预览。
|
|
85
|
+
|
|
86
|
+
执行技能时,若自动修复器或发布前扫描发现动态格式变量、配置对象、函数/展开属性,继续追踪实际来源并修复能确认的旧格式;不能只记录“人工检查”便算完成。无法确认用途或缺少源配置的项才保留为未解决,并写明原因。不要全仓替换 `yyyy/dd`,也不改后端协议、其它日期库、分钟 `mm` 或星期 `ddd/dddd`。用最终产物核对初始回显、选择后的绑定值和请求日期一致;例如 `2026-10-20` 不能显示成 `2026-02-01`。详见 [F21](pitfalls.md#f21-element-plus-日期格式-token-迁移遗漏hr-历史组织机构图)。
|
|
75
87
|
|
|
76
88
|
## 迁移完怎么验:迁移包 vs 线上 三方对比(postAppoint / recruit / hr 实证)
|
|
77
89
|
|
|
@@ -90,6 +102,8 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
|
|
|
90
102
|
**运行时实证判据(别靠肉眼 / 文本 / 静态 grep)**:
|
|
91
103
|
- 组件在不在:`#app.__vue_app__._context.components` 数量 / 组件实例的 `$slots` 键;
|
|
92
104
|
- 样式生不生效:`getComputedStyle(el)` 比对(容器高度是否塌陷 0、色值 / 尺寸是否对齐线上);
|
|
105
|
+
- 样式是否泄漏:涉及 scoped、`:deep()` 或全局样式变更时,用最终懒加载产物记录外部同名元素(如 `.avatar`、`.container`)加载组件前后的计算样式;覆盖组件加载后、离开页面及进入其他页面的状态。组件内有效且组件外不受影响,才能验收(F15);
|
|
106
|
+
- 工具栏选择框与按钮:核对选择框宽度、父容器布局及 `getBoundingClientRect()` 的纵向中心位置;按 F20 检查升级后不再享有的旧垫片默认值,同时确认表单内整行选择框仍按设计占满可用宽度;
|
|
93
107
|
- 差异定性:`el-table` 固定列会复制一份 DOM(Vue2 Element UI 行数翻倍、Vue3 Element Plus 不翻)——比对「共 N 条 / 首行文本」而非 DOM 元素数,否则把「翻倍」误当差异;
|
|
94
108
|
- **静态 grep 到 Vue2 写法 ≠ 运行时一定失效**:失效与否取决于消费方 / 是否被平台全局样式兜住 / 组件运行时兼容(如 JSX `slot=` 在 el-popover reference 失效、在 el-dropdown 正常),必须运行时实证再判改不改。
|
|
95
109
|
|
|
@@ -118,6 +132,7 @@ epx 的产品/项目远程库(`window.library.<pkg>`,由 `FM_SYSTEM_WEBPACK`
|
|
|
118
132
|
`FM_SYSTEM_WEBPACK` 里仍只配那两条 url,其余按相对路径取。
|
|
119
133
|
3. **`chunks/` 的 `import()` 需要文件服务给 CORS 头**,跨域没配会整库降级。
|
|
120
134
|
4. `index.deps.json` **必须与 index.js 同目录同名一并上传**,漏传不报错但精确 ensure 会静默退化。
|
|
135
|
+
5. 样式隔离有改动时,逐个核对修改的 style 块和最终 CSS;完成 F15 的组件外同名元素及跨页面验收。构建和静态扫描通过不能替代这一步;未测项明确记录为待验证。
|
|
121
136
|
|
|
122
137
|
## 常见错误
|
|
123
138
|
|