chore(mp-harmony): vue.config.js 顶层 IIFE 集成 runSyncCheck (4 处一致性自动校验)
背景:
之前 vue.config.js 顶层 IIFE 只调 fixSubpackageModuleNames 修 5 个子包 name,
但漏改 build-profile.json5 / entry/oh-package.json5 / ascf_build/ 目录时
没有任何提示, 用户在 HBuilderX 看不到错误, 直到 DevEco ohpm 报错才发现。
改动:
1. scripts/fix-subpackage-module-names.js 新增 runSyncCheck() 函数:
- 读取 har-deps-required.json5 (whitelist) 作为单一事实源 (优先 json5 包,
失败回退手写解析)
- 扫描 3 个地方的一致性: build-profile.json5 modules / entry/oh-package.json5
file: 依赖 / ascf_build/ 实际目录
- 不一致时 console 打印明确错误 + 修复步骤 (1, 2, 3, 4 个文件)
- 默认不抛错 (silent: false 仅 console 输出, exitOnError: false)
- 暴露为 module.exports.runSyncCheck
2. vue.config.js 顶层 IIFE 集成:
- 修完 name 后调 runSyncCheck()
- HBuilderX 触发 require vue.config.js 时立即执行
- 不阻塞 vue-cli-service, 但 console 输出立刻告知用户漏改位置
- 鸿蒙端的硬性错误 (ohpm "Field IS Empty") 仍由 DevEco 抛出
端到端验证:
1. 故意在 whitelist 加 pages_extra (未同步其他 3 处)
→ vue.config.js require 立即输出:
✘ build-profile.json5 缺失子包: [pages_extra]
✘ entry/oh-package.json5 缺失 file: 依赖: [pages_extra]
✘ ascf_build/ 目录缺失子包: [pages_extra]
修复: 1. entry/har-deps-required.json5 ... 2. mp-harmony/build-profile.json5 ...
3. entry/oh-package.json5 ... 4. ascf_build/<pkg>/ 实际目录
2. 故意清空 pages_tool 的 name 字段
→ 修成 "pages_tool" + 跑 sync check, 输出 ✓ 5 个子包配置完全一致
module.exports 仍只有白名单字段 (productionSourceMap, configureWebpack),
vue-cli-service 不会报 "Invalid options" 错。
依赖: 项目已有 json5 包, 无需新装
This commit is contained in:
@@ -261,6 +261,162 @@ function main() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步子包配置一致性检查 (被 vue.config.js 顶层 IIFE 调用)
|
||||
*
|
||||
* 用途: HBuilderX 触发 require('./vue.config.js') 时, 在修完 name 之后
|
||||
* 跑一次 4 处一致性检查, 立即告诉用户哪些地方没改。
|
||||
*
|
||||
* 检查项 (复用 SUBPACKAGE_NAMES 数组):
|
||||
* 1. mp-harmony/build-profile.json5 的 modules 数组 (排除 entry)
|
||||
* 2. entry/oh-package.json5 的 file: 依赖
|
||||
* 3. ascf_build 实际目录
|
||||
*
|
||||
* 与 scripts/check-subpackage-sync.js 的区别:
|
||||
* - check-subpackage-sync.js: CLI/CI 用, --strict 可 exit 1
|
||||
* - runSyncCheck: vue.config.js IIFE 用, 默认不抛错, 仅打印
|
||||
*
|
||||
* @param {object} [opts]
|
||||
* @param {boolean} [opts.silent=false] - true 时不打日志
|
||||
* @param {boolean} [opts.exitOnError=false] - true 时不一致即抛错 (CLI 模式)
|
||||
* @returns {{ok: boolean, errors: string[], warnings: string[]}}
|
||||
*/
|
||||
function runSyncCheck({ silent = false, exitOnError = false } = {}) {
|
||||
const log = silent ? () => {} : console.log;
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
|
||||
// 读取白名单 (从 har-deps-required.json5 拿, 与 check-subpackage-sync.js 保持一致)
|
||||
// 注: 优先用 json5 npm 包 (项目已装), 失败则回退到内置 SUBPACKAGE_NAMES
|
||||
const configPath = path.join(ROOT, 'stub-app-projects', 'mp-harmony', 'entry', 'har-deps-required.json5');
|
||||
let canonical = SUBPACKAGE_NAMES.slice().sort();
|
||||
try {
|
||||
if (fs.existsSync(configPath)) {
|
||||
const raw = fs.readFileSync(configPath, 'utf8');
|
||||
let cfg = null;
|
||||
try {
|
||||
// 优先: json5 包 (支持裸 key, 注释, 单引号字符串)
|
||||
cfg = require('json5').parse(raw);
|
||||
} catch (e1) {
|
||||
// 回退: 手写 JSON5 解析 (剥注释后用 JSON.parse)
|
||||
try {
|
||||
const cleaned = stripJson5Comments(raw);
|
||||
cfg = JSON.parse(cleaned);
|
||||
} catch (e2) {
|
||||
if (!silent) console.warn(` ⚠️ har-deps-required.json5 解析失败 (json5: ${e1.message}; json: ${e2.message}), 用内置 SUBPACKAGE_NAMES`);
|
||||
}
|
||||
}
|
||||
if (cfg && Array.isArray(cfg.requiredHarDeps) && cfg.requiredHarDeps.length) {
|
||||
canonical = cfg.requiredHarDeps.slice().sort();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (!silent) console.warn(' ⚠️ 读取 har-deps-required.json5 失败, 用内置 SUBPACKAGE_NAMES:', e.message);
|
||||
}
|
||||
|
||||
const canonicalSet = new Set(canonical);
|
||||
const errors = [];
|
||||
const warnings = [];
|
||||
|
||||
// 工具: 列出某目录下的子目录
|
||||
function listSubdirs(p) {
|
||||
try {
|
||||
return fs.readdirSync(p, { withFileTypes: true })
|
||||
.filter(e => e.isDirectory())
|
||||
.map(e => e.name)
|
||||
.sort();
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function diff(b) {
|
||||
const bSet = new Set(b);
|
||||
return {
|
||||
onlyA: [...canonicalSet].filter(x => !bSet.has(x)),
|
||||
onlyB: [...bSet].filter(x => !canonicalSet.has(x)),
|
||||
};
|
||||
}
|
||||
|
||||
// === 检查 1: build-profile.json5 ===
|
||||
const buildProfilePath = path.join(ROOT, 'stub-app-projects', 'mp-harmony', 'build-profile.json5');
|
||||
let buildProfileModules = [];
|
||||
if (!fs.existsSync(buildProfilePath)) {
|
||||
warnings.push(`build-profile.json5 不存在: ${buildProfilePath}`);
|
||||
} else {
|
||||
try {
|
||||
const raw = fs.readFileSync(buildProfilePath, 'utf8').replace(/\/\/.*$/gm, '');
|
||||
const bp = JSON.parse(raw);
|
||||
buildProfileModules = (bp.modules || []).map(m => m.name).filter(n => n && n !== 'entry');
|
||||
} catch (e) {
|
||||
errors.push(`build-profile.json5 解析失败: ${e.message}`);
|
||||
}
|
||||
}
|
||||
const d1 = diff(buildProfileModules);
|
||||
if (d1.onlyA.length) errors.push(`build-profile.json5 缺失子包: [${d1.onlyA.join(', ')}]`);
|
||||
if (d1.onlyB.length) errors.push(`build-profile.json5 多了子包: [${d1.onlyB.join(', ')}]`);
|
||||
|
||||
// === 检查 2: entry/oh-package.json5 ===
|
||||
const ohPkgPath = path.join(ROOT, 'stub-app-projects', 'mp-harmony', 'entry', 'oh-package.json5');
|
||||
let ohPkgDeps = [];
|
||||
if (!fs.existsSync(ohPkgPath)) {
|
||||
warnings.push(`entry/oh-package.json5 不存在: ${ohPkgPath}`);
|
||||
} else {
|
||||
try {
|
||||
const raw = fs.readFileSync(ohPkgPath, 'utf8').replace(/\/\/.*$/gm, '');
|
||||
const op = JSON.parse(raw);
|
||||
const deps = op.dependencies || {};
|
||||
ohPkgDeps = Object.keys(deps).filter(k => deps[k] && deps[k].startsWith('file:'));
|
||||
} catch (e) {
|
||||
errors.push(`entry/oh-package.json5 解析失败: ${e.message}`);
|
||||
}
|
||||
}
|
||||
const d2 = diff(ohPkgDeps);
|
||||
if (d2.onlyA.length) errors.push(`entry/oh-package.json5 缺失 file: 依赖: [${d2.onlyA.join(', ')}]`);
|
||||
if (d2.onlyB.length) warnings.push(`entry/oh-package.json5 多了 file: 依赖: [${d2.onlyB.join(', ')}] (可能是新子包未更新白名单)`);
|
||||
|
||||
// === 检查 3: ascf_build 实际目录 ===
|
||||
const ascfBuildRoot = path.join(ROOT, 'stub-app-projects', 'mp-harmony', 'ascf', 'ascf_build');
|
||||
const ascfBuildDirs = listSubdirs(ascfBuildRoot);
|
||||
const d3 = diff(ascfBuildDirs);
|
||||
if (d3.onlyA.length) errors.push(`ascf_build/ 目录缺失子包: [${d3.onlyA.join(', ')}]`);
|
||||
if (d3.onlyB.length) warnings.push(`ascf_build/ 多了子包: [${d3.onlyB.join(', ')}] (可能是历史遗留)`);
|
||||
|
||||
// === 输出 ===
|
||||
if (silent) {
|
||||
// 静默模式仅返回结果
|
||||
return { ok: errors.length === 0, errors, warnings };
|
||||
}
|
||||
|
||||
const c = (s, color) => {
|
||||
if (!process.stdout.isTTY) return s;
|
||||
const codes = { red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', cyan: '\x1b[36m', gray: '\x1b[90m', reset: '\x1b[0m' };
|
||||
return codes[color] + s + codes.reset;
|
||||
};
|
||||
|
||||
if (errors.length === 0 && warnings.length === 0) {
|
||||
log(c(`\n🔍 [sync check] ✓ ${canonical.length} 个子包在 3 处配置完全一致 (build-profile / oh-package / ascf_build)`, 'green'));
|
||||
} else {
|
||||
log(c(`\n🔍 [sync check] ${errors.length === 0 ? '⚠️' : '✘'} 4 处子包配置不一致:`, errors.length === 0 ? 'yellow' : 'red'));
|
||||
for (const w of warnings) log(c(` ⚠️ ${w}`, 'yellow'));
|
||||
for (const e of errors) log(c(` ✘ ${e}`, 'red'));
|
||||
if (errors.length > 0) {
|
||||
log(c(`\n 修复: 同步更新以下 4 个文件 (whitelist 是 har-deps-required.json5):`, 'gray'));
|
||||
log(c(` 1. entry/har-deps-required.json5 (whitelist, 单一事实源)`, 'gray'));
|
||||
log(c(` 2. mp-harmony/build-profile.json5 modules 数组`, 'gray'));
|
||||
log(c(` 3. entry/oh-package.json5 dependencies 加 "file:../ascf/ascf_build/<pkg>"`, 'gray'));
|
||||
log(c(` 4. ascf_build/<pkg>/ 实际目录`, 'gray'));
|
||||
log(c(` DevEco Build 仍会因 ohpm 校验而失败, 修完再发`, 'gray'));
|
||||
}
|
||||
}
|
||||
log('');
|
||||
|
||||
if (exitOnError && errors.length > 0) {
|
||||
throw new Error(`[sync check] ${errors.length} 个不一致`);
|
||||
}
|
||||
|
||||
return { ok: errors.length === 0, errors, warnings };
|
||||
}
|
||||
|
||||
// 判断是否作为 CLI 直接执行 (vs 作为模块被 require)
|
||||
if (require.main === module) {
|
||||
main();
|
||||
@@ -268,5 +424,6 @@ if (require.main === module) {
|
||||
|
||||
module.exports = {
|
||||
fixSubpackageModuleNames,
|
||||
runSyncCheck,
|
||||
SUBPACKAGE_NAMES,
|
||||
};
|
||||
Reference in New Issue
Block a user