@aiot-toolkit/aiotpack 2.1.0-prender.1 → 2.1.0-prender.3

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.
@@ -6,10 +6,6 @@ import IJavascriptCompileOption from '../../compiler/javascript/interface/IJavas
6
6
  declare class UxAfterCompile {
7
7
  static compileJavascript: FollowWork<IJavascriptCompileOption>;
8
8
  static protobuf: FollowWork<IJavascriptCompileOption>;
9
- /**
10
- * 预渲染:在 VM 沙箱中执行编译后的模板函数,生成 .template.json + .css.json
11
- */
12
- static prerender: FollowWork<IJavascriptCompileOption>;
13
9
  static jsc: FollowWork<IJavascriptCompileOption>;
14
10
  static toRpk: FollowWork<IJavascriptCompileOption>;
15
11
  /**
@@ -19,7 +19,6 @@ var _ZipFileUtil = _interopRequireDefault(require("@aiot-toolkit/shared-utils/li
19
19
  var _ImageIcu = _interopRequireDefault(require("../../compiler/tools/icu/ImageIcu"));
20
20
  var _LiteCard = _interopRequireDefault(require("../../compiler/javascript/vela/utils/LiteCard"));
21
21
  var _UxUtil = _interopRequireDefault(require("@aiot-toolkit/parser/lib/ux/utils/UxUtil"));
22
- var _prerender = require("../../prerender");
23
22
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
24
23
  const BinaryPlugin = require('@aiot-toolkit/parser/lib/ux/translate/vela/protobuf/BinaryPlugin');
25
24
 
@@ -90,70 +89,6 @@ class UxAfterCompile {
90
89
  BinaryPlugin.createBinFiles();
91
90
  }
92
91
  };
93
-
94
- /**
95
- * 预渲染:在 VM 沙箱中执行编译后的模板函数,生成 .template.json + .css.json
96
- */
97
- static prerender = async params => {
98
- const {
99
- compilerOption,
100
- onLog,
101
- compilation
102
- } = params;
103
- if (!compilerOption || compilerOption.enablePrerender === false) {
104
- return;
105
- }
106
-
107
- // In watch mode, clear prerender caches for changed pages
108
- if (compilation && compilation.trigger !== _FileLaneTriggerType.default.START) {
109
- const {
110
- sourceRoot
111
- } = compilerOption;
112
- const srcPath = _path.default.join(compilerOption.projectPath, sourceRoot);
113
- const changedPages = (compilation.changedFiles || []).filter(f => compilation.entries?.includes(f)).map(f => {
114
- const rel = _path.default.relative(srcPath, f).replace(/\\/g, '/');
115
- return rel.replace(/\.[^.]+$/, '');
116
- });
117
- (0, _prerender.watchChange)(changedPages.length > 0 ? changedPages : undefined);
118
- }
119
- const {
120
- projectPath,
121
- outputPath,
122
- sourceRoot
123
- } = compilerOption;
124
- const buildPath = _path.default.join(projectPath, outputPath);
125
- const manifestPath = _path.default.join(projectPath, sourceRoot, 'manifest.json');
126
- if (!_fsExtra.default.existsSync(manifestPath)) {
127
- return;
128
- }
129
- const excludeList = compilerOption.prerenderExclude || [];
130
- const manifest = _fsExtra.default.readJSONSync(manifestPath);
131
- const pages = Object.keys(manifest.router?.pages || {}).filter(pageName => {
132
- if (excludeList.some(pattern => pageName.startsWith(pattern))) {
133
- onLog?.([{
134
- level: _sharedUtils.Loglevel.INFO,
135
- message: [`prerender: skip excluded ${pageName}`]
136
- }]);
137
- return false;
138
- }
139
- return true;
140
- }).map(pageName => {
141
- const pageConf = manifest.router.pages[pageName];
142
- const component = pageConf.component || 'index';
143
- return `${pageName}/${component}`;
144
- });
145
- if (!pages.length) {
146
- return;
147
- }
148
- const deviceTypes = manifest.deviceTypeList?.length ? manifest.deviceTypeList : ['default'];
149
- await (0, _prerender.prerender)({
150
- buildPath,
151
- sourcePath: _path.default.join(projectPath, sourceRoot),
152
- pages,
153
- prerenderSubComp: compilerOption.prerenderSubComp !== false,
154
- deviceTypes
155
- }, onLog);
156
- };
157
92
  static jsc = async params => {
158
93
  const {
159
94
  context,
@@ -11,6 +11,33 @@ var _UxCompileUtil = _interopRequireDefault(require("./vela/utils/UxCompileUtil"
11
11
  var _UxFileUtils = _interopRequireDefault(require("../../utils/ux/UxFileUtils"));
12
12
  var _UxLoaderUtils = _interopRequireDefault(require("../../utils/ux/UxLoaderUtils"));
13
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ function extractAppStyleLiteral(code) {
15
+ const m = code.match(/var\s+\$app_style\$\s*=\s*\[/);
16
+ if (!m) return null;
17
+ let i = m.index + m[0].length - 1;
18
+ let depth = 0;
19
+ let inStr = null;
20
+ for (; i < code.length; i++) {
21
+ const c = code[i];
22
+ if (inStr) {
23
+ if (c === '\\') {
24
+ i++;
25
+ continue;
26
+ }
27
+ if (c === inStr) inStr = null;
28
+ continue;
29
+ }
30
+ if (c === '"' || c === "'") {
31
+ inStr = c;
32
+ continue;
33
+ }
34
+ if (c === '[') depth++;else if (c === ']') {
35
+ depth--;
36
+ if (depth === 0) return code.slice(m.index + m[0].length - 1, i + 1);
37
+ }
38
+ }
39
+ return null;
40
+ }
14
41
  class ViteCompiler {
15
42
  constructor(context, onLog) {
16
43
  this.context = context;
@@ -57,9 +84,9 @@ class ViteCompiler {
57
84
  fileName: () => 'output.js'
58
85
  },
59
86
  rollupOptions: {
60
- external: id => id.startsWith('@app-module/') || id.startsWith('@system.'),
87
+ external: id => id.startsWith('@app-module/') || /^@(system|service|android|hap)\./.test(id),
61
88
  output: {
62
- globals: id => `$app_require$("@app-module/${id.replace(/^@(system|app-module)\./, '')}")`
89
+ globals: id => `$app_require$("@app-module/${id.replace(/^@(system|service|android|hap|app-module)\./, '')}")`
63
90
  }
64
91
  },
65
92
  commonjsOptions: {
@@ -88,10 +115,15 @@ class ViteCompiler {
88
115
  name: 'system-to-app-require',
89
116
  enforce: 'pre',
90
117
  transform(code, id) {
91
- if (!code.includes('@system.')) return null;
118
+ if (!/@(system|service|android|hap)\.|@app-module\//.test(code)) return null;
119
+ const NS = '(system|service|android|hap)';
92
120
  let t = code;
93
- t = t.replace(/import\s+(\w+)\s+from\s+['"]@system\.([^'"]+)['"]\s*;?/g, 'const $1 = $app_require$("@app-module/system.$2");');
94
- t = t.replace(/import\s+\{([^}]+)\}\s+from\s+['"]@system\.([^'"]+)['"]\s*;?/g, 'const {$1} = $app_require$("@app-module/system.$2");');
121
+ t = t.replace(new RegExp(`import\\s+(\\w+)\\s+from\\s+['"]@${NS}\\.([^'"]+)['"]\\s*;?`, 'g'), 'const $1 = $app_require$("@app-module/$2.$3");');
122
+ t = t.replace(new RegExp(`import\\s+\\{([^}]+)\\}\\s+from\\s+['"]@${NS}\\.([^'"]+)['"]\\s*;?`, 'g'), 'const {$1} = $app_require$("@app-module/$2.$3");');
123
+ t = t.replace(/import\s+(\w+)\s+from\s+['"]@app-module\/([^'"]+)['"]\s*;?/g, 'const $1 = $app_require$("@app-module/$2");');
124
+ t = t.replace(/import\s+\{([^}]+)\}\s+from\s+['"]@app-module\/([^'"]+)['"]\s*;?/g, 'const {$1} = $app_require$("@app-module/$2");');
125
+ t = t.replace(/import\s+['"]@app-module\/([^'"]+)['"]\s*;?/g, '$app_require$("@app-module/$1");');
126
+ t = t.replace(new RegExp(`import\\s+['"]@${NS}\\.([^'"]+)['"]\\s*;?`, 'g'), '$app_require$("@app-module/$1.$2");');
95
127
  return t !== code ? {
96
128
  code: t,
97
129
  map: null
@@ -143,11 +175,9 @@ class ViteCompiler {
143
175
  const compiledCode = compFiles[0]?.content || '';
144
176
  // Extract $app_style$ array from compiled code
145
177
  let styleSheet = {};
146
- const styleMatch = compiledCode.match(/var \$app_style\$ = (\[[\s\S]*?\]);?\s*(?:import|export|var |const |$)/);
147
- if (styleMatch) {
148
- if (styleMatch) {
149
- styleSheet = (0, _TemplateCompiler.parseStyleArray)(styleMatch[1]);
150
- }
178
+ const styleLiteral = extractAppStyleLiteral(compiledCode);
179
+ if (styleLiteral) {
180
+ styleSheet = (0, _TemplateCompiler.parseStyleArray)(styleLiteral);
151
181
  }
152
182
  // Write css.json
153
183
  const cssPath = _path.default.join(buildPath, `${isApp ? 'app' : pageName}.css.json`);
@@ -164,53 +194,83 @@ class ViteCompiler {
164
194
  _fsExtra.default.writeJSONSync(tplPath, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, styleSheet, importMap, _path.default.dirname(pageName)), param.mode === 'production' ? undefined : {
165
195
  spaces: 2
166
196
  });
167
- // Generate sub-component template.json files
197
+ // Worklist BFS over nested <import> chain so transitively imported
198
+ // components (entry → compA → compB → compC) also get template.json
199
+ const worklist = [];
200
+ const visited = new Set();
168
201
  for (const [compName, compPath] of Object.entries(importMap)) {
169
202
  const compUxPath = _path.default.resolve(_path.default.dirname(id), `../../${compPath}.ux`);
170
- if (_fsExtra.default.existsSync(compUxPath)) {
171
- const compContent = _fsExtra.default.readFileSync(compUxPath, 'utf-8');
172
- const compDoc = parse5.parseFragment(compContent, {
173
- scriptingEnabled: false
174
- });
175
- const compTpl = compDoc.childNodes.find(n => n.nodeName === 'template');
176
- if (compTpl) {
177
- const compTplPath = _path.default.join(buildPath, `${compPath}.template.json`);
178
- _fsExtra.default.ensureDirSync(_path.default.dirname(compTplPath));
179
- // Get component styles
180
- const compResult = await _UxLoaderUtils.default.compileUxToJavascript({
181
- path: compUxPath,
182
- content: compContent
183
- }, {
184
- projectPath: originalProjectPath,
185
- sourceRoot
186
- }, false, param, compilation);
187
- let compStyleSheet = {};
188
- const compCode = compResult.files[0]?.content || '';
189
- const csm = compCode.match(/var \$app_style\$ = (\[[\s\S]*?\]);?\s*(?:import|export|var |const |$)/);
190
- if (csm) {
191
- compStyleSheet = (0, _TemplateCompiler.parseStyleArray)(csm[1]);
203
+ worklist.push({
204
+ compName,
205
+ compPath,
206
+ compUxPath
207
+ });
208
+ }
209
+ while (worklist.length) {
210
+ const {
211
+ compName,
212
+ compPath,
213
+ compUxPath
214
+ } = worklist.shift();
215
+ if (visited.has(compPath)) continue;
216
+ visited.add(compPath);
217
+ if (!_fsExtra.default.existsSync(compUxPath)) continue;
218
+ const compContent = _fsExtra.default.readFileSync(compUxPath, 'utf-8');
219
+ const compDoc = parse5.parseFragment(compContent, {
220
+ scriptingEnabled: false
221
+ });
222
+ let compTpl = null;
223
+ const compImportMap = {};
224
+ for (const node of compDoc.childNodes) {
225
+ if (node.nodeName === 'template') compTpl = node;else if (node.nodeName === 'import') {
226
+ const n = node.attrs?.find(a => a.name === 'name');
227
+ const s = node.attrs?.find(a => a.name === 'src');
228
+ if (n && s) {
229
+ const nestedAbsPath = _path.default.resolve(_path.default.dirname(compUxPath), s.value).replace(/\.ux$/, '');
230
+ const nestedPath = _path.default.relative(srcPath, nestedAbsPath).replace(/\\/g, '/');
231
+ compImportMap[n.value.toLowerCase()] = nestedPath;
232
+ if (!visited.has(nestedPath)) {
233
+ worklist.push({
234
+ compName: n.value.toLowerCase(),
235
+ compPath: nestedPath,
236
+ compUxPath: _path.default.resolve(_path.default.dirname(compUxPath), s.value)
237
+ });
238
+ }
192
239
  }
193
- const compSid = (0, _TemplateCompiler.getStyleObjectId)(compPath);
194
- _fsExtra.default.writeJSONSync(compTplPath, (0, _TemplateCompiler.uxToTemplateJson)(compTpl, compSid, compStyleSheet, undefined, _path.default.dirname(compPath)), param.mode === 'production' ? undefined : {
195
- spaces: 2
196
- });
197
- // Generate component css.json
198
- const compCssPath = _path.default.join(buildPath, `${compPath}.css.json`);
199
- _fsExtra.default.writeJSONSync(compCssPath, Object.keys(compStyleSheet).length ? {
200
- [String(compSid)]: compStyleSheet
201
- } : {}, param.mode === 'production' ? undefined : {
202
- spaces: 2
203
- });
204
- // Generate component js (script only)
205
- const compJsPath = _path.default.join(buildPath, `${compPath}.js`);
206
- // Extract the component object from the compiled code
207
- const exportMatch = compCode.match(/export\s+default\s+([\s\S]*?);?\s*$/);
208
- const compObj = exportMatch ? exportMatch[1].trim() : '{}';
209
- const compVarName = compName.replace(/-/g, '_') + '_default';
210
- const compJsContent = `let $style$${compSid} = {"@info":{"styleObjectId":${compSid}}};\nconst $app_style$${compSid} = $style$${compSid};\nvar ${compVarName} = ${compObj};\n$app_define$("@app-component/${compName}", [], function($app_require$, $app_exports$, $app_module$) {\n $app_module$.exports = ${compVarName}.default || ${compVarName};\n $app_module$.exports.style = $app_style$${compSid};\n});\n`;
211
- _fsExtra.default.writeFileSync(compJsPath, compJsContent);
212
240
  }
213
241
  }
242
+ if (!compTpl) continue;
243
+ const compTplPath = _path.default.join(buildPath, `${compPath}.template.json`);
244
+ _fsExtra.default.ensureDirSync(_path.default.dirname(compTplPath));
245
+ const compResult = await _UxLoaderUtils.default.compileUxToJavascript({
246
+ path: compUxPath,
247
+ content: compContent
248
+ }, {
249
+ projectPath: originalProjectPath,
250
+ sourceRoot
251
+ }, false, param, compilation);
252
+ let compStyleSheet = {};
253
+ const compCode = compResult.files[0]?.content || '';
254
+ const csm = extractAppStyleLiteral(compCode);
255
+ if (csm) {
256
+ compStyleSheet = (0, _TemplateCompiler.parseStyleArray)(csm);
257
+ }
258
+ const compSid = (0, _TemplateCompiler.getStyleObjectId)(compPath);
259
+ _fsExtra.default.writeJSONSync(compTplPath, (0, _TemplateCompiler.uxToTemplateJson)(compTpl, compSid, compStyleSheet, compImportMap, _path.default.dirname(compPath)), param.mode === 'production' ? undefined : {
260
+ spaces: 2
261
+ });
262
+ const compCssPath = _path.default.join(buildPath, `${compPath}.css.json`);
263
+ _fsExtra.default.writeJSONSync(compCssPath, Object.keys(compStyleSheet).length ? {
264
+ [String(compSid)]: compStyleSheet
265
+ } : {}, param.mode === 'production' ? undefined : {
266
+ spaces: 2
267
+ });
268
+ const compJsPath = _path.default.join(buildPath, `${compPath}.js`);
269
+ const exportMatch = compCode.match(/export\s+default\s+([\s\S]*?);?\s*$/);
270
+ const compObj = exportMatch ? exportMatch[1].trim() : '{}';
271
+ const compVarName = compName.replace(/-/g, '_') + '_default';
272
+ const compJsContent = `let $style$${compSid} = {"@info":{"styleObjectId":${compSid}}};\nconst $app_style$${compSid} = $style$${compSid};\nvar ${compVarName} = ${compObj};\n$app_define$("@app-component/${compName}", [], function($app_require$, $app_exports$, $app_module$) {\n $app_module$.exports = ${compVarName}.default || ${compVarName};\n $app_module$.exports.style = $app_style$${compSid};\n});\n`;
273
+ _fsExtra.default.writeFileSync(compJsPath, compJsContent);
214
274
  }
215
275
  }
216
276
  }
@@ -302,9 +362,9 @@ class ViteCompiler {
302
362
  const compCode = files[0]?.content || '';
303
363
  // Extract style
304
364
  let styleSheet = {};
305
- const csm = compCode.match(/var \$app_style\$ = (\[[\s\S]*?\]);?\s*(?:import|export|var |const |$)/);
365
+ const csm = extractAppStyleLiteral(compCode);
306
366
  if (csm) {
307
- styleSheet = (0, _TemplateCompiler.parseStyleArray)(csm[1]);
367
+ styleSheet = (0, _TemplateCompiler.parseStyleArray)(csm);
308
368
  }
309
369
  // Generate template.json
310
370
  if (templateNode) {
@@ -80,23 +80,6 @@ interface IJavascriptCompileOption extends ICompileParam {
80
80
  * @example log,warn
81
81
  */
82
82
  dropConsole?: boolean | string;
83
- /**
84
- * 启用预渲染
85
- *
86
- * 编译后在 VM 沙箱中执行模板函数,生成 .template.json + .css.json
87
- * @default true
88
- */
89
- enablePrerender?: boolean;
90
- /**
91
- * 是否预渲染子组件(import 引用的组件)
92
- * @default true
93
- */
94
- prerenderSubComp?: boolean;
95
- /**
96
- * 排除不预渲染的页面路径列表
97
- * 支持前缀匹配,如 ['pages/Dynamic'] 会排除 pages/Dynamic/index 等
98
- */
99
- prerenderExclude?: string[];
100
83
  /**
101
84
  * 启动页
102
85
  */
@@ -83,9 +83,6 @@ class UxConfig {
83
83
  }, {
84
84
  worker: _UxAfterCompile.default.compileJavascript,
85
85
  workerDescribe: 'Compile javascript project'
86
- }, {
87
- worker: _UxAfterCompile.default.prerender,
88
- workerDescribe: 'Prerender pages to template.json + css.json'
89
86
  }, {
90
87
  worker: _UxAfterCompile.default.copyResource,
91
88
  workerDescribe: 'Copy resource files'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiot-toolkit/aiotpack",
3
- "version": "2.1.0-prender.1",
3
+ "version": "2.1.0-prender.3",
4
4
  "description": "The process tool for packaging aiot projects.",
5
5
  "keywords": [
6
6
  "aiotpack"
@@ -19,16 +19,16 @@
19
19
  "test": "node ./__tests__/aiotpack.test.js"
20
20
  },
21
21
  "dependencies": {
22
- "@aiot-toolkit/generator": "2.1.0-prender.1",
23
- "@aiot-toolkit/parser": "2.1.0-prender.1",
24
- "@aiot-toolkit/shared-utils": "2.1.0-prender.1",
22
+ "@aiot-toolkit/generator": "2.1.0-prender.3",
23
+ "@aiot-toolkit/parser": "2.1.0-prender.3",
24
+ "@aiot-toolkit/shared-utils": "2.1.0-prender.3",
25
25
  "@hap-toolkit/aaptjs": "^2.0.0",
26
26
  "@rspack/core": "^1.3.9",
27
27
  "acorn": "^8.16.0",
28
28
  "aiot-parse5": "^1.0.2",
29
29
  "astring": "^1.9.0",
30
30
  "babel-loader": "^9.1.3",
31
- "file-lane": "2.1.0-prender.1",
31
+ "file-lane": "2.1.0-prender.3",
32
32
  "file-loader": "^6.2.0",
33
33
  "fs-extra": "^11.2.0",
34
34
  "jsrsasign": "^11.1.0",
@@ -45,5 +45,5 @@
45
45
  "@types/jsrsasign": "^10.5.12",
46
46
  "@types/webpack-sources": "^3.2.3"
47
47
  },
48
- "gitHead": "8bb39a59fbe7a7c22c1167e69d44c78024330cec"
48
+ "gitHead": "a0849da638ea3a9a6abb95a9cbcad400cbb6903a"
49
49
  }
@@ -1,86 +0,0 @@
1
- import { ILog } from '@aiot-toolkit/shared-utils';
2
- /** 预渲染 DOM 节点 */
3
- export interface PrerenderNode {
4
- type: string;
5
- attr?: Record<string, any>;
6
- class?: string;
7
- style?: Record<string, string>;
8
- styleObjectId?: number;
9
- children?: PrerenderNode[];
10
- events?: Record<string, string>;
11
- bind?: number;
12
- $repeat?: string;
13
- repeat?: any[];
14
- repeat_items?: PrerenderNode[];
15
- import?: string;
16
- }
17
- /** 绑定标记:文本/属性绑定 */
18
- export interface BindingMarker {
19
- $value: string;
20
- bind: 1;
21
- _staticValue?: any;
22
- [key: string]: any;
23
- }
24
- /** 循环标记 */
25
- export interface RepeatMarker {
26
- $repeat: string;
27
- repeat: any[];
28
- }
29
- /** 事件标记 */
30
- export interface EventMarker {
31
- [key: `$${string}`]: string;
32
- }
33
- /**
34
- * PrerenderVM - 在 Node.js VM 沙箱中执行编译后的模板函数,收集 DOM 树
35
- */
36
- export default class PrerenderVM {
37
- private components;
38
- private styleMap;
39
- private bindCounter;
40
- private styleSerializer;
41
- private accessedKeys;
42
- /** 创建 data Proxy,拦截访问并返回绑定标记(支持嵌套和数组) */
43
- createDataProxy(data: Record<string, any>, parentPath?: string): Record<string, any>;
44
- /** 获取已访问的 key 列表 */
45
- getAccessedKeys(): string[];
46
- /** Track binding markers accessed during a function call */
47
- private _bindingAccess;
48
- /** Create a binding marker with toString for string concatenation */
49
- private createBindingMarker;
50
- /** 文本绑定标记 */
51
- static createTextBinding(key: string): BindingMarker;
52
- /** 属性绑定标记 */
53
- static createAttrBinding(attr: string, key: string): Record<string, any>;
54
- /** 循环标记 */
55
- static createRepeatMarker(listName: string): RepeatMarker;
56
- /** 事件标记 */
57
- static createEventMarker(event: string, handler: string): EventMarker;
58
- /**
59
- * 执行编译后的 JS,收集组件定义
60
- */
61
- execute(jsCode: string, onLog?: (logs: ILog[]) => void): {
62
- tree: PrerenderNode | null;
63
- styles: Record<number, any>;
64
- };
65
- private unwrapCode;
66
- private createSandbox;
67
- private collectStyles;
68
- private normalizeStyleSheet;
69
- private createMockVM;
70
- private createNode;
71
- private createConditionalNode;
72
- private createForNode;
73
- private createBlockNode;
74
- private executeTemplate;
75
- private parseInlineStyle;
76
- private extractBindingExpression;
77
- /** Replace $item.xxx references in event handler strings with actual values */
78
- private bakeItemRefsInEvents;
79
- /**
80
- * Get all registered sub-component templates (excluding the bootstrapped main component)
81
- */
82
- getSubComponentTemplates(mainName?: string): Map<string, {
83
- tree: PrerenderNode | null;
84
- styles: Record<number, any>;
85
- }>;
86
- }