@dd-code/uni-tools 1.0.14 → 1.0.16
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/README.md +10 -24
- package/dist/cli.js +78 -36
- package/dist/cli.mjs.js +78 -36
- package/dist/index.js +289 -33
- package/dist/index.mjs.js +289 -33
- package/package.json +2 -1
package/dist/index.mjs.js
CHANGED
|
@@ -627,6 +627,11 @@ var downloadProjectFiles = function (manifestList) { return __awaiter(void 0, vo
|
|
|
627
627
|
});
|
|
628
628
|
}); };
|
|
629
629
|
|
|
630
|
+
/**
|
|
631
|
+
* 计算需要下载/更新的 Manifest 列表
|
|
632
|
+
* - 比较 node_modules 缓存中的 manifest 哈希与远端 manifest 哈希
|
|
633
|
+
* - 返回需要更新的清单(用于后续下载项目文件到本地缓存)
|
|
634
|
+
*/
|
|
630
635
|
var checkDownloadFilesIsExpired = function (manifestList) {
|
|
631
636
|
var filterList = manifestList.filter(function (conf) {
|
|
632
637
|
var targetPath = getNodeModulesEnvAppCodeFilePath(conf, MANIFEST_NAME);
|
|
@@ -636,6 +641,14 @@ var checkDownloadFilesIsExpired = function (manifestList) {
|
|
|
636
641
|
});
|
|
637
642
|
return filterList;
|
|
638
643
|
};
|
|
644
|
+
/**
|
|
645
|
+
* Manifest 管理器(构建态/运行态共享状态)
|
|
646
|
+
* - value:当前应用 Manifest(会随构建过程逐步填充)
|
|
647
|
+
* - setEnv:读取 cli/vite 环境,设置 isRoot/isServe/code/appCode/publicPath 等
|
|
648
|
+
* - setPagesJson/setFiles/setExposes:在插件流程中填充 pages 与产物清单与运行时暴露
|
|
649
|
+
* - saveFile:落盘 Manifest(计算 hash,剔除临时字段 isServe)
|
|
650
|
+
* - dependencies:记录其他应用的 Manifest(用于主应用合并)
|
|
651
|
+
*/
|
|
639
652
|
var createManifestManager = function () {
|
|
640
653
|
var envObj = process.env;
|
|
641
654
|
var row = {
|
|
@@ -688,25 +701,16 @@ var createManifestManager = function () {
|
|
|
688
701
|
},
|
|
689
702
|
};
|
|
690
703
|
};
|
|
691
|
-
|
|
692
|
-
|
|
704
|
+
/**
|
|
705
|
+
* 从 CDN 获取主应用 Manifest(ROOT_APP_CODE)
|
|
706
|
+
* - 仅用于校验/兜底:优先使用本地 dist 或缓存 node_modules 的 Manifest
|
|
707
|
+
*/
|
|
708
|
+
var downloadMainAppManifestJson = function (currentManifest) { return __awaiter(void 0, void 0, void 0, function () {
|
|
709
|
+
var mode, code, cdnUrl, manifestJson;
|
|
693
710
|
return __generator(this, function (_b) {
|
|
694
711
|
switch (_b.label) {
|
|
695
712
|
case 0:
|
|
696
|
-
|
|
697
|
-
pageManifest = uniReadFile(path.join(process.env.UNI_OUTPUT_DIR, MANIFEST_NAME));
|
|
698
|
-
if (Object.keys(pageManifest).length !== 0) {
|
|
699
|
-
return [2 /*return*/, pageManifest];
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
catch (_c) { }
|
|
703
|
-
try {
|
|
704
|
-
nodeModulesManifest = uniReadFile(path.join(SAVE_CDN_FILE_PATH, mode, ROOT_APP_CODE, MANIFEST_NAME));
|
|
705
|
-
if (Object.keys(nodeModulesManifest).length !== 0) {
|
|
706
|
-
return [2 /*return*/, nodeModulesManifest];
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
catch (_d) { }
|
|
713
|
+
mode = currentManifest.mode, code = currentManifest.code;
|
|
710
714
|
_b.label = 1;
|
|
711
715
|
case 1:
|
|
712
716
|
_b.trys.push([1, 3, , 4]);
|
|
@@ -718,19 +722,72 @@ var getRootMainManifestJson = function (code, mode) { return __awaiter(void 0, v
|
|
|
718
722
|
return [4 /*yield*/, fetchFileByPath(cdnUrl)];
|
|
719
723
|
case 2:
|
|
720
724
|
manifestJson = _b.sent();
|
|
721
|
-
|
|
722
|
-
return [2 /*return*/, manifestJson];
|
|
723
|
-
}
|
|
724
|
-
return [3 /*break*/, 4];
|
|
725
|
+
return [2 /*return*/, manifestJson];
|
|
725
726
|
case 3:
|
|
726
727
|
_b.sent();
|
|
727
728
|
return [3 /*break*/, 4];
|
|
728
|
-
case 4: return [2 /*return*/, {
|
|
729
|
+
case 4: return [2 /*return*/, {}];
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
}); };
|
|
733
|
+
/**
|
|
734
|
+
* 读取根主应用 Manifest(优先级:dist > node_modules 缓存 > CDN)
|
|
735
|
+
* - 兼容不同构建场景:
|
|
736
|
+
* - isServe(WS 联调)或内部构建(inner build)下无需校验哈希
|
|
737
|
+
* - 其他场景严格校验本地与远端 Manifest 的 hash 一致性
|
|
738
|
+
* - 选择顺序:
|
|
739
|
+
* 1) 当前构建输出目录的 app.json(dist)
|
|
740
|
+
* 2) node_modules 缓存目录中的 app.json(save cdn file path)
|
|
741
|
+
* 3) 远端 CDN 拉取的 Manifest(兜底)
|
|
742
|
+
*/
|
|
743
|
+
var getRootMainManifestJson = function (currentManifest) { return __awaiter(void 0, void 0, void 0, function () {
|
|
744
|
+
var mode, isInnerBuild, isWsBuild, needCheckHash, originHostManifestJson, checkHash, distPagePath, pageManifest, nodeModulePath, nodeModulesManifest;
|
|
745
|
+
return __generator(this, function (_a) {
|
|
746
|
+
switch (_a.label) {
|
|
747
|
+
case 0:
|
|
748
|
+
mode = currentManifest.mode;
|
|
749
|
+
isInnerBuild = checkIsInnerBuild();
|
|
750
|
+
isWsBuild = currentManifest.isServe;
|
|
751
|
+
needCheckHash = !(isWsBuild || isInnerBuild);
|
|
752
|
+
return [4 /*yield*/, downloadMainAppManifestJson(currentManifest)];
|
|
753
|
+
case 1:
|
|
754
|
+
originHostManifestJson = _a.sent();
|
|
755
|
+
checkHash = function (target) {
|
|
756
|
+
if ((originHostManifestJson === null || originHostManifestJson === void 0 ? void 0 : originHostManifestJson.hash) && needCheckHash && (originHostManifestJson === null || originHostManifestJson === void 0 ? void 0 : originHostManifestJson.hash) !== target.hash) {
|
|
757
|
+
throw new Error("originHostManifestJson hash not equal");
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
try {
|
|
761
|
+
distPagePath = path.join(process.env.UNI_OUTPUT_DIR, MANIFEST_NAME);
|
|
762
|
+
pageManifest = uniReadFile(distPagePath);
|
|
763
|
+
checkHash(pageManifest);
|
|
764
|
+
console.log("distPagePath done");
|
|
765
|
+
if (Object.keys(pageManifest).length !== 0) {
|
|
766
|
+
return [2 /*return*/, pageManifest];
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
catch (_b) { }
|
|
770
|
+
try {
|
|
771
|
+
nodeModulePath = path.join(SAVE_CDN_FILE_PATH, mode, ROOT_APP_CODE, MANIFEST_NAME);
|
|
772
|
+
nodeModulesManifest = uniReadFile(nodeModulePath);
|
|
773
|
+
checkHash(nodeModulesManifest);
|
|
774
|
+
console.log("nodeModulePath done");
|
|
775
|
+
if (Object.keys(nodeModulesManifest).length !== 0) {
|
|
776
|
+
return [2 /*return*/, nodeModulesManifest];
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
catch (_c) { }
|
|
780
|
+
console.log('origin done');
|
|
781
|
+
return [2 /*return*/, originHostManifestJson];
|
|
729
782
|
}
|
|
730
783
|
});
|
|
731
784
|
}); };
|
|
732
785
|
|
|
733
786
|
var num = 5;
|
|
787
|
+
/**
|
|
788
|
+
* 从主应用 HTTP 服务拉取当前进程环境(含 UNI_OUTPUT_DIR)
|
|
789
|
+
* - serve 非联调模式下,子应用通过此接口获知主应用输出根目录
|
|
790
|
+
*/
|
|
734
791
|
var getMainProcess = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
735
792
|
var URL, mainProcess, result;
|
|
736
793
|
return __generator(this, function (_a) {
|
|
@@ -748,6 +805,10 @@ var getMainProcess = function () { return __awaiter(void 0, void 0, void 0, func
|
|
|
748
805
|
}
|
|
749
806
|
});
|
|
750
807
|
}); };
|
|
808
|
+
/**
|
|
809
|
+
* 简易重试(最多 5 次,每次 100ms)
|
|
810
|
+
* - 主应用 HTTP 服务启动可能有延迟,子应用循环尝试获取
|
|
811
|
+
*/
|
|
751
812
|
var getMainProcessLoop = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
752
813
|
var mainProcess;
|
|
753
814
|
return __generator(this, function (_a) {
|
|
@@ -803,6 +864,10 @@ var resetOutDir = function (currentManifestJson, config) { return __awaiter(void
|
|
|
803
864
|
process.env.MFE_ROOT_OUTPUT_DIR = (_a = process.env.MFE_SOURCE_OUTPUT_DIR) === null || _a === void 0 ? void 0 : _a.replace(exp, "/").replace(/\/$/, "");
|
|
804
865
|
// if (!currentManifestJson.value.isRoot)
|
|
805
866
|
// console.log(config);
|
|
867
|
+
/**
|
|
868
|
+
* 非内部构建下,将 UNI_OUTPUT_DIR 统一指向主应用根输出目录
|
|
869
|
+
* - 便于后续写入 app.json 与拷贝产物
|
|
870
|
+
*/
|
|
806
871
|
if (!checkIsInnerBuild()) {
|
|
807
872
|
// setTimeout(() => {
|
|
808
873
|
process.env.UNI_OUTPUT_DIR = process.env.MFE_ROOT_OUTPUT_DIR;
|
|
@@ -813,6 +878,11 @@ var resetOutDir = function (currentManifestJson, config) { return __awaiter(void
|
|
|
813
878
|
});
|
|
814
879
|
}); };
|
|
815
880
|
|
|
881
|
+
/**
|
|
882
|
+
* 接管 uni 内置复制钩子
|
|
883
|
+
* - 通过 before/after 钩子记录从源到目标的拷贝行为
|
|
884
|
+
* - 便于在 Manifest 插件中收集运行期拷贝产生的文件清单
|
|
885
|
+
*/
|
|
816
886
|
var addUniCopyPluginHook = function (_a) {
|
|
817
887
|
var before = _a.before, after = _a.after;
|
|
818
888
|
var FileWatcher = require("@dcloudio/uni-cli-shared/dist/watcher").FileWatcher;
|
|
@@ -834,6 +904,11 @@ var copyFilesByTargetPath = function (sourcePath, targetPath) {
|
|
|
834
904
|
fsExtra.ensureDirSync(targetDir);
|
|
835
905
|
}
|
|
836
906
|
catch (err) { }
|
|
907
|
+
/**
|
|
908
|
+
* 内容比较:
|
|
909
|
+
* - 仅当源/目标均为文件且内容完全一致时跳过,避免无效写入
|
|
910
|
+
* - 目录或不存在的目标不跳过
|
|
911
|
+
*/
|
|
837
912
|
var shouldSkip = function () {
|
|
838
913
|
try {
|
|
839
914
|
var s = fs.statSync(sourcePath);
|
|
@@ -842,6 +917,11 @@ var copyFilesByTargetPath = function (sourcePath, targetPath) {
|
|
|
842
917
|
return false;
|
|
843
918
|
var sb = fs.readFileSync(sourcePath);
|
|
844
919
|
var tb = fs.readFileSync(targetPath);
|
|
920
|
+
/**
|
|
921
|
+
* Buffer 比较:
|
|
922
|
+
* - 长度与内容完全一致时跳过
|
|
923
|
+
* - 保留二进制级别比较,适配图片/字体等非文本文件
|
|
924
|
+
*/
|
|
845
925
|
return sb.length === tb.length && sb.equals(tb);
|
|
846
926
|
}
|
|
847
927
|
catch (_a) {
|
|
@@ -930,6 +1010,13 @@ var initPrePagesJson = function () {
|
|
|
930
1010
|
var pagesPath = path.resolve(process.cwd(), "src/pages.json");
|
|
931
1011
|
return fs.readFileSync(pagesPath, "utf-8");
|
|
932
1012
|
};
|
|
1013
|
+
/**
|
|
1014
|
+
* 解析并预处理 pages.json
|
|
1015
|
+
* - 读取全局 preprocess 上下文(根据平台注入不同变量)
|
|
1016
|
+
* - 使用 @dcloudio 的 preprocess 对 pages.json 做条件编译(如 #ifdef/#endif)
|
|
1017
|
+
* - 返回 JS 对象形式的 pages 配置
|
|
1018
|
+
* - isFormat=true 且平台为 mp-weixin 时,转换为微信特定格式(去除 globalStyle 并映射到 window/subPackages)
|
|
1019
|
+
*/
|
|
933
1020
|
var getPagesJson = function (jsonFile, isFormat) {
|
|
934
1021
|
if (isFormat === void 0) { isFormat = false; }
|
|
935
1022
|
var platform = process.env.UNI_PLATFORM;
|
|
@@ -942,6 +1029,12 @@ var getPagesJson = function (jsonFile, isFormat) {
|
|
|
942
1029
|
}
|
|
943
1030
|
return pagesConfig;
|
|
944
1031
|
};
|
|
1032
|
+
/**
|
|
1033
|
+
* 将 Uni 的 pages.json 转换为微信小程序格式
|
|
1034
|
+
* - window:映射 globalStyle,并兼容 mp-weixin 特定字段
|
|
1035
|
+
* - subPackages:后续会在 app-json.ts 中由各子应用补充到主应用
|
|
1036
|
+
* - usingComponents:保留全局组件声明
|
|
1037
|
+
*/
|
|
945
1038
|
var transformToWeixinFormat = function (uniPagesConfig) {
|
|
946
1039
|
var _a;
|
|
947
1040
|
var weixinConfig = __assign({ pages: [], window: {}, tabBar: null, subPackages: [], usingComponents: {} }, uniPagesConfig);
|
|
@@ -1007,6 +1100,19 @@ var transformToWeixinFormat = function (uniPagesConfig) {
|
|
|
1007
1100
|
};
|
|
1008
1101
|
|
|
1009
1102
|
// import { addRunningAppToSave } from "../running-core";
|
|
1103
|
+
/**
|
|
1104
|
+
* Manifest 采集与产物清单插件
|
|
1105
|
+
* - 目标:收集构建阶段产物与运行期拷贝的文件列表,生成可供主应用消费的文件清单
|
|
1106
|
+
* - CollectFiles:
|
|
1107
|
+
* - emitted:bundle 产物与拷贝文件的统一索引(fileName -> fileUrl)
|
|
1108
|
+
* - callbackFiles:拦截 uni 的复制钩子,收集被拷贝的源与目标相对路径
|
|
1109
|
+
* - copyFilesToPublishDir:将 outDir 下的产物拷贝到 publish 目录,便于后续上载/分发
|
|
1110
|
+
* - 插件钩子:
|
|
1111
|
+
* - config:记录 outDir,拦截 uni 拷贝行为
|
|
1112
|
+
* - renderStart:解析 pages.json,写入到 Manifest 状态
|
|
1113
|
+
* - writeBundle:收集本次打包输出的 chunk 信息
|
|
1114
|
+
* - closeBundle:汇总拷贝与产物,写入 Manifest 文件并拷贝到发布目录
|
|
1115
|
+
*/
|
|
1010
1116
|
var CollectFiles = /** @class */ (function () {
|
|
1011
1117
|
function CollectFiles() {
|
|
1012
1118
|
this.callbackFiles = [];
|
|
@@ -1026,6 +1132,11 @@ var CollectFiles = /** @class */ (function () {
|
|
|
1026
1132
|
Object.keys(bundles).forEach(function (key) {
|
|
1027
1133
|
var boundle = bundles[key];
|
|
1028
1134
|
var fileName = boundle.fileName, source = boundle.source, code = boundle.code;
|
|
1135
|
+
/**
|
|
1136
|
+
* code/source:
|
|
1137
|
+
* - chunk 使用 code 字段,asset 使用 source 字段
|
|
1138
|
+
* - 统一抽象为 fileInfo 行(包含 fileUrl 与大小哈希)
|
|
1139
|
+
*/
|
|
1029
1140
|
var fileInfo = genreFileInfoRow({ fileName: fileName, source: code || source });
|
|
1030
1141
|
_this.emitted.set(fileName, fileInfo);
|
|
1031
1142
|
});
|
|
@@ -1120,6 +1231,12 @@ var createManifestPlugin = function (manifestJson) {
|
|
|
1120
1231
|
};
|
|
1121
1232
|
};
|
|
1122
1233
|
|
|
1234
|
+
/**
|
|
1235
|
+
* 主应用 app.json 渲染与写入
|
|
1236
|
+
* - renderPagesJsonByArray:将多个子应用的 pages.json 以分包形式合入主应用
|
|
1237
|
+
* - genreFullMainAppJsonByManifestList:按 Manifest 列表生成完整的主应用 app.json
|
|
1238
|
+
* - genreNewAppJson:内容比较后写入 app.json,避免无效写入导致的频繁重启
|
|
1239
|
+
*/
|
|
1123
1240
|
var renderPagesJsonByArray = function (appPages, pageJson) {
|
|
1124
1241
|
var _loop_1 = function (app) {
|
|
1125
1242
|
var _a = getPagesJson(JSON.stringify((app === null || app === void 0 ? void 0 : app.pagesJson) || {}), true).pages, pages = _a === void 0 ? [] : _a;
|
|
@@ -1153,6 +1270,14 @@ var genreNewAppJson = function (outputPageJsonPath, appJson, manifestList) {
|
|
|
1153
1270
|
}
|
|
1154
1271
|
};
|
|
1155
1272
|
|
|
1273
|
+
/**
|
|
1274
|
+
* 运行期联调核心
|
|
1275
|
+
* - getAppsManifestList:在主应用非联调构建模式下,返回所有子应用的 Manifest 路径列表
|
|
1276
|
+
* - startDistWatcher:监听子应用输出目录的父级变更,增量拷贝到主应用分包路径,并上报变更
|
|
1277
|
+
* - 设计要点:
|
|
1278
|
+
* - 监听父级目录以覆盖新增/删除场景;通过 `isTargetFile` 过滤目标变化
|
|
1279
|
+
* - 拷贝时进行内容比较,避免触发无效写入
|
|
1280
|
+
*/
|
|
1156
1281
|
var getAppsManifestList = function (mode) {
|
|
1157
1282
|
var _a;
|
|
1158
1283
|
var manifest = formatCliCommandConfig(mode);
|
|
@@ -1182,6 +1307,11 @@ var startDistWatcher = function (mainPwd, onReady, onChange) {
|
|
|
1182
1307
|
var filePath = path.resolve(root);
|
|
1183
1308
|
checkAndgenreDir(filePath);
|
|
1184
1309
|
var parentDir = path.dirname(filePath);
|
|
1310
|
+
/**
|
|
1311
|
+
* 监听父级目录:
|
|
1312
|
+
* - uni 输出目录在构建时可能新增/删除文件或目录,监听父级可捕捉到此类变化
|
|
1313
|
+
* - 通过 isTargetFile 精确过滤与目标目录相关的事件
|
|
1314
|
+
*/
|
|
1185
1315
|
var watcher = createFileWatcher(parentDir);
|
|
1186
1316
|
var isTargetFile = function (p) {
|
|
1187
1317
|
return p.startsWith(filePath + path.sep) || p === filePath;
|
|
@@ -1196,6 +1326,11 @@ var startDistWatcher = function (mainPwd, onReady, onChange) {
|
|
|
1196
1326
|
var sourcePath = p;
|
|
1197
1327
|
var targetPath = path.join(mainPwd, rel);
|
|
1198
1328
|
if (["add", "change"].includes(evt)) {
|
|
1329
|
+
/**
|
|
1330
|
+
* 增量拷贝:
|
|
1331
|
+
* - 目录结构保持一致,从子应用输出拷贝到主应用分包路径
|
|
1332
|
+
* - 通过 copyFilesByTargetPath 的内容比较避免重复写入
|
|
1333
|
+
*/
|
|
1199
1334
|
copyFilesByTargetPath(sourcePath, targetPath);
|
|
1200
1335
|
}
|
|
1201
1336
|
onChange === null || onChange === void 0 ? void 0 : onChange({ type: evt, p: p, sourcePath: sourcePath, targetPath: targetPath });
|
|
@@ -1204,6 +1339,13 @@ var startDistWatcher = function (mainPwd, onReady, onChange) {
|
|
|
1204
1339
|
};
|
|
1205
1340
|
|
|
1206
1341
|
var app = null;
|
|
1342
|
+
/**
|
|
1343
|
+
* 创建开发态 HTTP 服务
|
|
1344
|
+
* - 单例复用:避免重复创建与重复监听
|
|
1345
|
+
* - 路由:
|
|
1346
|
+
* - GET `${HTTP_PATH}/root-path`:返回当前进程的环境变量(主应用输出位置等)
|
|
1347
|
+
* - 与 WS 服务配合:WSServer 绑定同一个 HTTP server 进行升级
|
|
1348
|
+
*/
|
|
1207
1349
|
var createHttpServer = function () {
|
|
1208
1350
|
if (app)
|
|
1209
1351
|
return { server: app, start: function () { } };
|
|
@@ -1213,6 +1355,11 @@ var createHttpServer = function () {
|
|
|
1213
1355
|
res.send(process.env);
|
|
1214
1356
|
});
|
|
1215
1357
|
app.use(cors({ origin: "*" }));
|
|
1358
|
+
/**
|
|
1359
|
+
* 返回:
|
|
1360
|
+
* - server:HTTP Server 实例(供 WS 复用)
|
|
1361
|
+
* - start(type):启动监听并输出日志,type 用于日志区分('http' | 'ws')
|
|
1362
|
+
*/
|
|
1216
1363
|
return {
|
|
1217
1364
|
server: server,
|
|
1218
1365
|
start: function (type) {
|
|
@@ -1230,6 +1377,10 @@ var WsServer = /** @class */ (function () {
|
|
|
1230
1377
|
this.httpServer = createHttpServer();
|
|
1231
1378
|
this.clientMap = new Map();
|
|
1232
1379
|
}
|
|
1380
|
+
/**
|
|
1381
|
+
* 单例获取 WS 服务实例
|
|
1382
|
+
* - 若已创建则复用并更新消息回调
|
|
1383
|
+
*/
|
|
1233
1384
|
WsServer.getInstance = function (handleMessage) {
|
|
1234
1385
|
if (!WsServer.instance) {
|
|
1235
1386
|
WsServer.instance = new WsServer(handleMessage);
|
|
@@ -1257,12 +1408,18 @@ var WsServer = /** @class */ (function () {
|
|
|
1257
1408
|
this.handleMessage = callback;
|
|
1258
1409
|
}
|
|
1259
1410
|
};
|
|
1411
|
+
/**
|
|
1412
|
+
* 向指定 appCode 的客户端发送消息
|
|
1413
|
+
*/
|
|
1260
1414
|
WsServer.prototype.sendMessageToApp = function (appCode, message) {
|
|
1261
1415
|
var ws = this.clientMap.get(appCode);
|
|
1262
1416
|
if (ws) {
|
|
1263
1417
|
ws.send(typeof message === "string" ? message : JSON.stringify(message));
|
|
1264
1418
|
}
|
|
1265
1419
|
};
|
|
1420
|
+
/**
|
|
1421
|
+
* 连接事件:建立客户端映射并下发初始化信息(主应用输出目录)
|
|
1422
|
+
*/
|
|
1266
1423
|
WsServer.prototype.onConnection = function () {
|
|
1267
1424
|
var _this = this;
|
|
1268
1425
|
this.wss.on("connection", function (ws, request) {
|
|
@@ -1301,6 +1458,9 @@ var WsClientServer = /** @class */ (function () {
|
|
|
1301
1458
|
this.ws = null;
|
|
1302
1459
|
this.isConnected = false;
|
|
1303
1460
|
}
|
|
1461
|
+
/**
|
|
1462
|
+
* 获取客户端单例
|
|
1463
|
+
*/
|
|
1304
1464
|
WsClientServer.getInstance = function (handleMessage) {
|
|
1305
1465
|
if (!WsClientServer.instance) {
|
|
1306
1466
|
WsClientServer.instance = new WsClientServer(handleMessage);
|
|
@@ -1354,6 +1514,9 @@ var WsClientServer = /** @class */ (function () {
|
|
|
1354
1514
|
this.handleMessage = callback;
|
|
1355
1515
|
}
|
|
1356
1516
|
};
|
|
1517
|
+
/**
|
|
1518
|
+
* 简单重试策略:一定时间后重新连接
|
|
1519
|
+
*/
|
|
1357
1520
|
WsClientServer.prototype.retryConnect = function (appCode) {
|
|
1358
1521
|
var _this = this;
|
|
1359
1522
|
if (this.isConnected)
|
|
@@ -1378,6 +1541,20 @@ var WsClientServer = /** @class */ (function () {
|
|
|
1378
1541
|
// export const mfeServer = new WsServer();
|
|
1379
1542
|
// export const mfeClientServer = new WsClientServer();
|
|
1380
1543
|
|
|
1544
|
+
/**
|
|
1545
|
+
* 主应用插件(Main App)
|
|
1546
|
+
* - 服务端(根应用):
|
|
1547
|
+
* - 启动 WS + HTTP 服务,向子应用广播初始化信息(主应用输出目录)
|
|
1548
|
+
* - 接收子应用文件变更事件,拉取对应子应用 Manifest 并增量更新主应用 app.json
|
|
1549
|
+
* - 客户端(子应用):
|
|
1550
|
+
* - 连接主应用 WS,接收初始化 pwd 后将自身构建产物增量拷贝到主应用分包路径
|
|
1551
|
+
* - 在构建完成后启动本地 DistWatcher,监控自身输出变更并通过 WS 通知主应用
|
|
1552
|
+
* - 构建阶段:
|
|
1553
|
+
* - 合并所有依赖子应用的 pages.json,生成最终主应用 app.json,内容比较避免无效写入
|
|
1554
|
+
* - 关键点:
|
|
1555
|
+
* - `isBuild`/`isServe`/`isRoot` 三态控制插件行为,避免生产与联调逻辑相互影响
|
|
1556
|
+
* - `copyFilesByTargetPath` 与 `genreNewAppJson` 均内置内容比较,防止频繁重启
|
|
1557
|
+
*/
|
|
1381
1558
|
var filterManifestJsonListAndMainPageJson = function (manifestJsonList) {
|
|
1382
1559
|
var outputPageJsonPath = getMainAppJsonPath();
|
|
1383
1560
|
return {
|
|
@@ -1429,6 +1606,11 @@ var createMainAppPlugin = function (manifestJson) {
|
|
|
1429
1606
|
startDistWatcher(state.mainPwd, function () {
|
|
1430
1607
|
state.isWatcherReady = true;
|
|
1431
1608
|
}, function (change) {
|
|
1609
|
+
/**
|
|
1610
|
+
* 通过 WS 将子应用的输出变更上报主应用
|
|
1611
|
+
* - 包含事件类型、源/目标路径、相对路径等
|
|
1612
|
+
* - 主应用端在收到 CHANGE 后增量更新 app.json
|
|
1613
|
+
*/
|
|
1432
1614
|
state.fn = function () {
|
|
1433
1615
|
return state.mfeClientServer.sendMessage(E_WS_TYPE.CHANGE, __assign(__assign({}, change), { appCode: manifestJson.value.appCode }));
|
|
1434
1616
|
};
|
|
@@ -1446,6 +1628,10 @@ var createMainAppPlugin = function (manifestJson) {
|
|
|
1446
1628
|
copyFilesByTargetPath(sourcePath, targetPath);
|
|
1447
1629
|
};
|
|
1448
1630
|
var watchFile = function () {
|
|
1631
|
+
/**
|
|
1632
|
+
* 在非 serve + 主应用构建时,监听所有子应用 Manifest 文件变化
|
|
1633
|
+
* - 变化时重算并写入 app.json,保持主应用 pages 配置最新
|
|
1634
|
+
*/
|
|
1449
1635
|
var allManifest = getAppsManifestList(manifestJson.value.mode);
|
|
1450
1636
|
var watchFileList = allManifest.map(function (item) { return item.filePath; });
|
|
1451
1637
|
var watcher = createFileWatcher(watchFileList);
|
|
@@ -1471,13 +1657,16 @@ var createMainAppPlugin = function (manifestJson) {
|
|
|
1471
1657
|
start();
|
|
1472
1658
|
return [2 /*return*/];
|
|
1473
1659
|
}
|
|
1660
|
+
/**
|
|
1661
|
+
* 联调开发:启动根应用 WS 服务,负责给子应用下发初始化信息并接收变更事件
|
|
1662
|
+
*/
|
|
1474
1663
|
createMainAppServer();
|
|
1475
|
-
// const subs = findLocalSubApps();
|
|
1476
|
-
// if (subs.length) {
|
|
1477
|
-
// startLocalSubApps(subs, "mp-weixin", manifestJson.value.mode);
|
|
1478
|
-
// }
|
|
1479
1664
|
}
|
|
1480
1665
|
else {
|
|
1666
|
+
/**
|
|
1667
|
+
* 子应用:作为 WS 客户端连接主应用
|
|
1668
|
+
* - 收到 INIT 后,将自身产物拷贝到主应用分包路径
|
|
1669
|
+
*/
|
|
1481
1670
|
state.mfeClientServer = createMainAppClient(manifestJson, function (data) {
|
|
1482
1671
|
copyAppDistModule(data);
|
|
1483
1672
|
});
|
|
@@ -1547,10 +1736,35 @@ var createMainAppPlugin = function (manifestJson) {
|
|
|
1547
1736
|
];
|
|
1548
1737
|
};
|
|
1549
1738
|
|
|
1739
|
+
/**
|
|
1740
|
+
* 运行时暴露插件(Exposes)
|
|
1741
|
+
* - 目标:在页面/模块中以 `@dd-code/runtime` 或 `@dd-code/runtime/<name>` 引用主应用的公共导出
|
|
1742
|
+
* - 流程:
|
|
1743
|
+
* 1) configResolved:从主应用 Manifest 读取 exposes 映射('.'、'./axios' 等)
|
|
1744
|
+
* 2) resolveId:拦截并识别 runtime 请求
|
|
1745
|
+
* 3) load:按请求的子路径拼装 require 代码,指向主应用模块(使用相对路径计算)
|
|
1746
|
+
* 4) buildStart:为每个 exposes 键发射独立的入口 chunk,确保输出到根目录
|
|
1747
|
+
* 5) generateBundle:收集产物映射(fileName + exports),保存到当前 Manifest
|
|
1748
|
+
* - 注意:
|
|
1749
|
+
* - `RUNTIME_NAME_REGEXP` 用于识别所有 runtime 形式,键以 '.' 开头并支持层级 './xxx'
|
|
1750
|
+
* - require 的相对路径通过 `renderRuntimeCode` 按当前 appCode + 构建位置计算,保持稳定
|
|
1751
|
+
*/
|
|
1550
1752
|
var buildName = "mfe_runtime/__mfe_{template}_runtime__.js";
|
|
1551
1753
|
var RUNTIME_NAME = "@dd-code/runtime";
|
|
1552
1754
|
// const runtimeDir = 'mfe_runtime'
|
|
1553
1755
|
var RUNTIME_NAME_REGEXP = new RegExp(RUNTIME_NAME + "(/.*)?");
|
|
1756
|
+
/**
|
|
1757
|
+
* 生成 runtime 入口代码
|
|
1758
|
+
* - 参数:
|
|
1759
|
+
* - moduleExpose:主应用 exposes 配置中指定的模块信息({ path, exports })
|
|
1760
|
+
* - appCode:当前应用代码,用于计算运行时代码与目标模块的相对路径
|
|
1761
|
+
* - 相对路径计算:
|
|
1762
|
+
* - runtime 文件输出位置:mfe_runtime/__mfe_{template}_runtime__.js
|
|
1763
|
+
* - 运行时代码中 require 的相对路径需指向主应用根下的模块文件(如 store/index.js)
|
|
1764
|
+
* - deepPath = 相对路径(从 runtime 所在目录到项目根 "."),用于拼接 require('deepPath/<filePath>')
|
|
1765
|
+
* - 导出约定:
|
|
1766
|
+
* - 仅支持命名导出列表(exports: string[]),以 `export const {name} = require(...)` 形式暴露
|
|
1767
|
+
*/
|
|
1554
1768
|
var renderRuntimeCode = function (moduleExpose, appCode) {
|
|
1555
1769
|
var deepPath = path.relative(path.join(appCode, path.dirname(buildName)), ".");
|
|
1556
1770
|
var resultCode = "";
|
|
@@ -1568,12 +1782,19 @@ var createExposesPlugin = function (options, currentManifestJson) {
|
|
|
1568
1782
|
{
|
|
1569
1783
|
name: "@chagee:uni-exposes",
|
|
1570
1784
|
enforce: "post",
|
|
1785
|
+
/**
|
|
1786
|
+
* 读取主应用的 exposes 配置
|
|
1787
|
+
* - 来源:根应用构建时生成的 Manifest(含 exposes 映射)
|
|
1788
|
+
* - 示例:
|
|
1789
|
+
* { '.': { path: 'store/index.js', exports: ['userStore'] },
|
|
1790
|
+
* './axios': { path: 'axios/index.js', exports: ['axios'] } }
|
|
1791
|
+
*/
|
|
1571
1792
|
configResolved: function (config) {
|
|
1572
1793
|
return __awaiter(this, void 0, void 0, function () {
|
|
1573
1794
|
var manifestJson;
|
|
1574
1795
|
return __generator(this, function (_a) {
|
|
1575
1796
|
switch (_a.label) {
|
|
1576
|
-
case 0: return [4 /*yield*/, getRootMainManifestJson(currentManifestJson.value
|
|
1797
|
+
case 0: return [4 /*yield*/, getRootMainManifestJson(currentManifestJson.value)];
|
|
1577
1798
|
case 1:
|
|
1578
1799
|
manifestJson = _a.sent();
|
|
1579
1800
|
mainAppExposeCode = manifestJson.exposes || {};
|
|
@@ -1582,6 +1803,11 @@ var createExposesPlugin = function (options, currentManifestJson) {
|
|
|
1582
1803
|
});
|
|
1583
1804
|
});
|
|
1584
1805
|
},
|
|
1806
|
+
/**
|
|
1807
|
+
* 统一拦截 runtime 引用
|
|
1808
|
+
* - 支持 @dd-code/runtime 与 @dd-code/runtime/<name>
|
|
1809
|
+
* - 返回原始 id,交由 load 钩子生成具体代码
|
|
1810
|
+
*/
|
|
1585
1811
|
resolveId: function (id, importer) {
|
|
1586
1812
|
return __awaiter(this, void 0, void 0, function () {
|
|
1587
1813
|
return __generator(this, function (_a) {
|
|
@@ -1592,6 +1818,11 @@ var createExposesPlugin = function (options, currentManifestJson) {
|
|
|
1592
1818
|
});
|
|
1593
1819
|
});
|
|
1594
1820
|
},
|
|
1821
|
+
/**
|
|
1822
|
+
* 生成运行时代码
|
|
1823
|
+
* - 通过解析 id 获取子路径('.' 或 './name')
|
|
1824
|
+
* - 按 exposes 映射找到对应模块与导出列表,拼装 require 代码
|
|
1825
|
+
*/
|
|
1595
1826
|
load: function (id) {
|
|
1596
1827
|
return __awaiter(this, void 0, void 0, function () {
|
|
1597
1828
|
var matched, deepPath, moduleExpose;
|
|
@@ -1606,6 +1837,11 @@ var createExposesPlugin = function (options, currentManifestJson) {
|
|
|
1606
1837
|
});
|
|
1607
1838
|
});
|
|
1608
1839
|
},
|
|
1840
|
+
/**
|
|
1841
|
+
* 为每个 exposes 键发射一个 runtime chunk
|
|
1842
|
+
* - fileName 模板中 {template} 取键名,将非路径字符替换为可用形式(如 './axios' -> '_axios')
|
|
1843
|
+
* - 保证各入口在输出根目录下具有稳定文件名
|
|
1844
|
+
*/
|
|
1609
1845
|
buildStart: function () {
|
|
1610
1846
|
return __awaiter(this, void 0, void 0, function () {
|
|
1611
1847
|
var _i, _a, _b, spec, r, id, fileName, fileNameWithoutExt;
|
|
@@ -1614,14 +1850,16 @@ var createExposesPlugin = function (options, currentManifestJson) {
|
|
|
1614
1850
|
switch (_c.label) {
|
|
1615
1851
|
case 0:
|
|
1616
1852
|
// 显式发射 runtime chunk,确保它被打包到根目录
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1853
|
+
if (!currentManifestJson.value.isRoot) {
|
|
1854
|
+
Object.keys(mainAppExposeCode).forEach(function (key) {
|
|
1855
|
+
var keyDir = key.replace(/\./g, "").replace(/\//g, "_");
|
|
1856
|
+
_this.emitFile({
|
|
1857
|
+
type: "chunk",
|
|
1858
|
+
id: path.join(RUNTIME_NAME, key),
|
|
1859
|
+
fileName: buildName.replace("{template}", keyDir),
|
|
1860
|
+
});
|
|
1623
1861
|
});
|
|
1624
|
-
}
|
|
1862
|
+
}
|
|
1625
1863
|
_i = 0, _a = Object.entries(options.exposes || {});
|
|
1626
1864
|
_c.label = 1;
|
|
1627
1865
|
case 1:
|
|
@@ -1649,6 +1887,11 @@ var createExposesPlugin = function (options, currentManifestJson) {
|
|
|
1649
1887
|
});
|
|
1650
1888
|
});
|
|
1651
1889
|
},
|
|
1890
|
+
/**
|
|
1891
|
+
* 产物阶段:收集 exposes 的打包路径与导出列表
|
|
1892
|
+
* - 通过 chunk.modules[moduleId.id] 反查模块所属 chunk
|
|
1893
|
+
* - 保存到当前 Manifest,以便下游消费
|
|
1894
|
+
*/
|
|
1652
1895
|
generateBundle: function (_, bundles) {
|
|
1653
1896
|
return __awaiter(this, void 0, void 0, function () {
|
|
1654
1897
|
var chunks, resolveIdsMap, _loop_1, this_1, _a, _b, _c, _i, i;
|
|
@@ -1707,6 +1950,19 @@ var createExposesPlugin = function (options, currentManifestJson) {
|
|
|
1707
1950
|
];
|
|
1708
1951
|
};
|
|
1709
1952
|
|
|
1953
|
+
/**
|
|
1954
|
+
* mp-weixin 平台插件聚合器
|
|
1955
|
+
* - 初始化并维护当前构建的 Manifest 管理器(state + IO)
|
|
1956
|
+
* - 根据模式预清理发布目录并重置 outDir(避免脏数据影响产物)
|
|
1957
|
+
* - 组合注册各业务插件:运行时暴露、资源搬运、Manifest 采集与主应用逻辑
|
|
1958
|
+
* - 插件间通过 `currentManifestJson` 共享上下文(环境、文件列表、依赖、exposes 映射)
|
|
1959
|
+
* - 插件注册顺序:
|
|
1960
|
+
* 1) pre: @dd-code:genre-params(设置环境、重置 outDir)
|
|
1961
|
+
* 2) post: exposes(生成 runtime 入口与 exposes 产物映射)
|
|
1962
|
+
* 3) pre: apps-assets(下载/搬运其它应用资源到主输出目录)
|
|
1963
|
+
* 4) default: manifest-plugin(采集 pages.json 与产物清单)
|
|
1964
|
+
* 5) post: main-app(serve/watch/merge 核心逻辑)
|
|
1965
|
+
*/
|
|
1710
1966
|
var createMpWeixinUniPlugin = function (options) {
|
|
1711
1967
|
if (options === void 0) { options = {}; }
|
|
1712
1968
|
var currentManifestJson = createManifestManager();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dd-code/uni-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"description": "Universal tools for code utilities",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"inquirer": "^12.6.3",
|
|
17
|
+
"js-yaml": "^4.1.1",
|
|
17
18
|
"@dd-code/shared": "1.0.9"
|
|
18
19
|
},
|
|
19
20
|
"peerDependencies": {
|