@aiot-toolkit/aiotpack 2.0.6-beta.9 → 2.1.0-prender.2
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/afterCompile/ux/UxAfterCompile.js +25 -2
- package/lib/compiler/javascript/JavascriptCompiler.js +11 -4
- package/lib/compiler/javascript/TemplateCompiler.d.ts +29 -0
- package/lib/compiler/javascript/TemplateCompiler.js +564 -0
- package/lib/compiler/javascript/ViteCompiler.d.ts +13 -0
- package/lib/compiler/javascript/ViteCompiler.js +449 -0
- package/lib/compiler/javascript/interface/IJavascriptCompileOption.d.ts +9 -0
- package/lib/compiler/javascript/vela/VelaWebpackConfigurator.d.ts +3 -1
- package/lib/compiler/javascript/vela/VelaWebpackConfigurator.js +16 -1
- package/lib/compiler/javascript/vela/interface/IManifest.d.ts +12 -0
- package/lib/compiler/javascript/vela/plugin/WrapPlugin.d.ts +10 -1
- package/lib/compiler/javascript/vela/plugin/WrapPlugin.js +241 -57
- package/lib/compiler/javascript/vela/utils/UxCompileUtil.d.ts +3 -2
- package/lib/compiler/javascript/vela/utils/UxCompileUtil.js +12 -4
- package/lib/compiler/javascript/vela/utils/VruUtil.d.ts +50 -0
- package/lib/compiler/javascript/vela/utils/VruUtil.js +128 -0
- package/lib/compiler/javascript/vela/utils/ZipUtil.d.ts +9 -0
- package/lib/compiler/javascript/vela/utils/ZipUtil.js +112 -6
- package/lib/compiler/javascript/vela/utils/webpackLoader/WebpackJsLoader.js +1 -1
- package/lib/config/UxConfig.d.ts +12 -5
- package/lib/config/UxConfig.js +4 -6
- package/lib/loader/ux/JsLoader.d.ts +7 -0
- package/lib/loader/ux/JsLoader.js +38 -8
- package/lib/loader/ux/vela/HmlLoader.d.ts +6 -6
- package/lib/loader/ux/vela/HmlLoader.js +30 -13
- package/lib/utils/BeforeCompileUtils.d.ts +1 -1
- package/lib/utils/BeforeCompileUtils.js +52 -9
- package/lib/utils/ux/ManifestSchema.js +0 -1
- package/lib/utils/ux/UxFileUtils.js +1 -1
- package/lib/utils/ux/UxLoaderUtils.js +8 -3
- package/package.json +9 -6
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import IJavascriptCompileOption from './interface/IJavascriptCompileOption';
|
|
2
|
+
import ICompileParam from '../interface/ICompileParam';
|
|
3
|
+
import ICompiler from '../interface/ICompiler';
|
|
4
|
+
import { ILog } from '@aiot-toolkit/shared-utils';
|
|
5
|
+
import { IFileLaneContext } from 'file-lane';
|
|
6
|
+
declare class ViteCompiler implements ICompiler {
|
|
7
|
+
private readonly context;
|
|
8
|
+
private readonly onLog?;
|
|
9
|
+
constructor(context: IFileLaneContext, onLog?: ((log: ILog[]) => void) | undefined);
|
|
10
|
+
compile(param: IJavascriptCompileOption): Promise<void>;
|
|
11
|
+
clean(param: ICompileParam & IJavascriptCompileOption): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export default ViteCompiler;
|
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _TemplateCompiler = require("./TemplateCompiler");
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
|
10
|
+
var _UxCompileUtil = _interopRequireDefault(require("./vela/utils/UxCompileUtil"));
|
|
11
|
+
var _UxFileUtils = _interopRequireDefault(require("../../utils/ux/UxFileUtils"));
|
|
12
|
+
var _UxLoaderUtils = _interopRequireDefault(require("../../utils/ux/UxLoaderUtils"));
|
|
13
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
class ViteCompiler {
|
|
15
|
+
constructor(context, onLog) {
|
|
16
|
+
this.context = context;
|
|
17
|
+
this.onLog = onLog;
|
|
18
|
+
}
|
|
19
|
+
async compile(param) {
|
|
20
|
+
await this.clean(param);
|
|
21
|
+
const {
|
|
22
|
+
projectPath,
|
|
23
|
+
sourceRoot,
|
|
24
|
+
outputPath
|
|
25
|
+
} = param;
|
|
26
|
+
const originalProjectPath = projectPath.replace(/\.temp_/, '');
|
|
27
|
+
const buildPath = _path.default.resolve(projectPath, outputPath);
|
|
28
|
+
const srcPath = _path.default.resolve(originalProjectPath, sourceRoot);
|
|
29
|
+
const manifestPath = _UxFileUtils.default.getManifestFilePath(originalProjectPath, sourceRoot);
|
|
30
|
+
const manifest = _fsExtra.default.readJSONSync(manifestPath);
|
|
31
|
+
const entries = _UxCompileUtil.default.resolveEntries(manifest, srcPath, originalProjectPath);
|
|
32
|
+
for (const [entryName, entryValue] of Object.entries(entries)) {
|
|
33
|
+
const entryPath = entryValue.split('?')[0];
|
|
34
|
+
const resolvedEntry = _path.default.resolve(originalProjectPath, entryPath);
|
|
35
|
+
if (!_fsExtra.default.existsSync(resolvedEntry)) continue;
|
|
36
|
+
const outputFile = _path.default.join(buildPath, `${entryName}.js`);
|
|
37
|
+
_fsExtra.default.ensureDirSync(_path.default.dirname(outputFile));
|
|
38
|
+
const allEntryPaths = Object.values(entries).map(v => _path.default.resolve(originalProjectPath, v.split('?')[0]));
|
|
39
|
+
const compilation = {
|
|
40
|
+
entries: allEntryPaths
|
|
41
|
+
};
|
|
42
|
+
try {
|
|
43
|
+
const {
|
|
44
|
+
build
|
|
45
|
+
} = await import('vite');
|
|
46
|
+
const result = await build({
|
|
47
|
+
root: originalProjectPath,
|
|
48
|
+
logLevel: 'silent',
|
|
49
|
+
resolve: {
|
|
50
|
+
extensions: ['.js', '.ts', '.ux', '.json']
|
|
51
|
+
},
|
|
52
|
+
build: {
|
|
53
|
+
write: false,
|
|
54
|
+
lib: {
|
|
55
|
+
entry: resolvedEntry,
|
|
56
|
+
formats: ['es'],
|
|
57
|
+
fileName: () => 'output.js'
|
|
58
|
+
},
|
|
59
|
+
rollupOptions: {
|
|
60
|
+
external: id => id.startsWith('@app-module/') || /^@(system|service|android|hap)\./.test(id),
|
|
61
|
+
output: {
|
|
62
|
+
globals: id => `$app_require$("@app-module/${id.replace(/^@(system|service|android|hap|app-module)\./, '')}")`
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
commonjsOptions: {
|
|
66
|
+
transformMixedEsModules: true
|
|
67
|
+
},
|
|
68
|
+
minify: param.mode === 'production' ? 'terser' : false,
|
|
69
|
+
terserOptions: {
|
|
70
|
+
format: {
|
|
71
|
+
comments: false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
plugins: [{
|
|
76
|
+
name: "cjs-shim",
|
|
77
|
+
enforce: "pre",
|
|
78
|
+
load(id) {
|
|
79
|
+
if (id.includes('node_modules') && !id.endsWith('.ux')) {
|
|
80
|
+
const content = _fsExtra.default.readFileSync(id, 'utf-8');
|
|
81
|
+
if (content.includes('module.exports') || content.includes('exports.')) {
|
|
82
|
+
return `var module = {exports:{}}; var exports = module.exports;\n${content}\nexport default module.exports;`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}, {
|
|
88
|
+
name: 'system-to-app-require',
|
|
89
|
+
enforce: 'pre',
|
|
90
|
+
transform(code, id) {
|
|
91
|
+
if (!/@(system|service|android|hap)\.|@app-module\//.test(code)) return null;
|
|
92
|
+
const NS = '(system|service|android|hap)';
|
|
93
|
+
let t = code;
|
|
94
|
+
t = t.replace(new RegExp(`import\\s+(\\w+)\\s+from\\s+['"]@${NS}\\.([^'"]+)['"]\\s*;?`, 'g'), 'const $1 = $app_require$("@app-module/$2.$3");');
|
|
95
|
+
t = t.replace(new RegExp(`import\\s+\\{([^}]+)\\}\\s+from\\s+['"]@${NS}\\.([^'"]+)['"]\\s*;?`, 'g'), 'const {$1} = $app_require$("@app-module/$2.$3");');
|
|
96
|
+
t = t.replace(/import\s+(\w+)\s+from\s+['"]@app-module\/([^'"]+)['"]\s*;?/g, 'const $1 = $app_require$("@app-module/$2");');
|
|
97
|
+
t = t.replace(/import\s+\{([^}]+)\}\s+from\s+['"]@app-module\/([^'"]+)['"]\s*;?/g, 'const {$1} = $app_require$("@app-module/$2");');
|
|
98
|
+
t = t.replace(/import\s+['"]@app-module\/([^'"]+)['"]\s*;?/g, '$app_require$("@app-module/$1");');
|
|
99
|
+
t = t.replace(new RegExp(`import\\s+['"]@${NS}\\.([^'"]+)['"]\\s*;?`, 'g'), '$app_require$("@app-module/$1.$2");');
|
|
100
|
+
return t !== code ? {
|
|
101
|
+
code: t,
|
|
102
|
+
map: null
|
|
103
|
+
} : null;
|
|
104
|
+
}
|
|
105
|
+
}, {
|
|
106
|
+
name: 'ux-loader',
|
|
107
|
+
resolveId(source, importer) {
|
|
108
|
+
if (source.endsWith('.ux')) {
|
|
109
|
+
return importer ? _path.default.resolve(_path.default.dirname(importer), source) : source;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
async load(id) {
|
|
113
|
+
if (!id.endsWith('.ux')) return null;
|
|
114
|
+
const content = _fsExtra.default.readFileSync(id, 'utf-8');
|
|
115
|
+
const isApp = id.endsWith('/app.ux') && _path.default.basename(_path.default.dirname(id)) === 'src';
|
|
116
|
+
// Generate template.json and css.json
|
|
117
|
+
if (id === resolvedEntry) {
|
|
118
|
+
const parse5 = require("aiot-parse5");
|
|
119
|
+
const doc = parse5.parseFragment(content, {
|
|
120
|
+
scriptingEnabled: false
|
|
121
|
+
});
|
|
122
|
+
let templateNode = null;
|
|
123
|
+
const importMap = {}; // name -> path
|
|
124
|
+
for (const node of doc.childNodes) {
|
|
125
|
+
if (node.nodeName === 'template') templateNode = node;else if (node.nodeName === 'import') {
|
|
126
|
+
const nameAttr = node.attrs?.find(a => a.name === 'name');
|
|
127
|
+
const srcAttr = node.attrs?.find(a => a.name === 'src');
|
|
128
|
+
if (nameAttr && srcAttr) {
|
|
129
|
+
const compAbsPath = _path.default.resolve(_path.default.dirname(resolvedEntry), srcAttr.value).replace(/\.ux$/, '');
|
|
130
|
+
const compPath = _path.default.relative(srcPath, compAbsPath).replace(/\\/g, '/');
|
|
131
|
+
importMap[nameAttr.value.toLowerCase()] = compPath;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const pageName = _path.default.relative(srcPath, id).replace(/\.ux$/, '');
|
|
136
|
+
// Compute styleObjectId
|
|
137
|
+
const sid = (0, _TemplateCompiler.getStyleObjectId)(entryName);
|
|
138
|
+
// Get style data from UxLoaderUtils compilation (handles LESS/CSS)
|
|
139
|
+
const {
|
|
140
|
+
files: compFiles
|
|
141
|
+
} = await _UxLoaderUtils.default.compileUxToJavascript({
|
|
142
|
+
path: id,
|
|
143
|
+
content
|
|
144
|
+
}, {
|
|
145
|
+
projectPath: originalProjectPath,
|
|
146
|
+
sourceRoot
|
|
147
|
+
}, isApp, param, compilation);
|
|
148
|
+
const compiledCode = compFiles[0]?.content || '';
|
|
149
|
+
// Extract $app_style$ array from compiled code
|
|
150
|
+
let styleSheet = {};
|
|
151
|
+
const styleMatch = compiledCode.match(/var \$app_style\$ = (\[[\s\S]*?\]);?\s*(?:import|export|var |const |$)/);
|
|
152
|
+
if (styleMatch) {
|
|
153
|
+
if (styleMatch) {
|
|
154
|
+
styleSheet = (0, _TemplateCompiler.parseStyleArray)(styleMatch[1]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Write css.json
|
|
158
|
+
const cssPath = _path.default.join(buildPath, `${isApp ? 'app' : pageName}.css.json`);
|
|
159
|
+
_fsExtra.default.ensureDirSync(_path.default.dirname(cssPath));
|
|
160
|
+
_fsExtra.default.writeJSONSync(cssPath, Object.keys(styleSheet).length ? {
|
|
161
|
+
[String(sid)]: styleSheet
|
|
162
|
+
} : {}, param.mode === 'production' ? undefined : {
|
|
163
|
+
spaces: 2
|
|
164
|
+
});
|
|
165
|
+
// Write template.json (with style inlining)
|
|
166
|
+
if (templateNode && !isApp) {
|
|
167
|
+
const tplPath = _path.default.join(buildPath, `${pageName}.template.json`);
|
|
168
|
+
_fsExtra.default.ensureDirSync(_path.default.dirname(tplPath));
|
|
169
|
+
_fsExtra.default.writeJSONSync(tplPath, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, styleSheet, importMap, _path.default.dirname(pageName)), param.mode === 'production' ? undefined : {
|
|
170
|
+
spaces: 2
|
|
171
|
+
});
|
|
172
|
+
// Worklist BFS over nested <import> chain so transitively imported
|
|
173
|
+
// components (entry → compA → compB → compC) also get template.json
|
|
174
|
+
const worklist = [];
|
|
175
|
+
const visited = new Set();
|
|
176
|
+
for (const [compName, compPath] of Object.entries(importMap)) {
|
|
177
|
+
const compUxPath = _path.default.resolve(_path.default.dirname(id), `../../${compPath}.ux`);
|
|
178
|
+
worklist.push({
|
|
179
|
+
compName,
|
|
180
|
+
compPath,
|
|
181
|
+
compUxPath
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
while (worklist.length) {
|
|
185
|
+
const {
|
|
186
|
+
compName,
|
|
187
|
+
compPath,
|
|
188
|
+
compUxPath
|
|
189
|
+
} = worklist.shift();
|
|
190
|
+
if (visited.has(compPath)) continue;
|
|
191
|
+
visited.add(compPath);
|
|
192
|
+
if (!_fsExtra.default.existsSync(compUxPath)) continue;
|
|
193
|
+
const compContent = _fsExtra.default.readFileSync(compUxPath, 'utf-8');
|
|
194
|
+
const compDoc = parse5.parseFragment(compContent, {
|
|
195
|
+
scriptingEnabled: false
|
|
196
|
+
});
|
|
197
|
+
let compTpl = null;
|
|
198
|
+
const compImportMap = {};
|
|
199
|
+
for (const node of compDoc.childNodes) {
|
|
200
|
+
if (node.nodeName === 'template') compTpl = node;else if (node.nodeName === 'import') {
|
|
201
|
+
const n = node.attrs?.find(a => a.name === 'name');
|
|
202
|
+
const s = node.attrs?.find(a => a.name === 'src');
|
|
203
|
+
if (n && s) {
|
|
204
|
+
const nestedAbsPath = _path.default.resolve(_path.default.dirname(compUxPath), s.value).replace(/\.ux$/, '');
|
|
205
|
+
const nestedPath = _path.default.relative(srcPath, nestedAbsPath).replace(/\\/g, '/');
|
|
206
|
+
compImportMap[n.value.toLowerCase()] = nestedPath;
|
|
207
|
+
if (!visited.has(nestedPath)) {
|
|
208
|
+
worklist.push({
|
|
209
|
+
compName: n.value.toLowerCase(),
|
|
210
|
+
compPath: nestedPath,
|
|
211
|
+
compUxPath: _path.default.resolve(_path.default.dirname(compUxPath), s.value)
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (!compTpl) continue;
|
|
218
|
+
const compTplPath = _path.default.join(buildPath, `${compPath}.template.json`);
|
|
219
|
+
_fsExtra.default.ensureDirSync(_path.default.dirname(compTplPath));
|
|
220
|
+
const compResult = await _UxLoaderUtils.default.compileUxToJavascript({
|
|
221
|
+
path: compUxPath,
|
|
222
|
+
content: compContent
|
|
223
|
+
}, {
|
|
224
|
+
projectPath: originalProjectPath,
|
|
225
|
+
sourceRoot
|
|
226
|
+
}, false, param, compilation);
|
|
227
|
+
let compStyleSheet = {};
|
|
228
|
+
const compCode = compResult.files[0]?.content || '';
|
|
229
|
+
const csm = compCode.match(/var \$app_style\$ = (\[[\s\S]*?\]);?\s*(?:import|export|var |const |$)/);
|
|
230
|
+
if (csm) {
|
|
231
|
+
compStyleSheet = (0, _TemplateCompiler.parseStyleArray)(csm[1]);
|
|
232
|
+
}
|
|
233
|
+
const compSid = (0, _TemplateCompiler.getStyleObjectId)(compPath);
|
|
234
|
+
_fsExtra.default.writeJSONSync(compTplPath, (0, _TemplateCompiler.uxToTemplateJson)(compTpl, compSid, compStyleSheet, compImportMap, _path.default.dirname(compPath)), param.mode === 'production' ? undefined : {
|
|
235
|
+
spaces: 2
|
|
236
|
+
});
|
|
237
|
+
const compCssPath = _path.default.join(buildPath, `${compPath}.css.json`);
|
|
238
|
+
_fsExtra.default.writeJSONSync(compCssPath, Object.keys(compStyleSheet).length ? {
|
|
239
|
+
[String(compSid)]: compStyleSheet
|
|
240
|
+
} : {}, param.mode === 'production' ? undefined : {
|
|
241
|
+
spaces: 2
|
|
242
|
+
});
|
|
243
|
+
const compJsPath = _path.default.join(buildPath, `${compPath}.js`);
|
|
244
|
+
const exportMatch = compCode.match(/export\s+default\s+([\s\S]*?);?\s*$/);
|
|
245
|
+
const compObj = exportMatch ? exportMatch[1].trim() : '{}';
|
|
246
|
+
const compVarName = compName.replace(/-/g, '_') + '_default';
|
|
247
|
+
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`;
|
|
248
|
+
_fsExtra.default.writeFileSync(compJsPath, compJsContent);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
const {
|
|
253
|
+
files
|
|
254
|
+
} = await _UxLoaderUtils.default.compileUxToJavascript({
|
|
255
|
+
path: id,
|
|
256
|
+
content
|
|
257
|
+
}, {
|
|
258
|
+
projectPath: originalProjectPath,
|
|
259
|
+
sourceRoot
|
|
260
|
+
}, isApp, param, compilation);
|
|
261
|
+
return files[0]?.content || '';
|
|
262
|
+
}
|
|
263
|
+
}]
|
|
264
|
+
});
|
|
265
|
+
// Extract the output code
|
|
266
|
+
if (result && !Array.isArray(result)) {
|
|
267
|
+
const output = result.output;
|
|
268
|
+
if (output?.[0]?.code) {
|
|
269
|
+
const code = wrapOutput(output[0].code, entryName, entryName === 'app');
|
|
270
|
+
_fsExtra.default.writeFileSync(outputFile, code);
|
|
271
|
+
}
|
|
272
|
+
} else if (Array.isArray(result) && result[0]) {
|
|
273
|
+
const output = result[0].output;
|
|
274
|
+
if (output?.[0]?.code) {
|
|
275
|
+
const code = wrapOutput(output[0].code, entryName, entryName === 'app');
|
|
276
|
+
_fsExtra.default.writeFileSync(outputFile, code);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
} catch (err) {
|
|
280
|
+
console.warn(`vite: failed to build ${entryName}:`, err.message);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Second pass: compile ALL .ux files that weren't entry pages
|
|
284
|
+
// Each .ux file gets its own template.json + css.json + js
|
|
285
|
+
const allUxFiles = [];
|
|
286
|
+
const findUx = dir => {
|
|
287
|
+
for (const f of _fsExtra.default.readdirSync(dir, {
|
|
288
|
+
withFileTypes: true
|
|
289
|
+
})) {
|
|
290
|
+
const p = _path.default.join(dir, f.name);
|
|
291
|
+
if (f.isDirectory() && f.name !== 'node_modules') findUx(p);else if (f.name.endsWith('.ux')) allUxFiles.push(p);
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
findUx(srcPath);
|
|
295
|
+
const compiledEntries = new Set(Object.values(entries).map(v => _path.default.resolve(originalProjectPath, v.split('?')[0])));
|
|
296
|
+
for (const uxFile of allUxFiles) {
|
|
297
|
+
if (compiledEntries.has(uxFile)) continue; // already compiled as entry
|
|
298
|
+
if (uxFile.endsWith('/app.ux')) continue; // app.ux handled separately
|
|
299
|
+
const relPath = _path.default.relative(srcPath, uxFile).replace(/\.ux$/, '');
|
|
300
|
+
const outputJs = _path.default.join(buildPath, `${relPath}.js`);
|
|
301
|
+
const outputTpl = _path.default.join(buildPath, `${relPath}.template.json`);
|
|
302
|
+
const outputCss = _path.default.join(buildPath, `${relPath}.css.json`);
|
|
303
|
+
if (_fsExtra.default.existsSync(outputTpl)) continue; // already generated by parent page
|
|
304
|
+
const content = _fsExtra.default.readFileSync(uxFile, 'utf-8');
|
|
305
|
+
const parse5 = require("aiot-parse5");
|
|
306
|
+
const doc = parse5.parseFragment(content, {
|
|
307
|
+
scriptingEnabled: false
|
|
308
|
+
});
|
|
309
|
+
let templateNode = null;
|
|
310
|
+
const importMap = {};
|
|
311
|
+
for (const node of doc.childNodes) {
|
|
312
|
+
if (node.nodeName === 'template') templateNode = node;else if (node.nodeName === 'import') {
|
|
313
|
+
const nameAttr = node.attrs?.find(a => a.name === 'name');
|
|
314
|
+
const srcAttr = node.attrs?.find(a => a.name === 'src');
|
|
315
|
+
if (nameAttr && srcAttr) {
|
|
316
|
+
const compPath = _path.default.resolve(_path.default.dirname(uxFile), srcAttr.value).replace(/\.ux$/, '');
|
|
317
|
+
importMap[nameAttr.value.toLowerCase()] = _path.default.relative(srcPath, compPath).replace(/\\/g, '/');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Compute styleObjectId
|
|
322
|
+
const sid = (0, _TemplateCompiler.getStyleObjectId)(relPath);
|
|
323
|
+
// Compile with UxLoaderUtils to get style data and script
|
|
324
|
+
const compilation = {
|
|
325
|
+
entries: [uxFile]
|
|
326
|
+
};
|
|
327
|
+
try {
|
|
328
|
+
const {
|
|
329
|
+
files
|
|
330
|
+
} = await _UxLoaderUtils.default.compileUxToJavascript({
|
|
331
|
+
path: uxFile,
|
|
332
|
+
content
|
|
333
|
+
}, {
|
|
334
|
+
projectPath: originalProjectPath,
|
|
335
|
+
sourceRoot
|
|
336
|
+
}, false, param, compilation);
|
|
337
|
+
const compCode = files[0]?.content || '';
|
|
338
|
+
// Extract style
|
|
339
|
+
let styleSheet = {};
|
|
340
|
+
const csm = compCode.match(/var \$app_style\$ = (\[[\s\S]*?\]);?\s*(?:import|export|var |const |$)/);
|
|
341
|
+
if (csm) {
|
|
342
|
+
styleSheet = (0, _TemplateCompiler.parseStyleArray)(csm[1]);
|
|
343
|
+
}
|
|
344
|
+
// Generate template.json
|
|
345
|
+
if (templateNode) {
|
|
346
|
+
_fsExtra.default.ensureDirSync(_path.default.dirname(outputTpl));
|
|
347
|
+
_fsExtra.default.writeJSONSync(outputTpl, (0, _TemplateCompiler.uxToTemplateJson)(templateNode, sid, styleSheet, Object.keys(importMap).length ? importMap : undefined, _path.default.dirname(relPath)), param.mode === 'production' ? undefined : {
|
|
348
|
+
spaces: 2
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
// Generate css.json
|
|
352
|
+
_fsExtra.default.ensureDirSync(_path.default.dirname(outputCss));
|
|
353
|
+
_fsExtra.default.writeJSONSync(outputCss, Object.keys(styleSheet).length ? {
|
|
354
|
+
[String(sid)]: styleSheet
|
|
355
|
+
} : {}, param.mode === 'production' ? undefined : {
|
|
356
|
+
spaces: 2
|
|
357
|
+
});
|
|
358
|
+
// Generate js
|
|
359
|
+
const exportMatch = compCode.match(/export\s+default\s+([\s\S]*?);?\s*$/);
|
|
360
|
+
const compObj = exportMatch ? exportMatch[1].trim() : '{}';
|
|
361
|
+
const compName = _path.default.basename(relPath).toLowerCase();
|
|
362
|
+
const varName = compName.replace(/-/g, '_') + '_default';
|
|
363
|
+
_fsExtra.default.ensureDirSync(_path.default.dirname(outputJs));
|
|
364
|
+
_fsExtra.default.writeFileSync(outputJs, `let $style$${sid} = {"@info":{"styleObjectId":${sid}}};\nconst $app_style$${sid} = $style$${sid};\nvar ${varName} = ${compObj};\n$app_define$("@app-component/${compName}", [], function($app_require$, $app_exports$, $app_module$) {\n $app_module$.exports = ${varName}.default || ${varName};\n $app_module$.exports.style = $app_style$${sid};\n});\n`);
|
|
365
|
+
} catch {}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async clean(param) {
|
|
369
|
+
const {
|
|
370
|
+
outputPath,
|
|
371
|
+
releasePath,
|
|
372
|
+
projectPath
|
|
373
|
+
} = param;
|
|
374
|
+
_UxCompileUtil.default.clean([outputPath, releasePath].map(item => _path.default.resolve(projectPath, item)));
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function wrapOutput(code, entryName, isApp) {
|
|
378
|
+
const componentName = _path.default.parse(entryName).name;
|
|
379
|
+
const defineId = isApp ? '@app-component/app' : `@app-component/${componentName}`;
|
|
380
|
+
const bootstrapId = isApp ? '@app-application/app' : `@app-component/${componentName}`;
|
|
381
|
+
// Remove IIFE wrapper: var _page_ = (function(...) { ... return xxx; })(...);
|
|
382
|
+
// Only remove the FIRST line and the LAST return+closing
|
|
383
|
+
if (code.startsWith('var _page_')) {
|
|
384
|
+
// Remove first line (the IIFE opening)
|
|
385
|
+
const firstNewline = code.indexOf('\n');
|
|
386
|
+
code = code.slice(firstNewline + 1);
|
|
387
|
+
// Remove the last return statement and closing })();
|
|
388
|
+
const lastReturn = code.lastIndexOf('\treturn ');
|
|
389
|
+
if (lastReturn !== -1) {
|
|
390
|
+
const afterReturn = code.indexOf('\n', lastReturn);
|
|
391
|
+
code = code.slice(0, lastReturn) + code.slice(afterReturn + 1);
|
|
392
|
+
}
|
|
393
|
+
// Remove the closing })(); or })(...)
|
|
394
|
+
const lastClose = code.lastIndexOf('})();');
|
|
395
|
+
if (lastClose !== -1) {
|
|
396
|
+
code = code.slice(0, lastClose);
|
|
397
|
+
} else {
|
|
398
|
+
const lastClose2 = code.lastIndexOf('})(');
|
|
399
|
+
if (lastClose2 !== -1) {
|
|
400
|
+
code = code.slice(0, lastClose2);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Remove rolldown region comments
|
|
405
|
+
code = code.replace(/\/\/#region[^\n]*\n/g, '');
|
|
406
|
+
code = code.replace(/\/\/#endregion[^\n]*/g, '');
|
|
407
|
+
// Remove rolldown runtime helpers (not needed in final output)
|
|
408
|
+
code = code.replace(/var __defProp = Object\.defineProperty;\n?/g, '');
|
|
409
|
+
code = code.replace(/var __exportAll = [\s\S]*?return target;\s*\};\n?/g, '');
|
|
410
|
+
// Inline __exportAll calls: __exportAll({key: () => value, ...}) -> {key: value, ...}
|
|
411
|
+
// Match __exportAll(...) or /* @__PURE__ */ __exportAll(...)
|
|
412
|
+
code = code.replace(/(?:\/\* @__PURE__ \*\/\s*)?__exportAll\(\s*\{([\s\S]*?)\}\s*\)/g, (_match, body) => {
|
|
413
|
+
// Replace each "key: () => value" with "get key() { return value }" for proper live binding
|
|
414
|
+
const inlined = body.replace(/(\w+)\s*:\s*\(\)\s*=>\s*([^,\n}]+?)([,\n])/g, 'get $1() { return $2; }$3');
|
|
415
|
+
return `{${inlined}}`;
|
|
416
|
+
});
|
|
417
|
+
// Remove Object.defineProperty for Symbol.toStringTag
|
|
418
|
+
code = code.replace(/\s*Object\.defineProperty\(\w+,\s*Symbol\.toStringTag[^;]*;\s*/g, '');
|
|
419
|
+
// Extract the default export variable
|
|
420
|
+
let exportVar = '_default';
|
|
421
|
+
const m1 = code.match(/export\s*\{\s*(\w+)\s+as\s+default\s*\}/);
|
|
422
|
+
if (m1) {
|
|
423
|
+
exportVar = m1[1];
|
|
424
|
+
code = code.replace(m1[0], '');
|
|
425
|
+
}
|
|
426
|
+
code = code.replace(/export\s+default\s+(\w+)\s*;?/g, (_, v) => {
|
|
427
|
+
exportVar = v;
|
|
428
|
+
return '';
|
|
429
|
+
});
|
|
430
|
+
code = code.replace(/export\s+\{[^}]*\}\s*;?/g, '');
|
|
431
|
+
// Find the return statement variable (IIFE returns the component)
|
|
432
|
+
const returnMatch = code.match(/return\s+(\w+)\s*;?\s*$/);
|
|
433
|
+
if (returnMatch) {
|
|
434
|
+
exportVar = returnMatch[1];
|
|
435
|
+
code = code.replace(returnMatch[0], '');
|
|
436
|
+
}
|
|
437
|
+
// Generate styleObjectId hash
|
|
438
|
+
const styleId = (0, _TemplateCompiler.getStyleObjectId)(entryName);
|
|
439
|
+
return `let $style$${styleId} = {"@info":{"styleObjectId":${styleId}}};
|
|
440
|
+
const $app_style$${styleId} = $style$${styleId};
|
|
441
|
+
${code.trim()}
|
|
442
|
+
$app_define$("${defineId}", [], function($app_require$, $app_exports$, $app_module$) {
|
|
443
|
+
$app_module$.exports = ${exportVar}.default || ${exportVar};
|
|
444
|
+
$app_module$.exports.style = $app_style$${styleId};
|
|
445
|
+
});
|
|
446
|
+
$app_bootstrap$("${bootstrapId}");
|
|
447
|
+
`;
|
|
448
|
+
}
|
|
449
|
+
var _default = exports.default = ViteCompiler;
|
|
@@ -40,6 +40,10 @@ interface IJavascriptCompileOption extends ICompileParam {
|
|
|
40
40
|
* 禁用 jsc
|
|
41
41
|
*/
|
|
42
42
|
enableJsc?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* 启用 VRU 包装格式(release 模式生成 manifest+CERT+inner-vru 的双层 RPK)
|
|
45
|
+
*/
|
|
46
|
+
enableVru?: boolean;
|
|
43
47
|
/**
|
|
44
48
|
* 启用 protobuf
|
|
45
49
|
*/
|
|
@@ -48,6 +52,11 @@ interface IJavascriptCompileOption extends ICompileParam {
|
|
|
48
52
|
* 启用应用自动化测试
|
|
49
53
|
*/
|
|
50
54
|
enableE2e?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* 自动化测试配置文件路径
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
e2eConfigPath?: string;
|
|
51
60
|
/**
|
|
52
61
|
* 启用 png8 压缩
|
|
53
62
|
*/
|
|
@@ -8,7 +8,9 @@ declare class VelaWebpackConfigurator implements IWebpackConfigurator {
|
|
|
8
8
|
protected createWrapPlugin(): RspackPluginInstance;
|
|
9
9
|
protected createBundleAnalyzerPlugin(): any;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* 生成entry
|
|
12
|
+
* 1. 通过读取 manifest.json 生成 entry
|
|
13
|
+
* 2. 通过自动化测试的entry配置生成entry
|
|
12
14
|
* @returns
|
|
13
15
|
*/
|
|
14
16
|
createEntry(): string | EntryObject | string[];
|
|
@@ -9,6 +9,7 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
9
9
|
var _UxFileUtils = _interopRequireDefault(require("../../../utils/ux/UxFileUtils"));
|
|
10
10
|
var _WrapPlugin = _interopRequireDefault(require("./plugin/WrapPlugin"));
|
|
11
11
|
var _UxCompileUtil = _interopRequireDefault(require("./utils/UxCompileUtil"));
|
|
12
|
+
var _UxUtil = _interopRequireDefault(require("@aiot-toolkit/parser/lib/ux/utils/UxUtil"));
|
|
12
13
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
14
|
class VelaWebpackConfigurator {
|
|
14
15
|
createPlugins() {
|
|
@@ -34,7 +35,9 @@ class VelaWebpackConfigurator {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
|
-
*
|
|
38
|
+
* 生成entry
|
|
39
|
+
* 1. 通过读取 manifest.json 生成 entry
|
|
40
|
+
* 2. 通过自动化测试的entry配置生成entry
|
|
38
41
|
* @returns
|
|
39
42
|
*/
|
|
40
43
|
createEntry() {
|
|
@@ -44,7 +47,19 @@ class VelaWebpackConfigurator {
|
|
|
44
47
|
} = this.param;
|
|
45
48
|
const configFilePath = _UxFileUtils.default.getManifestFilePath(this.param.projectPath, this.param.sourceRoot);
|
|
46
49
|
if (_fsExtra.default.existsSync(configFilePath)) {
|
|
50
|
+
// 1
|
|
47
51
|
const config = _fsExtra.default.readJSONSync(configFilePath);
|
|
52
|
+
// 2
|
|
53
|
+
if (this.param.e2eConfigPath && this.param.enableE2e) {
|
|
54
|
+
const e2eConfig = _UxUtil.default.getE2eConfig({
|
|
55
|
+
projectPath: this.param.projectPath,
|
|
56
|
+
e2eConfigPath: this.param.e2eConfigPath
|
|
57
|
+
});
|
|
58
|
+
const testPagePath = _path.default.parse(_path.default.relative(_path.default.join(this.param.projectPath, sourceRoot), _path.default.join(e2eConfig.dir, e2eConfig.entry.path)).replaceAll(_path.default.sep, _path.default.posix.sep));
|
|
59
|
+
config.router.pages[testPagePath.dir] = {
|
|
60
|
+
component: testPagePath.name
|
|
61
|
+
};
|
|
62
|
+
}
|
|
48
63
|
return _UxCompileUtil.default.resolveEntries(config, _path.default.resolve(projectPath, sourceRoot), projectPath);
|
|
49
64
|
} else {
|
|
50
65
|
throw new Error(`Configuration file does not exist: ${configFilePath}`);
|
|
@@ -8,6 +8,10 @@ interface IWidget {
|
|
|
8
8
|
sizes: string[];
|
|
9
9
|
type?: string;
|
|
10
10
|
}
|
|
11
|
+
interface IWidgetProvider {
|
|
12
|
+
name: string;
|
|
13
|
+
path: string;
|
|
14
|
+
}
|
|
11
15
|
/**
|
|
12
16
|
* vela manifest文件对应的数据结构
|
|
13
17
|
*/
|
|
@@ -29,12 +33,20 @@ export default interface IManifest {
|
|
|
29
33
|
entry: string;
|
|
30
34
|
pages: Dictionary<{
|
|
31
35
|
component?: string;
|
|
36
|
+
launchMode?: string;
|
|
32
37
|
}>;
|
|
38
|
+
floatingWindows?: any;
|
|
33
39
|
};
|
|
34
40
|
services: IService[] | Record<string, IService>;
|
|
35
41
|
minAPILevel?: number;
|
|
36
42
|
packageInfo?: Dictionary<string | number>;
|
|
43
|
+
widgetProvider?: IWidgetProvider[];
|
|
37
44
|
icon: string;
|
|
45
|
+
workers?: {
|
|
46
|
+
entries: {
|
|
47
|
+
file: string;
|
|
48
|
+
}[];
|
|
49
|
+
};
|
|
38
50
|
}
|
|
39
51
|
export interface IFeatures {
|
|
40
52
|
name: string;
|
|
@@ -4,7 +4,16 @@ declare class WrapPlugin {
|
|
|
4
4
|
private compilerOption;
|
|
5
5
|
constructor(compilerOption: IJavascriptCompileOption);
|
|
6
6
|
apply(compiler: Compiler): void;
|
|
7
|
+
private getComponentName;
|
|
8
|
+
private findMatching;
|
|
9
|
+
/**
|
|
10
|
+
* Extract keyed modules from rspack's __webpack_modules__ object
|
|
11
|
+
*/
|
|
12
|
+
private extractModules;
|
|
13
|
+
/**
|
|
14
|
+
* Clean a module body into blueos-pack format component block
|
|
15
|
+
*/
|
|
16
|
+
private buildBlock;
|
|
7
17
|
private wrap;
|
|
8
|
-
private translateStyleFunc;
|
|
9
18
|
}
|
|
10
19
|
export default WrapPlugin;
|