@lark-apaas/coding-preset-vite-react 1.0.12-alpha.1 → 1.0.12
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/lib/index.d.ts +9 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +153 -114
- package/lib/index.js.map +1 -1
- package/lib/plugins/{basename-injection.d.ts → basename.d.ts} +4 -4
- package/lib/plugins/basename.d.ts.map +1 -0
- package/lib/plugins/{basename-injection.js → basename.js} +7 -15
- package/lib/plugins/basename.js.map +1 -0
- package/lib/plugins/capabilities.d.ts +9 -6
- package/lib/plugins/capabilities.d.ts.map +1 -1
- package/lib/plugins/capabilities.js +27 -29
- package/lib/plugins/capabilities.js.map +1 -1
- package/lib/plugins/dev-proxy.d.ts +41 -0
- package/lib/plugins/dev-proxy.d.ts.map +1 -0
- package/lib/plugins/dev-proxy.js +229 -0
- package/lib/plugins/dev-proxy.js.map +1 -0
- package/lib/plugins/fonts-mirror.d.ts.map +1 -1
- package/lib/plugins/fonts-mirror.js +28 -0
- package/lib/plugins/fonts-mirror.js.map +1 -1
- package/lib/plugins/html-output.d.ts +21 -0
- package/lib/plugins/html-output.d.ts.map +1 -0
- package/lib/plugins/html-output.js +171 -0
- package/lib/plugins/html-output.js.map +1 -0
- package/lib/plugins/server-log.d.ts +45 -0
- package/lib/plugins/server-log.d.ts.map +1 -0
- package/lib/plugins/server-log.js +60 -0
- package/lib/plugins/server-log.js.map +1 -0
- package/lib/plugins/view-context.d.ts +0 -5
- package/lib/plugins/view-context.d.ts.map +1 -1
- package/lib/plugins/view-context.js +0 -3
- package/lib/plugins/view-context.js.map +1 -1
- package/lib/server-log/compat.d.ts +36 -0
- package/lib/server-log/compat.d.ts.map +1 -0
- package/lib/server-log/compat.js +73 -0
- package/lib/server-log/compat.js.map +1 -0
- package/lib/server-log/dev-logs/api-list-handler.d.ts +6 -0
- package/lib/server-log/dev-logs/api-list-handler.d.ts.map +1 -0
- package/lib/server-log/dev-logs/api-list-handler.js +132 -0
- package/lib/server-log/dev-logs/api-list-handler.js.map +1 -0
- package/lib/server-log/dev-logs/controller.d.ts +45 -0
- package/lib/server-log/dev-logs/controller.d.ts.map +1 -0
- package/lib/server-log/dev-logs/controller.js +239 -0
- package/lib/server-log/dev-logs/controller.js.map +1 -0
- package/lib/server-log/dev-logs/health.controller.d.ts +15 -0
- package/lib/server-log/dev-logs/health.controller.d.ts.map +1 -0
- package/lib/server-log/dev-logs/health.controller.js +79 -0
- package/lib/server-log/dev-logs/health.controller.js.map +1 -0
- package/lib/server-log/dev-logs/helper/path-matcher.d.ts +117 -0
- package/lib/server-log/dev-logs/helper/path-matcher.d.ts.map +1 -0
- package/lib/server-log/dev-logs/helper/path-matcher.js +214 -0
- package/lib/server-log/dev-logs/helper/path-matcher.js.map +1 -0
- package/lib/server-log/dev-logs/index.d.ts +12 -0
- package/lib/server-log/dev-logs/index.d.ts.map +1 -0
- package/lib/server-log/dev-logs/index.js +61 -0
- package/lib/server-log/dev-logs/index.js.map +1 -0
- package/lib/server-log/dev-logs/router.d.ts +7 -0
- package/lib/server-log/dev-logs/router.d.ts.map +1 -0
- package/lib/server-log/dev-logs/router.js +40 -0
- package/lib/server-log/dev-logs/router.js.map +1 -0
- package/lib/server-log/dev-logs/services/capability.service.d.ts +33 -0
- package/lib/server-log/dev-logs/services/capability.service.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services/capability.service.js +127 -0
- package/lib/server-log/dev-logs/services/capability.service.js.map +1 -0
- package/lib/server-log/dev-logs/services/file-reader.d.ts +10 -0
- package/lib/server-log/dev-logs/services/file-reader.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services/file-reader.js +67 -0
- package/lib/server-log/dev-logs/services/file-reader.js.map +1 -0
- package/lib/server-log/dev-logs/services/index.d.ts +8 -0
- package/lib/server-log/dev-logs/services/index.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services/index.js +30 -0
- package/lib/server-log/dev-logs/services/index.js.map +1 -0
- package/lib/server-log/dev-logs/services/parsers.d.ts +23 -0
- package/lib/server-log/dev-logs/services/parsers.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services/parsers.js +157 -0
- package/lib/server-log/dev-logs/services/parsers.js.map +1 -0
- package/lib/server-log/dev-logs/services/server-log.service.d.ts +17 -0
- package/lib/server-log/dev-logs/services/server-log.service.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services/server-log.service.js +119 -0
- package/lib/server-log/dev-logs/services/server-log.service.js.map +1 -0
- package/lib/server-log/dev-logs/services/trace.service.d.ts +14 -0
- package/lib/server-log/dev-logs/services/trace.service.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services/trace.service.js +162 -0
- package/lib/server-log/dev-logs/services/trace.service.js.map +1 -0
- package/lib/server-log/dev-logs/services/trigger.service.d.ts +14 -0
- package/lib/server-log/dev-logs/services/trigger.service.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services/trigger.service.js +153 -0
- package/lib/server-log/dev-logs/services/trigger.service.js.map +1 -0
- package/lib/server-log/dev-logs/services.d.ts +7 -0
- package/lib/server-log/dev-logs/services.d.ts.map +1 -0
- package/lib/server-log/dev-logs/services.js +20 -0
- package/lib/server-log/dev-logs/services.js.map +1 -0
- package/lib/server-log/dev-logs/sse/client-manager.d.ts +61 -0
- package/lib/server-log/dev-logs/sse/client-manager.d.ts.map +1 -0
- package/lib/server-log/dev-logs/sse/client-manager.js +140 -0
- package/lib/server-log/dev-logs/sse/client-manager.js.map +1 -0
- package/lib/server-log/dev-logs/sse/index.d.ts +5 -0
- package/lib/server-log/dev-logs/sse/index.d.ts.map +1 -0
- package/lib/server-log/dev-logs/sse/index.js +11 -0
- package/lib/server-log/dev-logs/sse/index.js.map +1 -0
- package/lib/server-log/dev-logs/sse/log-watcher.d.ts +51 -0
- package/lib/server-log/dev-logs/sse/log-watcher.d.ts.map +1 -0
- package/lib/server-log/dev-logs/sse/log-watcher.js +381 -0
- package/lib/server-log/dev-logs/sse/log-watcher.js.map +1 -0
- package/lib/server-log/dev-logs/sse/sse.controller.d.ts +25 -0
- package/lib/server-log/dev-logs/sse/sse.controller.d.ts.map +1 -0
- package/lib/server-log/dev-logs/sse/sse.controller.js +95 -0
- package/lib/server-log/dev-logs/sse/sse.controller.js.map +1 -0
- package/lib/server-log/dev-logs/types.d.ts +104 -0
- package/lib/server-log/dev-logs/types.d.ts.map +1 -0
- package/lib/server-log/dev-logs/types.js +3 -0
- package/lib/server-log/dev-logs/types.js.map +1 -0
- package/lib/server-log/dev-logs/utils.d.ts +68 -0
- package/lib/server-log/dev-logs/utils.d.ts.map +1 -0
- package/lib/server-log/dev-logs/utils.js +151 -0
- package/lib/server-log/dev-logs/utils.js.map +1 -0
- package/lib/server-log/register.d.ts +34 -0
- package/lib/server-log/register.d.ts.map +1 -0
- package/lib/server-log/register.js +196 -0
- package/lib/server-log/register.js.map +1 -0
- package/lib/server-log/types.d.ts +99 -0
- package/lib/server-log/types.d.ts.map +1 -0
- package/lib/server-log/types.js +3 -0
- package/lib/server-log/types.js.map +1 -0
- package/lib/utils/local-dev.d.ts +46 -0
- package/lib/utils/local-dev.d.ts.map +1 -0
- package/lib/utils/local-dev.js +96 -0
- package/lib/utils/local-dev.js.map +1 -0
- package/lib/utils/proxy-error.d.ts +29 -0
- package/lib/utils/proxy-error.d.ts.map +1 -0
- package/lib/utils/proxy-error.js +158 -0
- package/lib/utils/proxy-error.js.map +1 -0
- package/package.json +3 -1
- package/lib/plugins/basename-injection.d.ts.map +0 -1
- package/lib/plugins/basename-injection.js.map +0 -1
|
@@ -46,14 +46,17 @@ const DEFAULT_DIRS = ['shared/capabilities'];
|
|
|
46
46
|
* `@lark-apaas/client-capability` SDK(被 client-toolkit-lite 内联使用)会
|
|
47
47
|
* `import map from 'virtual:capabilities'` 取这个 map。SDK 在 dev 预览 / 沙箱
|
|
48
48
|
* 加载流程中依赖这个模块存在,所以即使 capabilities 目录为空,也必须把模块
|
|
49
|
-
* 注册成解析成功(空 map),否则
|
|
49
|
+
* 注册成解析成功(空 map),否则 build 时直接 fail。
|
|
50
50
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
51
|
+
* 解析挂两处:
|
|
52
|
+
* 1. Vite 主 pipeline `resolveId` / `load` —— dev 运行时 + production build 都走它。
|
|
53
|
+
* 2. depOptimizer 里把 `virtual:capabilities` 标记为 external(`optimizeDeps.exclude`),
|
|
54
|
+
* 让被预打包的 client-toolkit-lite(内联了 client-capability)保留运行时
|
|
55
|
+
* `import 'virtual:capabilities'`,交给主 pipeline 动态解析。详见下方 config() 注释。
|
|
54
56
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
+
* 这样 dev 期新增 / 修改 capability JSON 后,configureServer 的
|
|
58
|
+
* invalidateModule + full-reload 能即时刷新(旧实现把 map 内联进预打包快照,
|
|
59
|
+
* watch 刷不到,需重启 dev server —— 现已修复)。
|
|
57
60
|
*/
|
|
58
61
|
function capabilitiesBundlePlugin(options = {}) {
|
|
59
62
|
let rootDir = process.cwd();
|
|
@@ -87,31 +90,26 @@ function capabilitiesBundlePlugin(options = {}) {
|
|
|
87
90
|
configResolved(config) {
|
|
88
91
|
rootDir = config.root;
|
|
89
92
|
},
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
// depOptimizer 里把 `virtual:capabilities` 标记为 external,让被预打包的依赖
|
|
94
|
+
// (client-capability,内联进 client-toolkit-lite)保留运行时
|
|
95
|
+
// `import 'virtual:capabilities'`,由下面主 pipeline 的 resolveId/load 动态解析。
|
|
96
|
+
//
|
|
97
|
+
// 为什么不在 depOptimizer 里解析 + 内联(旧实现走 rolldownOptions.plugins):
|
|
98
|
+
// 那样 map 会被烤成 optimize 时的快照固化进预打包 chunk。dev 期新增 / 修改
|
|
99
|
+
// capability JSON 后,configureServer 的 invalidateModule + full-reload 作用在
|
|
100
|
+
// 主 pipeline 的虚拟模块上,而预打包消费者读的是 chunk 里那份内联快照 —— 两者
|
|
101
|
+
// 不是同一个模块,watch 永远刷不到(实测:inline 模式 getModuleById(RESOLVED)
|
|
102
|
+
// 返回 null,invalidate 是 no-op;首屏 optimize 时目录还空 → map 一直空,只有
|
|
103
|
+
// 重启 / re-optimize 才更新)。external 后虚拟模块进入运行时模块图,
|
|
104
|
+
// configureServer 的 invalidate + full-reload 才真正命中被读的模块、即时刷新。
|
|
105
|
+
//
|
|
106
|
+
// external 也顺带替代了"必须在 optimizer 里解析否则 build/optimize fail"的诉求:
|
|
107
|
+
// 标记 external 后 optimizer 不再尝试解析它(不会 fail);build 不经 depOptimizer,
|
|
108
|
+
// 由主 pipeline 解析内联,产物不受影响。
|
|
109
|
+
config() {
|
|
96
110
|
return {
|
|
97
111
|
optimizeDeps: {
|
|
98
|
-
|
|
99
|
-
plugins: [
|
|
100
|
-
{
|
|
101
|
-
name: 'miaoda-capabilities-rolldown',
|
|
102
|
-
resolveId(source) {
|
|
103
|
-
if (source === VIRTUAL_ID)
|
|
104
|
-
return RESOLVED;
|
|
105
|
-
return null;
|
|
106
|
-
},
|
|
107
|
-
load(id) {
|
|
108
|
-
if (id !== RESOLVED)
|
|
109
|
-
return null;
|
|
110
|
-
return `export default ${JSON.stringify(loadMap())};`;
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
},
|
|
112
|
+
exclude: [VIRTUAL_ID],
|
|
115
113
|
},
|
|
116
114
|
};
|
|
117
115
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/plugins/capabilities.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/plugins/capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev Server Proxy(vite dev → Nest backend)for nestjs-vite-react fullstack 形态。
|
|
3
|
+
*
|
|
4
|
+
* 命名澄清:这是**构建工具层**的 vite `server.proxy` 配置(HTTP 反代),跟 client-toolkit
|
|
5
|
+
* AppContainer 内置的 `api-proxy` / `childApi`(**运行时**的 postMessage 桥,给妙搭外壳
|
|
6
|
+
* 接口测试面板用)是不同概念,请勿混淆。
|
|
7
|
+
*
|
|
8
|
+
* fullstack 应用 dev 时 Vite(8080)是**用户入口**、Nest(3000)服务后端,二者分进程。
|
|
9
|
+
* 本 plugin 同时承担两件事:
|
|
10
|
+
*
|
|
11
|
+
* A. `config()` 注入 `server.proxy`:把 `/api`、`/openapi`、`/__innerapi__` 反代到 Nest,
|
|
12
|
+
* 且模拟沙箱网关的两件事:
|
|
13
|
+
* 1. 注入 `x-larkgw-suda-webuser` header(身份)—— 本地从 SUDA_WEBUSER env 取
|
|
14
|
+
* 2. 注入 `x-suda-csrf-token` header(csrf double-submit)—— per-request 从 cookie 抠
|
|
15
|
+
* 否则 Nest 端 ViewController 拿不到 appId(→ window.appId="" → auth-sdk URL 拼错),
|
|
16
|
+
* csrf middleware 也会拦下请求。
|
|
17
|
+
*
|
|
18
|
+
* B. `configureServer()` 挂 HTML 反代 middleware:用户访问 `vite-8080/<path>` 拿页面时,
|
|
19
|
+
* vite 默认走自己的 index.html。但 fullstack 形态要 Nest 渲染 HBS(注入 appId / csrf /
|
|
20
|
+
* platform-data 等),所以拦截所有 `accept: text/html` 请求转发到 Nest 3000。
|
|
21
|
+
* 白名单避开 vite dev-only 路径(`/@vite`、`/@fs`、`/__vite`、`/@id`、`/node_modules`、
|
|
22
|
+
* `/dev/`、`.hot-update`)和静态资源(.js / .css / 图片 / 字体),这些应该走 vite 自身。
|
|
23
|
+
*
|
|
24
|
+
* 实现搬自 fullstack-vite-preset/src/preset.ts 的 server.proxy + HTML proxy 段,逻辑一致。
|
|
25
|
+
*/
|
|
26
|
+
import type { Plugin } from 'vite';
|
|
27
|
+
export interface DevProxyPluginOptions {
|
|
28
|
+
/** Nest server 监听端口。默认 3000 */
|
|
29
|
+
serverPort?: number;
|
|
30
|
+
/** client base path,跟 normalizeBasePath 处理后一致(如 `/app/<id>` 或空串) */
|
|
31
|
+
clientBasePath?: string;
|
|
32
|
+
/** 从 clientBasePath 提取的 appId,用于挂老路径兼容 proxy(`/af/p/<appId>/...`) */
|
|
33
|
+
appId?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Vite plugin: 注入 dev server proxy 配置(仅 dev,build 时不挂)。
|
|
37
|
+
* 通过 `config()` hook 返回 `server.proxy` 让 vite mergeConfig 自动合并。
|
|
38
|
+
*/
|
|
39
|
+
export declare function devProxyPlugin(options?: DevProxyPluginOptions): Plugin;
|
|
40
|
+
export default devProxyPlugin;
|
|
41
|
+
//# sourceMappingURL=dev-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-proxy.d.ts","sourceRoot":"","sources":["../../src/plugins/dev-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,MAAM,CAAC;AAUjD,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAgL1E;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dev Server Proxy(vite dev → Nest backend)for nestjs-vite-react fullstack 形态。
|
|
4
|
+
*
|
|
5
|
+
* 命名澄清:这是**构建工具层**的 vite `server.proxy` 配置(HTTP 反代),跟 client-toolkit
|
|
6
|
+
* AppContainer 内置的 `api-proxy` / `childApi`(**运行时**的 postMessage 桥,给妙搭外壳
|
|
7
|
+
* 接口测试面板用)是不同概念,请勿混淆。
|
|
8
|
+
*
|
|
9
|
+
* fullstack 应用 dev 时 Vite(8080)是**用户入口**、Nest(3000)服务后端,二者分进程。
|
|
10
|
+
* 本 plugin 同时承担两件事:
|
|
11
|
+
*
|
|
12
|
+
* A. `config()` 注入 `server.proxy`:把 `/api`、`/openapi`、`/__innerapi__` 反代到 Nest,
|
|
13
|
+
* 且模拟沙箱网关的两件事:
|
|
14
|
+
* 1. 注入 `x-larkgw-suda-webuser` header(身份)—— 本地从 SUDA_WEBUSER env 取
|
|
15
|
+
* 2. 注入 `x-suda-csrf-token` header(csrf double-submit)—— per-request 从 cookie 抠
|
|
16
|
+
* 否则 Nest 端 ViewController 拿不到 appId(→ window.appId="" → auth-sdk URL 拼错),
|
|
17
|
+
* csrf middleware 也会拦下请求。
|
|
18
|
+
*
|
|
19
|
+
* B. `configureServer()` 挂 HTML 反代 middleware:用户访问 `vite-8080/<path>` 拿页面时,
|
|
20
|
+
* vite 默认走自己的 index.html。但 fullstack 形态要 Nest 渲染 HBS(注入 appId / csrf /
|
|
21
|
+
* platform-data 等),所以拦截所有 `accept: text/html` 请求转发到 Nest 3000。
|
|
22
|
+
* 白名单避开 vite dev-only 路径(`/@vite`、`/@fs`、`/__vite`、`/@id`、`/node_modules`、
|
|
23
|
+
* `/dev/`、`.hot-update`)和静态资源(.js / .css / 图片 / 字体),这些应该走 vite 自身。
|
|
24
|
+
*
|
|
25
|
+
* 实现搬自 fullstack-vite-preset/src/preset.ts 的 server.proxy + HTML proxy 段,逻辑一致。
|
|
26
|
+
*/
|
|
27
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
30
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
31
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
32
|
+
}
|
|
33
|
+
Object.defineProperty(o, k2, desc);
|
|
34
|
+
}) : (function(o, m, k, k2) {
|
|
35
|
+
if (k2 === undefined) k2 = k;
|
|
36
|
+
o[k2] = m[k];
|
|
37
|
+
}));
|
|
38
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
39
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
40
|
+
}) : function(o, v) {
|
|
41
|
+
o["default"] = v;
|
|
42
|
+
});
|
|
43
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
44
|
+
var ownKeys = function(o) {
|
|
45
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
46
|
+
var ar = [];
|
|
47
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
48
|
+
return ar;
|
|
49
|
+
};
|
|
50
|
+
return ownKeys(o);
|
|
51
|
+
};
|
|
52
|
+
return function (mod) {
|
|
53
|
+
if (mod && mod.__esModule) return mod;
|
|
54
|
+
var result = {};
|
|
55
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
56
|
+
__setModuleDefault(result, mod);
|
|
57
|
+
return result;
|
|
58
|
+
};
|
|
59
|
+
})();
|
|
60
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
61
|
+
exports.devProxyPlugin = devProxyPlugin;
|
|
62
|
+
const http = __importStar(require("node:http"));
|
|
63
|
+
const local_dev_1 = require("../utils/local-dev");
|
|
64
|
+
const proxy_error_1 = require("../utils/proxy-error");
|
|
65
|
+
/**
|
|
66
|
+
* Vite plugin: 注入 dev server proxy 配置(仅 dev,build 时不挂)。
|
|
67
|
+
* 通过 `config()` hook 返回 `server.proxy` 让 vite mergeConfig 自动合并。
|
|
68
|
+
*/
|
|
69
|
+
function devProxyPlugin(options = {}) {
|
|
70
|
+
const serverPort = options.serverPort ?? 3000;
|
|
71
|
+
const clientBasePath = options.clientBasePath ?? '';
|
|
72
|
+
const appId = options.appId;
|
|
73
|
+
return {
|
|
74
|
+
name: 'nestjs-vite-react-dev-proxy',
|
|
75
|
+
apply: 'serve',
|
|
76
|
+
config() {
|
|
77
|
+
const localDev = (0, local_dev_1.isLocalDev)();
|
|
78
|
+
const sandboxBase = (0, local_dev_1.resolveSandboxOrigin)();
|
|
79
|
+
const { cookie: outboundCookie, csrfToken: outboundCsrfToken } = (0, local_dev_1.composeSandboxOutboundAuth)();
|
|
80
|
+
// 解析 SUDA_WEBUSER(沙箱注入到 .env.local,dotenv@17 转义边界容错)
|
|
81
|
+
let localDevWebUserHeader = '';
|
|
82
|
+
const parsedSudaWebUser = (0, local_dev_1.parseSudaWebUserEnv)(process.env.SUDA_WEBUSER);
|
|
83
|
+
if (parsedSudaWebUser) {
|
|
84
|
+
try {
|
|
85
|
+
localDevWebUserHeader = encodeURIComponent(JSON.stringify(parsedSudaWebUser));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* ignore */
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const proxy = {};
|
|
92
|
+
// 本地反代沙箱的平台 runtime API(条件性)
|
|
93
|
+
if (localDev && sandboxBase) {
|
|
94
|
+
proxy[`${clientBasePath}/__runtime__`] = {
|
|
95
|
+
target: sandboxBase,
|
|
96
|
+
changeOrigin: true,
|
|
97
|
+
headers: {
|
|
98
|
+
...(outboundCookie ? { cookie: outboundCookie } : {}),
|
|
99
|
+
...(outboundCsrfToken ? { 'x-suda-csrf-token': outboundCsrfToken } : {}),
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// API proxy。本地 dev 没有 larkgw 经过这条 incoming 链路,server 端 NestJS 缺:
|
|
104
|
+
// 1. x-larkgw-suda-webuser header(身份) → ViewController 拿不到 appId
|
|
105
|
+
// 2. x-suda-csrf-token header(csrf double-submit) → csrf middleware 403
|
|
106
|
+
// 在 dev server 这层模拟 larkgw 注入这两样
|
|
107
|
+
proxy[`${clientBasePath}/api`] = {
|
|
108
|
+
target: `http://localhost:${serverPort}`,
|
|
109
|
+
changeOrigin: true,
|
|
110
|
+
...(localDev && localDevWebUserHeader
|
|
111
|
+
? { headers: { 'x-larkgw-suda-webuser': localDevWebUserHeader } }
|
|
112
|
+
: {}),
|
|
113
|
+
configure: (proxyServer) => {
|
|
114
|
+
proxyServer.on('error', (err, req, res) => {
|
|
115
|
+
(0, proxy_error_1.handleDevProxyError)(err, req, res, {
|
|
116
|
+
target: `http://localhost:${serverPort}`,
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
if (localDev) {
|
|
120
|
+
proxyServer.on('proxyReq', (proxyReq, req) => {
|
|
121
|
+
if (proxyReq.getHeader('x-suda-csrf-token'))
|
|
122
|
+
return;
|
|
123
|
+
const cookie = req.headers.cookie;
|
|
124
|
+
if (!cookie)
|
|
125
|
+
return;
|
|
126
|
+
const m = /(?:^|;\s*)suda-csrf-token=([^;]+)/.exec(cookie);
|
|
127
|
+
if (m)
|
|
128
|
+
proxyReq.setHeader('x-suda-csrf-token', m[1]);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
// OpenAPI proxy
|
|
134
|
+
proxy[`${clientBasePath}/openapi`] = {
|
|
135
|
+
target: `http://localhost:${serverPort}`,
|
|
136
|
+
changeOrigin: true,
|
|
137
|
+
configure: (proxyServer) => {
|
|
138
|
+
proxyServer.on('error', (err, req, res) => {
|
|
139
|
+
(0, proxy_error_1.handleDevProxyError)(err, req, res, {
|
|
140
|
+
target: `http://localhost:${serverPort}`,
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
// Inner API proxy
|
|
146
|
+
proxy[`${clientBasePath}/__innerapi__`] = {
|
|
147
|
+
target: `http://localhost:${serverPort}`,
|
|
148
|
+
changeOrigin: true,
|
|
149
|
+
configure: (proxyServer) => {
|
|
150
|
+
proxyServer.on('error', (err, req, res) => {
|
|
151
|
+
(0, proxy_error_1.handleDevProxyError)(err, req, res, {
|
|
152
|
+
target: `http://localhost:${serverPort}`,
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
// 旧路径(/af/p/:appId)兼容代理(仅在 appId 已知时挂)
|
|
158
|
+
if (appId) {
|
|
159
|
+
proxy[`/af/p/${appId}/api`] = {
|
|
160
|
+
target: `http://localhost:${serverPort}`,
|
|
161
|
+
changeOrigin: true,
|
|
162
|
+
configure: (proxyServer) => {
|
|
163
|
+
proxyServer.on('error', (err, req, res) => {
|
|
164
|
+
(0, proxy_error_1.handleDevProxyError)(err, req, res, {
|
|
165
|
+
target: `http://localhost:${serverPort}`,
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
proxy[`/af/p/${appId}/__innerapi__`] = {
|
|
171
|
+
target: `http://localhost:${serverPort}`,
|
|
172
|
+
changeOrigin: true,
|
|
173
|
+
configure: (proxyServer) => {
|
|
174
|
+
proxyServer.on('error', (err, req, res) => {
|
|
175
|
+
(0, proxy_error_1.handleDevProxyError)(err, req, res, {
|
|
176
|
+
target: `http://localhost:${serverPort}`,
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
server: { proxy },
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
configureServer(server) {
|
|
187
|
+
// HTML 反代到 Nest:fullstack 入口是 vite (8080),但 HTML 由 Nest hbs 渲染
|
|
188
|
+
server.middlewares.use((req, res, next) => {
|
|
189
|
+
const devServerWhiteList = [
|
|
190
|
+
'/@vite',
|
|
191
|
+
'/@fs',
|
|
192
|
+
'/__vite',
|
|
193
|
+
'/@id',
|
|
194
|
+
'/node_modules',
|
|
195
|
+
'/dev/',
|
|
196
|
+
'.hot-update',
|
|
197
|
+
'/@react-refresh',
|
|
198
|
+
'/@ws-watchdog',
|
|
199
|
+
'/@error-overlay',
|
|
200
|
+
];
|
|
201
|
+
const isHtmlRequest = req.headers.accept?.includes('text/html');
|
|
202
|
+
const pathname = req.url?.split('?')[0] || '';
|
|
203
|
+
const isDevServerPath = devServerWhiteList.some((item) => pathname.includes(item));
|
|
204
|
+
const isStaticAsset = /\.(js|mjs|cjs|css|map|png|jpg|jpeg|gif|svg|ico|webp|woff|woff2|ttf|eot)$/i.test(pathname);
|
|
205
|
+
if (!isHtmlRequest || isDevServerPath || isStaticAsset) {
|
|
206
|
+
return next();
|
|
207
|
+
}
|
|
208
|
+
const proxyReq = http.request({
|
|
209
|
+
hostname: 'localhost',
|
|
210
|
+
port: serverPort,
|
|
211
|
+
path: req.url,
|
|
212
|
+
method: req.method,
|
|
213
|
+
headers: req.headers,
|
|
214
|
+
}, (proxyRes) => {
|
|
215
|
+
res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
|
|
216
|
+
proxyRes.pipe(res);
|
|
217
|
+
});
|
|
218
|
+
proxyReq.on('error', (err) => {
|
|
219
|
+
(0, proxy_error_1.handleDevProxyError)(err, req, res, {
|
|
220
|
+
target: `http://localhost:${serverPort}`,
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
req.pipe(proxyReq);
|
|
224
|
+
});
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
exports.default = devProxyPlugin;
|
|
229
|
+
//# sourceMappingURL=dev-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-proxy.js","sourceRoot":"","sources":["../../src/plugins/dev-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fonts-mirror.d.ts","sourceRoot":"","sources":["../../src/plugins/fonts-mirror.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"fonts-mirror.d.ts","sourceRoot":"","sources":["../../src/plugins/fonts-mirror.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAsBnC,MAAM,WAAW,wBAAwB;IACvC,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gCAAgC;IAChC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB;IAClB,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC/B;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,MAAM,GAAG,KAAK,CA8ExF;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -9,6 +9,12 @@ exports.fontsMirrorPlugin = fontsMirrorPlugin;
|
|
|
9
9
|
* - URL pathname 保持与 Google Fonts 一致(`/css`、`/css2?family=...&wght=...`),
|
|
10
10
|
* 任意模型输出形式都能被代理;只换域名
|
|
11
11
|
* - 关闭:`{ disabled: true }` 或环境变量 `MIAODA_FONTS_MIRROR_OFF=1`
|
|
12
|
+
*
|
|
13
|
+
* 兜底策略(generateBundle):
|
|
14
|
+
* - postcss-import / @tailwindcss/postcss 内联子 CSS 时用 fs.readFile 直接读盘,
|
|
15
|
+
* 不走 Vite plugin 流水线 → transform 钩子漏过
|
|
16
|
+
* - 因此在 build 阶段对最终产出的 CSS asset 再扫一遍,确保替换不漏
|
|
17
|
+
* - transform 已替换过的文件,HAS_GOOGLE_FONTS 检测自动跳过,不重复计数
|
|
12
18
|
*/
|
|
13
19
|
const DEFAULT_MIRROR = 'https://miaoda.feishu.cn/fonts';
|
|
14
20
|
const GOOGLE_FONTS_RE = /https?:\/\/fonts\.(googleapis|gstatic)\.com/g;
|
|
@@ -59,6 +65,28 @@ function fontsMirrorPlugin(options = {}) {
|
|
|
59
65
|
}
|
|
60
66
|
return { code: code.replace(GOOGLE_FONTS_RE, mirror), map: null };
|
|
61
67
|
},
|
|
68
|
+
generateBundle(_options, bundle) {
|
|
69
|
+
for (const file of Object.values(bundle)) {
|
|
70
|
+
if (file.type !== 'asset')
|
|
71
|
+
continue;
|
|
72
|
+
if (!/\.css$/.test(file.fileName))
|
|
73
|
+
continue;
|
|
74
|
+
const src = typeof file.source === 'string'
|
|
75
|
+
? file.source
|
|
76
|
+
: Buffer.from(file.source).toString('utf-8');
|
|
77
|
+
if (!HAS_GOOGLE_FONTS.test(src))
|
|
78
|
+
continue;
|
|
79
|
+
const matches = src.match(GOOGLE_FONTS_RE);
|
|
80
|
+
if (!matches)
|
|
81
|
+
continue;
|
|
82
|
+
file.source = src.replace(GOOGLE_FONTS_RE, mirror);
|
|
83
|
+
stats.files += 1;
|
|
84
|
+
stats.occurrences += matches.length;
|
|
85
|
+
if (warn) {
|
|
86
|
+
console.warn(`[miaoda-fonts-mirror] rewrote ${matches.length} occurrence(s) in ${file.fileName}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
62
90
|
closeBundle() {
|
|
63
91
|
if (stats.files > 0) {
|
|
64
92
|
console.log(`[miaoda-fonts-mirror] ✓ rewrote ${stats.occurrences} occurrence(s) across ${stats.files} file(s) → ${mirror}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fonts-mirror.js","sourceRoot":"","sources":["../../src/plugins/fonts-mirror.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"fonts-mirror.js","sourceRoot":"","sources":["../../src/plugins/fonts-mirror.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Minify HTML while preserving HBS (Handlebars) template expressions.
|
|
4
|
+
*
|
|
5
|
+
* HBS expressions like {{csrfToken}} and {{{appAvatar}}} are temporarily
|
|
6
|
+
* replaced with safe placeholders before minification, then restored after.
|
|
7
|
+
*/
|
|
8
|
+
export declare function minifyHtmlWithHbsProtection(html: string): Promise<string>;
|
|
9
|
+
export interface HtmlOutputPluginOptions {
|
|
10
|
+
/** Whether running in development mode */
|
|
11
|
+
isDev: boolean;
|
|
12
|
+
/** Output directory for built files */
|
|
13
|
+
outDir: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Vite plugin to handle HTML output:
|
|
17
|
+
* 1. In production: fixes HTML output path (removes extra 'client' directory)
|
|
18
|
+
* 2. In development: writes transformed HTML to disk for backend to serve
|
|
19
|
+
*/
|
|
20
|
+
export declare function htmlOutputPlugin(options: HtmlOutputPluginOptions): Plugin;
|
|
21
|
+
//# sourceMappingURL=html-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-output.d.ts","sourceRoot":"","sources":["../../src/plugins/html-output.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAC;AAGlE;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0B/E;AAED,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,KAAK,EAAE,OAAO,CAAC;IACf,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAwIzE"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.minifyHtmlWithHbsProtection = minifyHtmlWithHbsProtection;
|
|
7
|
+
exports.htmlOutputPlugin = htmlOutputPlugin;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const html_minifier_terser_1 = require("html-minifier-terser");
|
|
11
|
+
/**
|
|
12
|
+
* Minify HTML while preserving HBS (Handlebars) template expressions.
|
|
13
|
+
*
|
|
14
|
+
* HBS expressions like {{csrfToken}} and {{{appAvatar}}} are temporarily
|
|
15
|
+
* replaced with safe placeholders before minification, then restored after.
|
|
16
|
+
*/
|
|
17
|
+
async function minifyHtmlWithHbsProtection(html) {
|
|
18
|
+
// Replace HBS expressions with placeholders before minification
|
|
19
|
+
// to prevent html-minifier-terser from corrupting them
|
|
20
|
+
const hbsPlaceholders = [];
|
|
21
|
+
let processed = html.replace(/\{\{\{?.+?\}\}\}?/g, (match) => {
|
|
22
|
+
const index = hbsPlaceholders.length;
|
|
23
|
+
hbsPlaceholders.push(match);
|
|
24
|
+
return `__HBS_${index}__`;
|
|
25
|
+
});
|
|
26
|
+
processed = await (0, html_minifier_terser_1.minify)(processed, {
|
|
27
|
+
collapseWhitespace: true,
|
|
28
|
+
removeComments: true,
|
|
29
|
+
removeRedundantAttributes: true,
|
|
30
|
+
removeEmptyAttributes: true,
|
|
31
|
+
minifyCSS: true,
|
|
32
|
+
// Do NOT minifyJS — inline scripts may reference HBS placeholders
|
|
33
|
+
minifyJS: false,
|
|
34
|
+
});
|
|
35
|
+
// Restore HBS expressions
|
|
36
|
+
processed = processed.replace(/__HBS_(\d+)__/g, (_, index) => {
|
|
37
|
+
return hbsPlaceholders[Number(index)];
|
|
38
|
+
});
|
|
39
|
+
return processed;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Vite plugin to handle HTML output:
|
|
43
|
+
* 1. In production: fixes HTML output path (removes extra 'client' directory)
|
|
44
|
+
* 2. In development: writes transformed HTML to disk for backend to serve
|
|
45
|
+
*/
|
|
46
|
+
function htmlOutputPlugin(options) {
|
|
47
|
+
const { isDev, outDir } = options;
|
|
48
|
+
let config;
|
|
49
|
+
let server = null;
|
|
50
|
+
/**
|
|
51
|
+
* Transform and write HTML to disk for backend to serve
|
|
52
|
+
*/
|
|
53
|
+
async function writeHtmlToDisk() {
|
|
54
|
+
if (!server || !config)
|
|
55
|
+
return;
|
|
56
|
+
try {
|
|
57
|
+
// Find the input HTML file from rollup options
|
|
58
|
+
const rollupInput = config.build.rollupOptions?.input;
|
|
59
|
+
let htmlPath;
|
|
60
|
+
if (typeof rollupInput === 'string') {
|
|
61
|
+
htmlPath = rollupInput;
|
|
62
|
+
}
|
|
63
|
+
else if (Array.isArray(rollupInput)) {
|
|
64
|
+
htmlPath = rollupInput.find((f) => f.endsWith('.html')) || '';
|
|
65
|
+
}
|
|
66
|
+
else if (rollupInput && typeof rollupInput === 'object') {
|
|
67
|
+
htmlPath =
|
|
68
|
+
Object.values(rollupInput).find((f) => f.endsWith('.html')) || '';
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
htmlPath = path_1.default.resolve(config.root, 'index.html');
|
|
72
|
+
}
|
|
73
|
+
if (!htmlPath || !fs_1.default.existsSync(htmlPath)) {
|
|
74
|
+
console.warn(`[html-output] HTML file not found: ${htmlPath}`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Read the source HTML
|
|
78
|
+
let html = fs_1.default.readFileSync(htmlPath, 'utf-8');
|
|
79
|
+
// Apply Vite's HTML transformations (this calls all plugin's transformIndexHtml hooks)
|
|
80
|
+
const url = '/' + path_1.default.relative(config.root, htmlPath);
|
|
81
|
+
html = await server.transformIndexHtml(url, html);
|
|
82
|
+
// Write to output directory
|
|
83
|
+
const outputPath = path_1.default.resolve(outDir, 'index.html');
|
|
84
|
+
// Ensure output directory exists
|
|
85
|
+
const dir = path_1.default.dirname(outputPath);
|
|
86
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
87
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
88
|
+
}
|
|
89
|
+
fs_1.default.writeFileSync(outputPath, html);
|
|
90
|
+
console.log(`[html-output] Written to: ${outputPath}`);
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
console.error(`[html-output] Failed to write HTML:`, e);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
name: 'vite-html-output',
|
|
98
|
+
configResolved(resolvedConfig) {
|
|
99
|
+
config = resolvedConfig;
|
|
100
|
+
},
|
|
101
|
+
configureServer(devServer) {
|
|
102
|
+
if (!isDev)
|
|
103
|
+
return;
|
|
104
|
+
server = devServer;
|
|
105
|
+
// Return a post hook to run after all plugins' configureServer and
|
|
106
|
+
// Vite's internal middlewares are set up
|
|
107
|
+
return () => {
|
|
108
|
+
writeHtmlToDisk();
|
|
109
|
+
// Watch for HTML file changes
|
|
110
|
+
const rollupInput = config.build.rollupOptions?.input;
|
|
111
|
+
let htmlPath;
|
|
112
|
+
if (typeof rollupInput === 'string' && rollupInput.endsWith('.html')) {
|
|
113
|
+
htmlPath = rollupInput;
|
|
114
|
+
}
|
|
115
|
+
else if (rollupInput && typeof rollupInput === 'object') {
|
|
116
|
+
const inputs = Array.isArray(rollupInput)
|
|
117
|
+
? rollupInput
|
|
118
|
+
: Object.values(rollupInput);
|
|
119
|
+
htmlPath = inputs.find((f) => f.endsWith('.html'));
|
|
120
|
+
}
|
|
121
|
+
if (htmlPath) {
|
|
122
|
+
devServer.watcher.add(htmlPath);
|
|
123
|
+
devServer.watcher.on('change', (file) => {
|
|
124
|
+
if (file === htmlPath) {
|
|
125
|
+
console.log(`[html-output] HTML changed, regenerating...`);
|
|
126
|
+
writeHtmlToDisk();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
// In production, fix the HTML output path and minify after build
|
|
133
|
+
async closeBundle() {
|
|
134
|
+
if (!isDev && config) {
|
|
135
|
+
const outDir = config.build.outDir;
|
|
136
|
+
const wrongPath = path_1.default.resolve(outDir, 'client/index.html');
|
|
137
|
+
const correctPath = path_1.default.resolve(outDir, 'index.html');
|
|
138
|
+
// Check if HTML was output to wrong location
|
|
139
|
+
if (fs_1.default.existsSync(wrongPath)) {
|
|
140
|
+
// Move HTML to correct location
|
|
141
|
+
fs_1.default.renameSync(wrongPath, correctPath);
|
|
142
|
+
console.log(`[html-output] Moved: ${wrongPath} -> ${correctPath}`);
|
|
143
|
+
// Remove empty client directory if it exists
|
|
144
|
+
const clientDir = path_1.default.resolve(outDir, 'client');
|
|
145
|
+
try {
|
|
146
|
+
const files = fs_1.default.readdirSync(clientDir);
|
|
147
|
+
if (files.length === 0) {
|
|
148
|
+
fs_1.default.rmdirSync(clientDir);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Directory doesn't exist or not empty, ignore
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Minify HTML (protect HBS templates like {{csrfToken}}, {{{appAvatar}}})
|
|
156
|
+
if (fs_1.default.existsSync(correctPath)) {
|
|
157
|
+
try {
|
|
158
|
+
const html = fs_1.default.readFileSync(correctPath, 'utf-8');
|
|
159
|
+
const minified = await minifyHtmlWithHbsProtection(html);
|
|
160
|
+
fs_1.default.writeFileSync(correctPath, minified);
|
|
161
|
+
console.log(`[html-output] Minified: ${correctPath}`);
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
console.warn(`[html-output] HTML minification failed, skipping:`, e);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=html-output.js.map
|