vite-plugin-taro 0.3.2 → 0.4.0
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.en.md +44 -0
- package/README.md +22 -497
- package/client.d.ts +9 -0
- package/dist/node/plugins/client/client-taro.d.ts +4 -0
- package/dist/node/plugins/client/client-taro.js +19 -0
- package/dist/node/plugins/client/constant.d.ts +4 -0
- package/dist/node/plugins/client/constant.js +4 -0
- package/dist/node/plugins/conditional/conditional-directives.d.ts +4 -0
- package/dist/node/plugins/{conditional-directives.js → conditional/conditional-directives.js} +27 -11
- package/dist/node/plugins/css/plugins.d.ts +4 -0
- package/dist/node/plugins/css/plugins.js +84 -0
- package/dist/node/plugins/h5/constant.d.ts +2 -0
- package/dist/node/plugins/h5/constant.js +3 -0
- package/dist/node/plugins/h5/plugins.d.ts +4 -0
- package/dist/node/plugins/h5/plugins.js +161 -0
- package/dist/node/plugins/h5/resolver/module-resolver.d.ts +14 -0
- package/dist/node/plugins/h5/resolver/module-resolver.js +19 -0
- package/dist/node/plugins/h5/transform-app.d.ts +10 -0
- package/dist/node/plugins/h5/transform-app.js +48 -0
- package/dist/node/plugins/wx/dev/dev-host.d.ts +15 -0
- package/dist/node/plugins/wx/dev/dev-host.js +352 -0
- package/dist/node/plugins/wx/dev/hmr-files.d.ts +28 -0
- package/dist/node/plugins/wx/dev/hmr-files.js +34 -0
- package/dist/node/plugins/wx/dev/patch-publisher.d.ts +22 -0
- package/dist/node/plugins/wx/dev/patch-publisher.js +40 -0
- package/dist/node/plugins/wx/dev/plugin.d.ts +7 -0
- package/dist/node/plugins/wx/dev/plugin.js +73 -0
- package/dist/node/plugins/wx/dev/react-refresh.d.ts +20 -0
- package/dist/node/plugins/wx/dev/react-refresh.js +198 -0
- package/dist/node/plugins/wx/module.d.ts +45 -0
- package/dist/node/plugins/wx/module.js +66 -0
- package/dist/node/plugins/wx/native/compile-native-component-interface.d.ts +21 -0
- package/dist/node/plugins/wx/native/compile-native-component-interface.js +29 -0
- package/dist/node/plugins/wx/native/create-native-component-output.d.ts +15 -0
- package/dist/node/plugins/wx/native/create-native-component-output.js +39 -0
- package/dist/node/plugins/wx/native/native-component-assets.d.ts +26 -0
- package/dist/node/plugins/wx/native/native-component-assets.js +76 -0
- package/dist/node/plugins/wx/native/native-component-interface.d.ts +12 -0
- package/dist/node/plugins/wx/native/native-component-interface.js +201 -0
- package/dist/node/plugins/wx/output/files.d.ts +12 -0
- package/dist/node/plugins/wx/output/files.js +12 -0
- package/dist/node/plugins/wx/output/json.d.ts +14 -0
- package/dist/node/plugins/wx/output/json.js +52 -0
- package/dist/node/plugins/wx/output/relative-root.d.ts +2 -0
- package/dist/node/plugins/wx/output/relative-root.js +6 -0
- package/dist/node/plugins/wx/output/templates.d.ts +7 -0
- package/dist/node/plugins/wx/output/templates.js +100 -0
- package/dist/node/plugins/wx/placement/placer.d.ts +78 -0
- package/dist/node/plugins/wx/placement/placer.js +145 -0
- package/dist/node/plugins/wx/placement/plan.d.ts +46 -0
- package/dist/node/plugins/wx/placement/plan.js +210 -0
- package/dist/node/plugins/wx/plugins.d.ts +4 -0
- package/dist/node/plugins/wx/plugins.js +137 -0
- package/dist/node/plugins/wx/render/capsule-wrapper.d.ts +3 -0
- package/dist/node/plugins/wx/render/capsule-wrapper.js +64 -0
- package/dist/node/plugins/wx/render/capsule.d.ts +4 -0
- package/dist/node/plugins/wx/render/capsule.js +13 -0
- package/dist/node/plugins/wx/render/native.d.ts +9 -0
- package/dist/node/plugins/wx/render/native.js +45 -0
- package/dist/node/plugins/wx/render/transport.d.ts +17 -0
- package/dist/node/plugins/wx/render/transport.js +94 -0
- package/dist/node/plugins/wx/resolve/resolver.d.ts +7 -0
- package/dist/node/plugins/wx/resolve/resolver.js +86 -0
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.d.ts +9 -0
- package/dist/node/plugins/wx/resolve/specialize-bootstrap.js +9 -0
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.d.ts +9 -0
- package/dist/node/plugins/wx/resolve/specialize-page-capsule.js +11 -0
- package/dist/node/utils/constant.d.ts +1 -0
- package/dist/node/utils/constant.js +1 -0
- package/dist/node/utils/memoize.d.ts +122 -0
- package/dist/node/utils/memoize.js +86 -0
- package/dist/node/utils/modules.d.ts +20 -24
- package/dist/node/utils/modules.js +21 -34
- package/dist/node/utils/once.d.ts +10 -0
- package/dist/node/utils/once.js +20 -0
- package/dist/node/utils/packages.d.ts +1 -0
- package/dist/node/utils/packages.js +1 -1
- package/dist/node/utils/project-config.d.ts +3 -0
- package/dist/node/utils/project-config.js +8 -0
- package/dist/node/utils/serialized-task-queue.d.ts +9 -0
- package/dist/node/utils/serialized-task-queue.js +17 -0
- package/dist/node/utils/transform.d.ts +11 -0
- package/dist/node/utils/transform.js +58 -0
- package/dist/node/vite-plugin.d.ts +1 -1
- package/dist/node/vite-plugin.js +11 -27
- package/dist/options.d.ts +3 -4
- package/dist/runtime/{taro → client/taro}/api.d.ts +0 -1
- package/dist/runtime/client/taro/api.js +9 -0
- package/dist/runtime/client/taro/component.d.ts +1 -0
- package/dist/runtime/client/taro/component.js +1 -0
- package/dist/runtime/client/taro/define-native-component.d.ts +7 -0
- package/dist/runtime/client/taro/define-native-component.js +4 -0
- package/dist/runtime/h5/app.d.ts +2 -0
- package/dist/runtime/h5/app.js +15 -0
- package/dist/runtime/h5/taro-runtime.d.ts +1 -1
- package/dist/runtime/h5/taro-runtime.js +1 -4
- package/dist/runtime/wx/amphibious/bootstrap.d.ts +4 -0
- package/dist/runtime/wx/amphibious/bootstrap.js +16 -0
- package/dist/runtime/wx/amphibious/transport.d.ts +2 -0
- package/dist/runtime/wx/amphibious/transport.js +4 -0
- package/dist/runtime/wx/capsule/app.d.ts +2 -0
- package/dist/runtime/wx/capsule/app.js +7 -0
- package/dist/runtime/wx/capsule/component.d.ts +3 -0
- package/dist/runtime/wx/capsule/component.js +4 -0
- package/dist/runtime/wx/capsule/page.d.ts +3 -0
- package/dist/runtime/wx/capsule/page.js +68 -0
- package/dist/runtime/wx/capsule/taro-runtime.d.ts +6 -0
- package/dist/runtime/wx/capsule/taro-runtime.js +6 -0
- package/dist/runtime/wx/dev/dev-runtime.d.ts +1 -0
- package/dist/runtime/wx/dev/dev-runtime.js +246 -0
- package/dist/runtime/wx/native/app.d.ts +1 -0
- package/dist/runtime/wx/native/app.js +3 -0
- package/dist/runtime/wx/native/component.d.ts +1 -0
- package/dist/runtime/wx/native/component.js +3 -0
- package/dist/runtime/wx/native/page.d.ts +1 -0
- package/dist/runtime/wx/native/page.js +4 -0
- package/dist/runtime/wx/systemjs/system-core.d.ts +4 -0
- package/dist/runtime/wx/systemjs/system-core.js +331 -0
- package/package.json +21 -14
- package/src/node/plugins/client/client-taro.ts +23 -0
- package/src/node/plugins/client/constant.ts +5 -0
- package/src/node/plugins/{conditional-directives.ts → conditional/conditional-directives.ts} +33 -13
- package/src/node/plugins/css/plugins.ts +96 -0
- package/src/node/plugins/h5/constant.ts +4 -0
- package/src/node/plugins/h5/plugins.ts +197 -0
- package/src/node/plugins/h5/resolver/module-resolver.ts +32 -0
- package/src/node/plugins/h5/transform-app.ts +90 -0
- package/src/node/plugins/wx/dev/dev-host.ts +448 -0
- package/src/node/plugins/wx/dev/hmr-files.ts +55 -0
- package/src/node/plugins/wx/dev/patch-publisher.ts +49 -0
- package/src/node/plugins/wx/dev/plugin.ts +82 -0
- package/src/node/plugins/wx/dev/react-refresh.ts +227 -0
- package/src/node/plugins/wx/module.ts +97 -0
- package/src/node/plugins/wx/native/compile-native-component-interface.ts +47 -0
- package/src/node/plugins/wx/native/create-native-component-output.ts +57 -0
- package/src/node/plugins/wx/native/native-component-assets.ts +114 -0
- package/src/node/plugins/wx/native/native-component-interface.ts +265 -0
- package/src/node/plugins/wx/output/files.ts +27 -0
- package/src/node/plugins/wx/output/json.ts +79 -0
- package/src/node/plugins/wx/output/relative-root.ts +7 -0
- package/src/node/plugins/wx/output/templates.ts +141 -0
- package/src/node/plugins/wx/placement/placer.ts +172 -0
- package/src/node/plugins/wx/placement/plan.ts +306 -0
- package/src/node/plugins/wx/plugins.ts +165 -0
- package/src/node/plugins/wx/render/capsule-wrapper.ts +86 -0
- package/src/node/plugins/wx/render/capsule.ts +21 -0
- package/src/node/plugins/wx/render/native.ts +84 -0
- package/src/node/plugins/wx/render/transport.ts +157 -0
- package/src/node/plugins/wx/resolve/resolver.ts +125 -0
- package/src/node/plugins/wx/resolve/specialize-bootstrap.ts +27 -0
- package/src/node/plugins/wx/resolve/specialize-page-capsule.ts +29 -0
- package/src/node/utils/constant.ts +1 -0
- package/src/node/utils/memoize.ts +149 -0
- package/src/node/utils/modules.ts +36 -38
- package/src/node/utils/once.ts +21 -0
- package/src/node/utils/packages.ts +1 -1
- package/src/node/utils/project-config.ts +10 -0
- package/src/node/utils/serialized-task-queue.ts +20 -0
- package/src/node/utils/transform.ts +82 -0
- package/src/node/vite-plugin.ts +12 -32
- package/src/options.ts +3 -4
- package/src/runtime/client/taro/api.ts +11 -0
- package/src/runtime/client/taro/component.ts +1 -0
- package/src/runtime/client/taro/define-native-component.ts +15 -0
- package/src/runtime/h5/app.ts +25 -0
- package/src/runtime/h5/taro-runtime.ts +1 -4
- package/src/runtime/wx/amphibious/bootstrap.ts +22 -0
- package/src/runtime/wx/amphibious/transport.ts +10 -0
- package/src/runtime/wx/capsule/app.ts +9 -0
- package/src/runtime/wx/capsule/component.ts +6 -0
- package/src/runtime/wx/capsule/page.ts +96 -0
- package/src/runtime/wx/capsule/taro-runtime.ts +14 -0
- package/src/runtime/wx/dev/dev-runtime.ts +317 -0
- package/src/runtime/wx/native/app.ts +4 -0
- package/src/runtime/wx/native/component.ts +4 -0
- package/src/runtime/wx/native/page.ts +6 -0
- package/src/runtime/wx/systemjs/LICENSE +10 -0
- package/src/runtime/wx/systemjs/system-core.js +370 -0
- package/src/runtime/wx/systemjs/system.d.ts +55 -0
- package/src/runtime/wx/wechat.d.ts +52 -0
- package/README.zh.md +0 -521
- package/dist/node/build-context.d.ts +0 -25
- package/dist/node/build-context.js +0 -47
- package/dist/node/css/css-pipeline.d.ts +0 -35
- package/dist/node/css/css-pipeline.js +0 -154
- package/dist/node/plugins/conditional-directives.d.ts +0 -3
- package/dist/node/plugins/taro-runtime.d.ts +0 -5
- package/dist/node/plugins/taro-runtime.js +0 -18
- package/dist/node/targets/h5/plugin.d.ts +0 -6
- package/dist/node/targets/h5/plugin.js +0 -117
- package/dist/node/targets/h5/virtual-modules.d.ts +0 -5
- package/dist/node/targets/h5/virtual-modules.js +0 -60
- package/dist/node/targets/wx/companion-assets.d.ts +0 -19
- package/dist/node/targets/wx/companion-assets.js +0 -129
- package/dist/node/targets/wx/dev-server/development-session.d.ts +0 -32
- package/dist/node/targets/wx/dev-server/development-session.js +0 -215
- package/dist/node/targets/wx/dev-server/full-build-scheduler.d.ts +0 -14
- package/dist/node/targets/wx/dev-server/full-build-scheduler.js +0 -60
- package/dist/node/targets/wx/dev-server/js-utils.d.ts +0 -5
- package/dist/node/targets/wx/dev-server/js-utils.js +0 -28
- package/dist/node/targets/wx/dev-server/output.d.ts +0 -19
- package/dist/node/targets/wx/dev-server/output.js +0 -44
- package/dist/node/targets/wx/dev-server/rolldown-runtime-source.d.ts +0 -8
- package/dist/node/targets/wx/dev-server/rolldown-runtime-source.js +0 -95
- package/dist/node/targets/wx/dev-server/update-server-state.d.ts +0 -65
- package/dist/node/targets/wx/dev-server/update-server-state.js +0 -116
- package/dist/node/targets/wx/dev-server/update-transport.d.ts +0 -28
- package/dist/node/targets/wx/dev-server/update-transport.js +0 -212
- package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.d.ts +0 -44
- package/dist/node/targets/wx/dev-server/vite-bundled-dev-adapter.js +0 -145
- package/dist/node/targets/wx/development-files.d.ts +0 -8
- package/dist/node/targets/wx/development-files.js +0 -8
- package/dist/node/targets/wx/plugin.d.ts +0 -6
- package/dist/node/targets/wx/plugin.js +0 -144
- package/dist/node/targets/wx/react-refresh.d.ts +0 -4
- package/dist/node/targets/wx/react-refresh.js +0 -38
- package/dist/node/targets/wx/virtual-modules.d.ts +0 -16
- package/dist/node/targets/wx/virtual-modules.js +0 -120
- package/dist/node/utils/async.d.ts +0 -8
- package/dist/node/utils/async.js +0 -16
- package/dist/node/utils/filesystem.d.ts +0 -13
- package/dist/node/utils/filesystem.js +0 -43
- package/dist/runtime/taro/api.js +0 -11
- package/dist/runtime/taro/components.d.ts +0 -2
- package/dist/runtime/taro/components.js +0 -2
- package/dist/runtime/wx/page-update.d.ts +0 -6
- package/dist/runtime/wx/page-update.js +0 -157
- package/dist/runtime/wx/taro-runtime.d.ts +0 -5
- package/dist/runtime/wx/taro-runtime.js +0 -6
- package/dist/runtime/wx/update-client-state.d.ts +0 -68
- package/dist/runtime/wx/update-client-state.js +0 -84
- package/dist/runtime/wx/update-client.d.ts +0 -1
- package/dist/runtime/wx/update-client.js +0 -171
- package/src/node/build-context.ts +0 -62
- package/src/node/css/css-pipeline.ts +0 -171
- package/src/node/plugins/taro-runtime.ts +0 -22
- package/src/node/targets/h5/plugin.ts +0 -135
- package/src/node/targets/h5/virtual-modules.ts +0 -71
- package/src/node/targets/wx/companion-assets.ts +0 -174
- package/src/node/targets/wx/dev-server/development-session.ts +0 -271
- package/src/node/targets/wx/dev-server/full-build-scheduler.ts +0 -62
- package/src/node/targets/wx/dev-server/js-utils.ts +0 -33
- package/src/node/targets/wx/dev-server/output.ts +0 -56
- package/src/node/targets/wx/dev-server/rolldown-runtime-source.ts +0 -95
- package/src/node/targets/wx/dev-server/update-server-state.ts +0 -183
- package/src/node/targets/wx/dev-server/update-transport.ts +0 -261
- package/src/node/targets/wx/dev-server/vite-bundled-dev-adapter.ts +0 -203
- package/src/node/targets/wx/development-files.ts +0 -11
- package/src/node/targets/wx/plugin.ts +0 -164
- package/src/node/targets/wx/react-refresh.ts +0 -51
- package/src/node/targets/wx/virtual-modules.ts +0 -152
- package/src/node/utils/async.ts +0 -19
- package/src/node/utils/filesystem.ts +0 -45
- package/src/runtime/taro/api.ts +0 -13
- package/src/runtime/taro/components.ts +0 -2
- package/src/runtime/wx/page-update.ts +0 -230
- package/src/runtime/wx/react-refresh.d.ts +0 -20
- package/src/runtime/wx/taro-runtime.ts +0 -7
- package/src/runtime/wx/update-client-state.ts +0 -138
- package/src/runtime/wx/update-client.ts +0 -223
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { RolldownMagicString } from 'rolldown';
|
|
3
|
+
import { parseAst } from 'rolldown/parseAst';
|
|
4
|
+
import { normalizeModuleId } from '../../../utils/modules.js';
|
|
5
|
+
import { clientTaroNativeId } from '../../client/constant.js';
|
|
6
|
+
/** Replaces native component interface calls with source-folder names and returns their static metadata. */
|
|
7
|
+
export function transformNativeComponentInterfaces(code, id, sourcemap) {
|
|
8
|
+
const moduleId = normalizeModuleId(id);
|
|
9
|
+
const program = parseAst(code, {
|
|
10
|
+
astType: 'ts',
|
|
11
|
+
lang: 'tsx',
|
|
12
|
+
preserveParens: false,
|
|
13
|
+
sourceType: 'module'
|
|
14
|
+
}, moduleId);
|
|
15
|
+
const declaredInterfaces = collectInterfaceDeclarations(program);
|
|
16
|
+
const macroImports = collectMacroImports(program);
|
|
17
|
+
const importedMacroNames = new Set(macroImports.flatMap((item) => item.names));
|
|
18
|
+
const calls = collectTopLevelMacroCalls(program, importedMacroNames);
|
|
19
|
+
const replacements = calls.map((call) => {
|
|
20
|
+
const definition = parseDefinition(call, moduleId, declaredInterfaces, (message) => createTransformError(message, moduleId, code, call.start));
|
|
21
|
+
return { call, definition };
|
|
22
|
+
});
|
|
23
|
+
// This transform-local mutable buffer applies non-overlapping AST edits without regenerating untouched source.
|
|
24
|
+
const transformed = new RolldownMagicString(code, { filename: moduleId });
|
|
25
|
+
replacements.forEach(({ call, definition }) => {
|
|
26
|
+
transformed.overwrite(call.start, call.end, JSON.stringify(path.posix.basename(definition.folder)));
|
|
27
|
+
});
|
|
28
|
+
macroImports.forEach(({ declaration }) => {
|
|
29
|
+
transformed.remove(declaration.start, declaration.end);
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
code: transformed.toString(),
|
|
33
|
+
map: sourcemap ? createSourceMap(transformed, moduleId) : null,
|
|
34
|
+
definitions: replacements.map(({ definition }) => definition)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Normalizes Rolldown's native source-map object to the public plugin source-map shape. */
|
|
38
|
+
function createSourceMap(transformed, moduleId) {
|
|
39
|
+
const sourceMap = transformed.generateMap({
|
|
40
|
+
hires: 'boundary',
|
|
41
|
+
includeContent: true,
|
|
42
|
+
source: moduleId
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
file: sourceMap.file,
|
|
46
|
+
mappings: sourceMap.mappings,
|
|
47
|
+
names: sourceMap.names,
|
|
48
|
+
sources: sourceMap.sources,
|
|
49
|
+
sourcesContent: sourceMap.sourcesContent,
|
|
50
|
+
version: sourceMap.version
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Finds named imports of the compile-time macro and records their local aliases. */
|
|
54
|
+
function collectMacroImports(program) {
|
|
55
|
+
return program.body.flatMap((statement) => {
|
|
56
|
+
if (statement.type !== 'ImportDeclaration' || statement.source.value !== clientTaroNativeId) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
const names = statement.specifiers.flatMap((specifier) => {
|
|
60
|
+
if (specifier.type !== 'ImportSpecifier' || getStaticName(specifier.imported) !== 'defineNativeComponent') {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
return [specifier.local.name];
|
|
64
|
+
});
|
|
65
|
+
return names.length === 0 ? [] : [{ declaration: statement, names }];
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Collects direct module-level macro calls, excluding calls inside nested scopes. */
|
|
69
|
+
function collectTopLevelMacroCalls(program, importedMacroNames) {
|
|
70
|
+
return program.body.flatMap((statement) => {
|
|
71
|
+
if (statement.type === 'ExpressionStatement') {
|
|
72
|
+
return isImportedMacroCall(statement.expression, importedMacroNames) ? [statement.expression] : [];
|
|
73
|
+
}
|
|
74
|
+
if (statement.type === 'ExportDefaultDeclaration') {
|
|
75
|
+
return isImportedMacroCall(statement.declaration, importedMacroNames) ? [statement.declaration] : [];
|
|
76
|
+
}
|
|
77
|
+
const declaration = statement.type === 'ExportNamedDeclaration' ? statement.declaration : statement;
|
|
78
|
+
if (declaration?.type !== 'VariableDeclaration') {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
return declaration.declarations.flatMap(({ init }) => {
|
|
82
|
+
return isImportedMacroCall(init, importedMacroNames) ? [init] : [];
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** Matches a direct call to one of the macro's module-level import bindings. */
|
|
87
|
+
function isImportedMacroCall(node, importedMacroNames) {
|
|
88
|
+
return (node?.type === 'CallExpression' && node.callee.type === 'Identifier' && importedMacroNames.has(node.callee.name));
|
|
89
|
+
}
|
|
90
|
+
/** Parses one native entry loader and its optional TypeScript interface. */
|
|
91
|
+
function parseDefinition(call, moduleId, declaredInterfaces, buildError) {
|
|
92
|
+
if (call.arguments.length !== 1) {
|
|
93
|
+
throw buildError('defineNativeComponent() requires exactly one entry loader');
|
|
94
|
+
}
|
|
95
|
+
const entryReference = readStaticEntryImport(call.arguments[0]);
|
|
96
|
+
if (!entryReference) {
|
|
97
|
+
throw buildError('Native component entry must use () => import(...) with a static relative .js path');
|
|
98
|
+
}
|
|
99
|
+
const entryPath = normalizeModuleId(path.resolve(path.dirname(moduleId), entryReference));
|
|
100
|
+
return {
|
|
101
|
+
folder: path.posix.dirname(entryPath),
|
|
102
|
+
entry: path.posix.basename(entryPath, '.js'),
|
|
103
|
+
fields: readInterfaceFields(call.typeArguments, declaredInterfaces, buildError)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** Collects non-generic local object aliases and interfaces as native template field declarations. */
|
|
107
|
+
function collectInterfaceDeclarations(program) {
|
|
108
|
+
// This module-local map supports nearby declarations without constructing a TypeScript type-checker program.
|
|
109
|
+
const declarations = new Map();
|
|
110
|
+
for (const statement of program.body) {
|
|
111
|
+
const declaration = statement.type === 'ExportNamedDeclaration' ? statement.declaration : statement;
|
|
112
|
+
if (declaration?.type === 'TSTypeAliasDeclaration' &&
|
|
113
|
+
!declaration.typeParameters &&
|
|
114
|
+
declaration.typeAnnotation.type === 'TSTypeLiteral') {
|
|
115
|
+
declarations.set(declaration.id.name, declaration.typeAnnotation.members);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (declaration?.type === 'TSInterfaceDeclaration' &&
|
|
119
|
+
!declaration.typeParameters &&
|
|
120
|
+
declaration.extends.length === 0) {
|
|
121
|
+
declarations.set(declaration.id.name, declaration.body.body);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return declarations;
|
|
125
|
+
}
|
|
126
|
+
/** Resolves an inline type or a non-generic object declaration from the current module. */
|
|
127
|
+
function resolveInterfaceMembers(typeNode, declarations) {
|
|
128
|
+
if (typeNode.type === 'TSTypeLiteral') {
|
|
129
|
+
return typeNode.members;
|
|
130
|
+
}
|
|
131
|
+
if (typeNode.type === 'TSTypeReference' && typeNode.typeName.type === 'Identifier' && !typeNode.typeArguments) {
|
|
132
|
+
return declarations.get(typeNode.typeName.name);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Reads native template field names without resolving or validating their TypeScript value types. */
|
|
136
|
+
function readInterfaceFields(typeArguments, declaredInterfaces, buildError) {
|
|
137
|
+
if (!typeArguments) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
if (typeArguments.params.length !== 1) {
|
|
141
|
+
throw buildError('Native component interface must be one TypeScript object type');
|
|
142
|
+
}
|
|
143
|
+
const firstType = typeArguments.params[0];
|
|
144
|
+
const members = firstType ? resolveInterfaceMembers(firstType, declaredInterfaces) : undefined;
|
|
145
|
+
if (!members) {
|
|
146
|
+
throw buildError('Native component interface must be inline or declared in the same module');
|
|
147
|
+
}
|
|
148
|
+
// This local set preserves declaration order while rejecting ambiguous duplicate template fields.
|
|
149
|
+
const names = new Set();
|
|
150
|
+
for (const member of members) {
|
|
151
|
+
if (member.type !== 'TSPropertySignature' && member.type !== 'TSMethodSignature') {
|
|
152
|
+
throw buildError('Native component interface must contain only static fields');
|
|
153
|
+
}
|
|
154
|
+
if (member.computed) {
|
|
155
|
+
throw buildError('Native component interface contains a computed field');
|
|
156
|
+
}
|
|
157
|
+
const name = getStaticName(member.key);
|
|
158
|
+
if (!name) {
|
|
159
|
+
throw buildError('Native component interface contains a computed field');
|
|
160
|
+
}
|
|
161
|
+
if (names.has(name)) {
|
|
162
|
+
throw buildError(`Duplicate native component interface field: ${name}`);
|
|
163
|
+
}
|
|
164
|
+
names.add(name);
|
|
165
|
+
}
|
|
166
|
+
return [...names].filter((name) => name !== 'children');
|
|
167
|
+
}
|
|
168
|
+
/** Reads an identifier or string-literal key. */
|
|
169
|
+
function getStaticName(node) {
|
|
170
|
+
if (node.type === 'Identifier') {
|
|
171
|
+
return node.name;
|
|
172
|
+
}
|
|
173
|
+
if (node.type === 'Literal' && typeof node.value === 'string') {
|
|
174
|
+
return node.value;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Reads a zero-argument entry loader containing one statically resolvable native `.js` import. */
|
|
178
|
+
function readStaticEntryImport(node) {
|
|
179
|
+
if (node?.type !== 'ArrowFunctionExpression' || node.params.length !== 0 || node.body.type !== 'ImportExpression') {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
const importExpression = node.body;
|
|
183
|
+
if (importExpression.source.type !== 'Literal' ||
|
|
184
|
+
typeof importExpression.source.value !== 'string' ||
|
|
185
|
+
importExpression.options !== null ||
|
|
186
|
+
!isLocalJavaScriptEntry(importExpression.source.value)) {
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
return importExpression.source.value;
|
|
190
|
+
}
|
|
191
|
+
/** Limits component entries to JavaScript files reachable from their interface module. */
|
|
192
|
+
function isLocalJavaScriptEntry(entry) {
|
|
193
|
+
return (entry.startsWith('./') || entry.startsWith('../')) && path.posix.extname(entry) === '.js';
|
|
194
|
+
}
|
|
195
|
+
/** Adds a stable source location to semantic errors reported after parsing. */
|
|
196
|
+
function createTransformError(message, moduleId, code, offset) {
|
|
197
|
+
const prefix = code.slice(0, offset);
|
|
198
|
+
const line = prefix.split('\n').length;
|
|
199
|
+
const column = offset - prefix.lastIndexOf('\n');
|
|
200
|
+
return new Error(`${message}\n${moduleId}:${line}:${column}`);
|
|
201
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Rolldown } from 'vite';
|
|
2
|
+
import type { VitePluginTaroOptions } from '../../../../options.ts';
|
|
3
|
+
import type { GeneratedSubpackage } from '../placement/placer.ts';
|
|
4
|
+
/** Creates every native companion file derived from the final Rolldown bundle. */
|
|
5
|
+
export declare function createOutputFiles({ bundle, options, subpackages, getModuleInfo }: {
|
|
6
|
+
bundle: Rolldown.OutputBundle;
|
|
7
|
+
options: VitePluginTaroOptions;
|
|
8
|
+
subpackages: readonly GeneratedSubpackage[];
|
|
9
|
+
getModuleInfo: (moduleId: string) => {
|
|
10
|
+
meta: Rolldown.CustomPluginOptions;
|
|
11
|
+
} | null;
|
|
12
|
+
}): Promise<Rolldown.EmittedFile[]>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createNativeComponentOutput } from '../native/create-native-component-output.js';
|
|
2
|
+
import { createJsonAssets } from './json.js';
|
|
3
|
+
import { createTemplateAssets } from './templates.js';
|
|
4
|
+
/** Creates every native companion file derived from the final Rolldown bundle. */
|
|
5
|
+
export async function createOutputFiles({ bundle, options, subpackages, getModuleInfo }) {
|
|
6
|
+
const nativeOutput = await createNativeComponentOutput({ bundle, getModuleInfo });
|
|
7
|
+
return [
|
|
8
|
+
...createJsonAssets({ options, subpackages, nativeComponents: nativeOutput.registrations }),
|
|
9
|
+
...createTemplateAssets(bundle, options, nativeOutput.registrations),
|
|
10
|
+
...nativeOutput.files
|
|
11
|
+
];
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Rolldown } from 'vite';
|
|
2
|
+
import type { JsonObject, VitePluginTaroOptions } from '../../../../options.ts';
|
|
3
|
+
import type { GeneratedSubpackage } from '../placement/placer.ts';
|
|
4
|
+
/** Creates every configured native JSON asset. */
|
|
5
|
+
export declare function createJsonAssets({ options, subpackages, nativeComponents }: {
|
|
6
|
+
options: VitePluginTaroOptions;
|
|
7
|
+
subpackages: readonly GeneratedSubpackage[];
|
|
8
|
+
nativeComponents: readonly {
|
|
9
|
+
name: string;
|
|
10
|
+
componentPath: string;
|
|
11
|
+
}[];
|
|
12
|
+
}): Rolldown.EmittedAsset[];
|
|
13
|
+
/** Serializes one native JSON object with stable formatting. */
|
|
14
|
+
export declare function renderJson(value: JsonObject): string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createAppConfig } from '../../../utils/project-config.js';
|
|
2
|
+
import { isGeneratedSubpackageFile } from '../placement/plan.js';
|
|
3
|
+
import { toRootRelativePath } from './relative-root.js';
|
|
4
|
+
/** Creates every configured native JSON asset. */
|
|
5
|
+
export function createJsonAssets({ options, subpackages, nativeComponents }) {
|
|
6
|
+
return [
|
|
7
|
+
createJsonAsset('app.json', {
|
|
8
|
+
...createAppConfig(options),
|
|
9
|
+
...(subpackages.length > 0 ? { subPackages: subpackages } : {})
|
|
10
|
+
}),
|
|
11
|
+
...options.pages.map((page) => createJsonAsset(`${page.path}.json`, createPageJson(page, nativeComponents))),
|
|
12
|
+
createJsonAsset('project.config.json', options.projectConfigJson),
|
|
13
|
+
...(options.projectPrivateConfigJson
|
|
14
|
+
? [createJsonAsset('project.private.config.json', options.projectPrivateConfigJson)]
|
|
15
|
+
: []),
|
|
16
|
+
createJsonAsset('sitemap.json', options.sitemapJson)
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
/** Creates Page JSON with generated Taro and native component registrations. */
|
|
20
|
+
function createPageJson(page, nativeComponents) {
|
|
21
|
+
const usingComponents = isJsonObject(page.config.usingComponents) ? page.config.usingComponents : {};
|
|
22
|
+
// Cross-package components require a placeholder while WeChat downloads their generated subpackage. Paths are
|
|
23
|
+
// root-absolute, so remove the leading slash before testing the output-relative subpackage prefix.
|
|
24
|
+
// https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/async.html
|
|
25
|
+
// https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/placeholder.html
|
|
26
|
+
const placeholderEntries = nativeComponents.flatMap(({ name, componentPath }) => isGeneratedSubpackageFile(componentPath.slice(1)) ? [[name, 'view']] : []);
|
|
27
|
+
return {
|
|
28
|
+
...page.config,
|
|
29
|
+
...(placeholderEntries.length > 0 ? { componentPlaceholder: Object.fromEntries(placeholderEntries) } : {}),
|
|
30
|
+
usingComponents: {
|
|
31
|
+
...usingComponents,
|
|
32
|
+
...Object.fromEntries(nativeComponents.map(({ name, componentPath }) => [name, componentPath])),
|
|
33
|
+
comp: toRootRelativePath(page.path, 'comp')
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Tests whether a configured JSON value can be merged as an object. */
|
|
38
|
+
function isJsonObject(value) {
|
|
39
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
40
|
+
}
|
|
41
|
+
/** Serializes one native JSON object with stable formatting. */
|
|
42
|
+
export function renderJson(value) {
|
|
43
|
+
return `${JSON.stringify(value, null, 4)}\n`;
|
|
44
|
+
}
|
|
45
|
+
/** Creates one native JSON asset. */
|
|
46
|
+
function createJsonAsset(fileName, value) {
|
|
47
|
+
return {
|
|
48
|
+
type: 'asset',
|
|
49
|
+
fileName,
|
|
50
|
+
source: renderJson(value)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
/** Creates a Page-relative path to a file emitted at the wx output root. */
|
|
3
|
+
export function toRootRelativePath(pagePath, rootFileName) {
|
|
4
|
+
const relativePath = path.posix.relative(path.posix.dirname(pagePath), rootFileName);
|
|
5
|
+
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
|
6
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Rolldown } from 'vite';
|
|
2
|
+
import type { VitePluginTaroOptions } from '../../../../options.ts';
|
|
3
|
+
/** Creates Taro's shared WeChat templates and native WXML/WXSS companions for every Page. */
|
|
4
|
+
export declare function createTemplateAssets(bundle: Rolldown.OutputBundle, options: VitePluginTaroOptions, nativeComponents: readonly {
|
|
5
|
+
name: string;
|
|
6
|
+
fields: readonly string[];
|
|
7
|
+
}[]): Rolldown.EmittedAsset[];
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { recursiveMerge } from '@tarojs/helper';
|
|
2
|
+
import { Weapp as WxPlatform } from '@tarojs/plugin-platform-weapp';
|
|
3
|
+
import { normalizeModuleId } from '../../../utils/modules.js';
|
|
4
|
+
import { packageRequire } from '../../../utils/packages.js';
|
|
5
|
+
import { renderJson } from './json.js';
|
|
6
|
+
import { toRootRelativePath } from './relative-root.js';
|
|
7
|
+
const taroComponentsModulePath = packageRequire.resolve('@tarojs/plugin-platform-weapp/dist/components-react');
|
|
8
|
+
/** Creates Taro's shared WeChat templates and native WXML/WXSS companions for every Page. */
|
|
9
|
+
export function createTemplateAssets(bundle, options, nativeComponents) {
|
|
10
|
+
const templateBuilder = createTemplateBuilder();
|
|
11
|
+
return [
|
|
12
|
+
createAsset('base.wxml', templateBuilder.buildTemplate(collectTemplateComponentConfig(bundle, nativeComponents))),
|
|
13
|
+
createAsset('utils.wxs', templateBuilder.buildXScript()),
|
|
14
|
+
createAsset('comp.wxml', templateBuilder.buildBaseComponentTemplate('.wxml')),
|
|
15
|
+
createAsset('comp.json', renderJson(createComponentJson())),
|
|
16
|
+
...options.pages.flatMap((page) => [
|
|
17
|
+
createAsset(`${page.path}.wxml`, templateBuilder.buildPageTemplate(toRootRelativePath(page.path, 'base.wxml'), {
|
|
18
|
+
content: page.config,
|
|
19
|
+
path: page.path
|
|
20
|
+
})),
|
|
21
|
+
createAsset(`${page.path}.wxss`, '')
|
|
22
|
+
])
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
/** Creates the Taro WeChat template builder without invoking its Webpack integration. */
|
|
26
|
+
function createTemplateBuilder() {
|
|
27
|
+
const platform = new WxPlatform({
|
|
28
|
+
helper: {
|
|
29
|
+
recursiveMerge
|
|
30
|
+
},
|
|
31
|
+
modifyWebpackChain() { },
|
|
32
|
+
registerPlatform() { }
|
|
33
|
+
}, {}, {});
|
|
34
|
+
platform.modifyTemplate({});
|
|
35
|
+
return platform.template;
|
|
36
|
+
}
|
|
37
|
+
/** Creates template metadata from reachable Taro hosts and native component JSX fields. */
|
|
38
|
+
function collectTemplateComponentConfig(bundle, nativeComponents) {
|
|
39
|
+
// This local config accumulates names in output order before the template builder consumes it.
|
|
40
|
+
const config = {
|
|
41
|
+
includes: new Set([
|
|
42
|
+
'view',
|
|
43
|
+
'catch-view',
|
|
44
|
+
'static-view',
|
|
45
|
+
'pure-view',
|
|
46
|
+
'click-view',
|
|
47
|
+
'scroll-view',
|
|
48
|
+
'image',
|
|
49
|
+
'static-image',
|
|
50
|
+
'text',
|
|
51
|
+
'static-text'
|
|
52
|
+
]),
|
|
53
|
+
exclude: new Set(),
|
|
54
|
+
thirdPartyComponents: new Map(),
|
|
55
|
+
includeAll: false
|
|
56
|
+
};
|
|
57
|
+
const components = findBundleModule(bundle, taroComponentsModulePath);
|
|
58
|
+
for (const name of components?.renderedExports ?? []) {
|
|
59
|
+
config.includes.add(toDashed(name));
|
|
60
|
+
}
|
|
61
|
+
for (const component of nativeComponents) {
|
|
62
|
+
config.thirdPartyComponents.set(component.name, new Set(component.fields));
|
|
63
|
+
}
|
|
64
|
+
return config;
|
|
65
|
+
}
|
|
66
|
+
/** Finds one module in the final chunk metadata. */
|
|
67
|
+
function findBundleModule(bundle, resolvedId) {
|
|
68
|
+
const normalizedResolvedId = normalizeModuleId(resolvedId);
|
|
69
|
+
for (const output of Object.values(bundle)) {
|
|
70
|
+
if (output.type !== 'chunk') {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const found = Object.entries(output.modules).find(([id]) => normalizeModuleId(id) === normalizedResolvedId);
|
|
74
|
+
if (found) {
|
|
75
|
+
return found[1];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** Converts a React component export to Taro's dashed host-component name. */
|
|
80
|
+
function toDashed(value) {
|
|
81
|
+
return value.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
82
|
+
}
|
|
83
|
+
/** Creates the recursive component configuration expected by Taro's templates. */
|
|
84
|
+
function createComponentJson() {
|
|
85
|
+
return {
|
|
86
|
+
component: true,
|
|
87
|
+
styleIsolation: 'apply-shared',
|
|
88
|
+
usingComponents: {
|
|
89
|
+
comp: './comp'
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Creates one emitted template or style asset. */
|
|
94
|
+
function createAsset(fileName, source) {
|
|
95
|
+
return {
|
|
96
|
+
type: 'asset',
|
|
97
|
+
fileName,
|
|
98
|
+
source
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { Rolldown } from 'vite';
|
|
2
|
+
import { type ModuleGraph } from './plan.ts';
|
|
3
|
+
/** Native app.json declaration for one generated code-only subpackage. */
|
|
4
|
+
export type GeneratedSubpackage = {
|
|
5
|
+
/** Stable native alias derived from the generated root hash. */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Physical directory containing this subpackage's emitted capsules. */
|
|
8
|
+
root: string;
|
|
9
|
+
/** Marks this as a code-only subpackage with no native Page routes. */
|
|
10
|
+
pages: readonly [];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Creates the stateful adapter between graph planning and Rolldown's output lifecycle:
|
|
14
|
+
*
|
|
15
|
+
* - renderStart analyzes transformed modules before chunking.
|
|
16
|
+
* - codeSplitting prevents modules assigned to different packages from being merged.
|
|
17
|
+
* - filename callbacks materialize planned subpackage roots.
|
|
18
|
+
* - renderChunk derives native loading mode from those physical paths.
|
|
19
|
+
* - generateBundle reconciles the plan with chunks that survived tree shaking.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createPlacer(): {
|
|
22
|
+
/** Assigns every transformed module to main or one generated, size-bounded subpackage. */
|
|
23
|
+
analyze(graph: ModuleGraph): void;
|
|
24
|
+
/**
|
|
25
|
+
* Complete Rolldown fragment required to preserve package placement and native entry semantics.
|
|
26
|
+
*
|
|
27
|
+
* ```text
|
|
28
|
+
* native App/Page/Component shell entry
|
|
29
|
+
* └─ static import / runtime importSync() ─▶ explicit capsule entry + static closure [main, no TLA]
|
|
30
|
+
* └─ System.import() ─▶ lazy-a [package A, TLA allowed]
|
|
31
|
+
* └─ static import ─▶ lazy-b [package B]
|
|
32
|
+
*
|
|
33
|
+
* name() assigns lazy-a and lazy-b to their planned package groups
|
|
34
|
+
* includeDependenciesRecursively false: does not pull lazy-b back into package A
|
|
35
|
+
* preserveEntrySignatures allows cross-chunk bindings without weakening native entry exports
|
|
36
|
+
*
|
|
37
|
+
* package A capsule
|
|
38
|
+
* └─ SystemJS dependency ─▶ package B capsule
|
|
39
|
+
* ▲
|
|
40
|
+
* └─ main transport obtains registration with require.async()
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* Explicit entries preserve the shell/capsule rendering boundary while their static edge executes synchronously
|
|
44
|
+
* from main. Once a dynamic boundary is crossed, physical fetches may be asynchronous and modules may use
|
|
45
|
+
* top-level await. SystemJS still links that complete static lazy graph before execution, even across packages.
|
|
46
|
+
*/
|
|
47
|
+
rolldownOptions: {
|
|
48
|
+
output: {
|
|
49
|
+
/**
|
|
50
|
+
* Gives every generated subpackage a distinct Rolldown chunk group. Recursive dependency capture must
|
|
51
|
+
* stay disabled: lazy static dependencies may belong to other subpackages and SystemJS links them
|
|
52
|
+
* asynchronously.
|
|
53
|
+
*/
|
|
54
|
+
codeSplitting: {
|
|
55
|
+
groups: {
|
|
56
|
+
name(moduleId: string): string | null;
|
|
57
|
+
includeDependenciesRecursively: boolean;
|
|
58
|
+
}[];
|
|
59
|
+
};
|
|
60
|
+
/** Preserves exact native shell paths while hashing transport and explicit capsule entries. */
|
|
61
|
+
entryFileNames(chunk: Rolldown.PreRenderedChunk): string;
|
|
62
|
+
/** Converts the planned owner into its physical main or generated subpackage filename template. */
|
|
63
|
+
chunkFileNames(chunk: Rolldown.PreRenderedChunk): string;
|
|
64
|
+
assetFileNames: string;
|
|
65
|
+
};
|
|
66
|
+
preserveEntrySignatures: 'allow-extension';
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Selects loading mode from physical output rather than graph intent. Transport executes in main, so main files
|
|
70
|
+
* use require() and every generated subpackage file uses require.async().
|
|
71
|
+
*/
|
|
72
|
+
getLoadMode(chunk: Rolldown.RenderedChunk): 'sync' | 'async';
|
|
73
|
+
/**
|
|
74
|
+
* Reconciles planned ownership with final chunks through module IDs. Tree-shaken subpackages disappear naturally,
|
|
75
|
+
* while roots are deduplicated and sorted before becoming deterministic app.json declarations.
|
|
76
|
+
*/
|
|
77
|
+
getSubpackages(bundle: Rolldown.OutputBundle): GeneratedSubpackage[];
|
|
78
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { getWxExecutionKind, isTransportModule } from '../module.js';
|
|
2
|
+
import { createPlacementPlan, getSubpackageName, isGeneratedSubpackageFile, mainPackage } from './plan.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates the stateful adapter between graph planning and Rolldown's output lifecycle:
|
|
5
|
+
*
|
|
6
|
+
* - renderStart analyzes transformed modules before chunking.
|
|
7
|
+
* - codeSplitting prevents modules assigned to different packages from being merged.
|
|
8
|
+
* - filename callbacks materialize planned subpackage roots.
|
|
9
|
+
* - renderChunk derives native loading mode from those physical paths.
|
|
10
|
+
* - generateBundle reconciles the plan with chunks that survived tree shaking.
|
|
11
|
+
*/
|
|
12
|
+
export function createPlacer() {
|
|
13
|
+
// Filename and output callbacks run after analyze and read this immutable plan through their shared closure.
|
|
14
|
+
let plan = new Map();
|
|
15
|
+
/**
|
|
16
|
+
* Reduces module ownership to one package for filename generation. Unknown Rolldown-generated modules default to
|
|
17
|
+
* main, empty chunks default to main, and a chunk containing multiple known owners is rejected before paths diverge.
|
|
18
|
+
*/
|
|
19
|
+
function getChunkLocation(chunk) {
|
|
20
|
+
let location;
|
|
21
|
+
for (const moduleId of chunk.moduleIds) {
|
|
22
|
+
const moduleLocation = plan.get(moduleId) ?? mainPackage;
|
|
23
|
+
if (!location) {
|
|
24
|
+
location = moduleLocation;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (!hasSameLocation(location, moduleLocation)) {
|
|
28
|
+
throw new Error(`wx chunk mixes package owners: ${chunk.moduleIds.join(', ')}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return location ?? mainPackage;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
/** Assigns every transformed module to main or one generated, size-bounded subpackage. */
|
|
35
|
+
analyze(graph) {
|
|
36
|
+
plan = createPlacementPlan(graph);
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* Complete Rolldown fragment required to preserve package placement and native entry semantics.
|
|
40
|
+
*
|
|
41
|
+
* ```text
|
|
42
|
+
* native App/Page/Component shell entry
|
|
43
|
+
* └─ static import / runtime importSync() ─▶ explicit capsule entry + static closure [main, no TLA]
|
|
44
|
+
* └─ System.import() ─▶ lazy-a [package A, TLA allowed]
|
|
45
|
+
* └─ static import ─▶ lazy-b [package B]
|
|
46
|
+
*
|
|
47
|
+
* name() assigns lazy-a and lazy-b to their planned package groups
|
|
48
|
+
* includeDependenciesRecursively false: does not pull lazy-b back into package A
|
|
49
|
+
* preserveEntrySignatures allows cross-chunk bindings without weakening native entry exports
|
|
50
|
+
*
|
|
51
|
+
* package A capsule
|
|
52
|
+
* └─ SystemJS dependency ─▶ package B capsule
|
|
53
|
+
* ▲
|
|
54
|
+
* └─ main transport obtains registration with require.async()
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* Explicit entries preserve the shell/capsule rendering boundary while their static edge executes synchronously
|
|
58
|
+
* from main. Once a dynamic boundary is crossed, physical fetches may be asynchronous and modules may use
|
|
59
|
+
* top-level await. SystemJS still links that complete static lazy graph before execution, even across packages.
|
|
60
|
+
*/
|
|
61
|
+
rolldownOptions: {
|
|
62
|
+
output: {
|
|
63
|
+
/**
|
|
64
|
+
* Gives every generated subpackage a distinct Rolldown chunk group. Recursive dependency capture must
|
|
65
|
+
* stay disabled: lazy static dependencies may belong to other subpackages and SystemJS links them
|
|
66
|
+
* asynchronously.
|
|
67
|
+
*/
|
|
68
|
+
codeSplitting: {
|
|
69
|
+
groups: [
|
|
70
|
+
{
|
|
71
|
+
name(moduleId) {
|
|
72
|
+
const location = plan.get(moduleId);
|
|
73
|
+
return location?.kind === 'subpackage' ? getSubpackageName(location.root) : null;
|
|
74
|
+
},
|
|
75
|
+
// Do not let Rolldown pull a lazy group's static closure into one chunk. Past the nested dynamic
|
|
76
|
+
// boundary, transport may obtain registrations from several packages asynchronously before
|
|
77
|
+
// SystemJS links and executes the original graph, including cycles and top-level await.
|
|
78
|
+
includeDependenciesRecursively: false
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
// strictExecutionOrder deliberately has no plugin default. When an application enables it through normal
|
|
83
|
+
// Rolldown output options, the generated helper runtime becomes amphibious: CommonJS evaluates it once and
|
|
84
|
+
// transport publishes that cached namespace to SystemJS.
|
|
85
|
+
/** Preserves exact native shell paths while hashing transport and explicit capsule entries. */
|
|
86
|
+
entryFileNames(chunk) {
|
|
87
|
+
return getWxExecutionKind(chunk) === 'native' && !isTransportModule(chunk)
|
|
88
|
+
? '[name]'
|
|
89
|
+
: 'assets/[name]-[hash].js';
|
|
90
|
+
},
|
|
91
|
+
/** Converts the planned owner into its physical main or generated subpackage filename template. */
|
|
92
|
+
chunkFileNames(chunk) {
|
|
93
|
+
const location = getChunkLocation(chunk);
|
|
94
|
+
if (location.kind === 'main') {
|
|
95
|
+
return 'assets/[name]-[hash].js';
|
|
96
|
+
}
|
|
97
|
+
// The containing subpackage already supplies a stable identity. Do not leak the Rolldown group name
|
|
98
|
+
// into every physical chunk filename; content identity alone is sufficient beneath that root.
|
|
99
|
+
return `${location.root}/assets/[hash].js`;
|
|
100
|
+
},
|
|
101
|
+
// Keep generic assets independent of stylesheet conventions. The CSS adapter sees Tailwind's final
|
|
102
|
+
// mutation and owns the exact global `app.wxss` identity without confusing native Page companions.
|
|
103
|
+
assetFileNames: 'assets/[name]-[hash][extname]'
|
|
104
|
+
},
|
|
105
|
+
// Rolldown rejects strict entry signatures when code-splitting groups disable recursive dependency capture.
|
|
106
|
+
// allow-extension retains required native-entry exports while permitting the extra cross-chunk bindings used
|
|
107
|
+
// to split lazy static closures across physical packages.
|
|
108
|
+
preserveEntrySignatures: 'allow-extension'
|
|
109
|
+
},
|
|
110
|
+
/**
|
|
111
|
+
* Selects loading mode from physical output rather than graph intent. Transport executes in main, so main files
|
|
112
|
+
* use require() and every generated subpackage file uses require.async().
|
|
113
|
+
*/
|
|
114
|
+
getLoadMode(chunk) {
|
|
115
|
+
return isGeneratedSubpackageFile(chunk.fileName) ? 'async' : 'sync';
|
|
116
|
+
},
|
|
117
|
+
/**
|
|
118
|
+
* Reconciles planned ownership with final chunks through module IDs. Tree-shaken subpackages disappear naturally,
|
|
119
|
+
* while roots are deduplicated and sorted before becoming deterministic app.json declarations.
|
|
120
|
+
*/
|
|
121
|
+
getSubpackages(bundle) {
|
|
122
|
+
const emittedSubpackageRoots = new Set();
|
|
123
|
+
for (const output of Object.values(bundle)) {
|
|
124
|
+
if (output.type !== 'chunk') {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
for (const moduleId of output.moduleIds) {
|
|
128
|
+
const location = plan.get(moduleId);
|
|
129
|
+
if (location?.kind === 'subpackage') {
|
|
130
|
+
emittedSubpackageRoots.add(location.root);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return [...emittedSubpackageRoots].sort().map((root) => ({
|
|
135
|
+
name: getSubpackageName(root),
|
|
136
|
+
root,
|
|
137
|
+
pages: []
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/** Compares main by discriminant and generated subpackages by their unique physical root. */
|
|
143
|
+
function hasSameLocation(left, right) {
|
|
144
|
+
return left.kind === 'main' ? right.kind === 'main' : right.kind === 'subpackage' && left.root === right.root;
|
|
145
|
+
}
|