@blocklet/pages-kit-block-studio 0.6.1 โ 0.6.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.
- package/lib/cjs/middlewares/init-resource-router.js +35 -0
- package/lib/cjs/middlewares/init-uploader-router.js +0 -3
- package/lib/cjs/plugins/_theme.js +3 -2
- package/lib/cjs/plugins/vite-plugin-block-studio.js +5 -125
- package/lib/cjs/plugins/vite-plugin-code-splitter.js +594 -246
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/helper.js +17 -3
- package/lib/esm/middlewares/init-resource-router.js +36 -1
- package/lib/esm/middlewares/init-uploader-router.js +0 -3
- package/lib/esm/plugins/_theme.js +5 -4
- package/lib/esm/plugins/vite-plugin-block-studio.js +6 -126
- package/lib/esm/plugins/vite-plugin-code-splitter.js +562 -247
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/helper.js +13 -2
- package/lib/types/plugins/vite-plugin-block-studio.d.ts +0 -1
- package/lib/types/plugins/vite-plugin-code-splitter.d.ts +8 -4
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/lib/types/utils/helper.d.ts +6 -1
- package/package.json +5 -5
|
@@ -1,194 +1,274 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
39
|
exports.vitePluginCodeSplitter = vitePluginCodeSplitter;
|
|
7
|
-
|
|
8
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Vite Plugin: Component Code Splitter
|
|
42
|
+
*
|
|
43
|
+
* ๐ WORKFLOW OVERVIEW:
|
|
44
|
+
*
|
|
45
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
46
|
+
* โ PLUGIN 1: CODE SPLITTER โ
|
|
47
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
48
|
+
*
|
|
49
|
+
* ๐ Phase 1: Config Stage
|
|
50
|
+
* โโโ Analyze entry files to find all exports
|
|
51
|
+
* โโโ Detect: default, EditComponent, PropertiesSchema, GetServerSideProps
|
|
52
|
+
* โโโ Create separate entry points for each export:
|
|
53
|
+
* โข Component โ Component?exportName=default&target=browser
|
|
54
|
+
* โข EditComponent โ Component_EditComponent?exportName=EditComponent&target=browser
|
|
55
|
+
* โข GetServerSideProps โ Component_GetServerSideProps?exportName=GetServerSideProps&target=node
|
|
56
|
+
*
|
|
57
|
+
* ๐ Phase 2: Resolve & Load Stage
|
|
58
|
+
* โโโ resolveId: Identify virtual modules with ?exportName= params
|
|
59
|
+
* โโโ load: Transform code and split exports
|
|
60
|
+
* โโโ Use esbuild for fast transformation
|
|
61
|
+
* โโโ Apply tree-shaking to remove unused code
|
|
62
|
+
* โโโ Filter to keep only specified exports
|
|
63
|
+
*
|
|
64
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
65
|
+
* โ PLUGIN 2: POST-BUILD PROCESSING โ
|
|
66
|
+
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
67
|
+
*
|
|
68
|
+
* ๐ง Phase 3: Post-Build Optimization
|
|
69
|
+
* โโโ Scan generated files and classify by target:
|
|
70
|
+
* โ โโโ Node.js Target: GetServerSideProps functions
|
|
71
|
+
* โ โโโ Browser Target: Components, EditComponents, Schemas
|
|
72
|
+
* โโโ Node.js files: Re-bundle with esbuild (platform: node, format: cjs)
|
|
73
|
+
* โโโ Browser files: Transpile with TypeScript + builtin module transformer
|
|
74
|
+
* โโโ Generate dependency mapping (chunks-map.json)
|
|
75
|
+
*
|
|
76
|
+
* ๐ก WHY THIS DESIGN:
|
|
77
|
+
* โข Reduces bundle size by splitting unused exports
|
|
78
|
+
* โข Optimizes for different runtime environments (browser vs node)
|
|
79
|
+
* โข Enables selective loading in Component Studio
|
|
80
|
+
* โข Maintains clean separation between edit-time and runtime code
|
|
81
|
+
*/
|
|
82
|
+
const builtin_1 = require("@blocklet/pages-kit/utils/builtin");
|
|
83
|
+
const builtin_module_transformer_1 = require("@blocklet/pages-kit/utils/typescript/builtin-module-transformer");
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
const chunks_analyzer_transformer_1 = require("@blocklet/pages-kit/utils/typescript/chunks-analyzer-transformer");
|
|
86
|
+
const esbuild = __importStar(require("esbuild"));
|
|
87
|
+
const fs_1 = __importStar(require("fs"));
|
|
88
|
+
const p_limit_1 = __importDefault(require("p-limit"));
|
|
89
|
+
const path_1 = __importStar(require("path"));
|
|
9
90
|
const typescript_1 = __importDefault(require("typescript"));
|
|
10
91
|
const constants_1 = require("../constants");
|
|
11
92
|
const helper_1 = require("../utils/helper");
|
|
93
|
+
const minify = true;
|
|
12
94
|
/**
|
|
13
|
-
*
|
|
14
|
-
* @param sourceFile TypeScriptๆบๆไปถ
|
|
95
|
+
* ๅฏผๅบ้
็ฝฎ
|
|
15
96
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
97
|
+
const EXPORT_CONFIGS = [
|
|
98
|
+
{
|
|
99
|
+
exportName: 'default',
|
|
100
|
+
getBlockName: (key) => `${key}`,
|
|
101
|
+
description: 'Default',
|
|
102
|
+
supportSeparateFile: false,
|
|
103
|
+
target: 'browser',
|
|
104
|
+
external: [],
|
|
105
|
+
},
|
|
106
|
+
// {
|
|
107
|
+
// exportName: 'default',
|
|
108
|
+
// getBlockName: (key) => `${key}(default)`,
|
|
109
|
+
// description: 'Default CJS',
|
|
110
|
+
// supportSeparateFile: false,
|
|
111
|
+
// target: 'node',
|
|
112
|
+
// external: [],
|
|
113
|
+
// },
|
|
114
|
+
{
|
|
115
|
+
exportName: helper_1.EDIT_COMPONENT_NAME,
|
|
116
|
+
getBlockName: helper_1.getEditComponentBlockName,
|
|
117
|
+
description: 'EditComponent',
|
|
118
|
+
supportSeparateFile: true, // ๆฏๆ็ฌ็ซ็ @edit-component ๆไปถ
|
|
119
|
+
target: 'browser', // ๅ็ซฏ็ปไปถ
|
|
120
|
+
external: [],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
exportName: helper_1.PROPERTIES_SCHEMA_NAME,
|
|
124
|
+
getBlockName: helper_1.getPropertiesSchemaBlockName,
|
|
125
|
+
description: 'PropertiesSchema',
|
|
126
|
+
supportSeparateFile: false,
|
|
127
|
+
target: 'browser', // ๅ็ซฏ schema
|
|
128
|
+
external: [],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
exportName: helper_1.AIGNE_OUTPUT_VALUE_SCHEMA_NAME,
|
|
132
|
+
getBlockName: helper_1.getAigneOutputValueSchemaBlockName,
|
|
133
|
+
description: 'AigneOutputValueSchema',
|
|
134
|
+
supportSeparateFile: false,
|
|
135
|
+
target: 'browser', // ๅ็ซฏ schema
|
|
136
|
+
external: [],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
exportName: helper_1.GET_SERVER_SIDE_PROPS_NAME,
|
|
140
|
+
getBlockName: helper_1.getGetServerSidePropsBlockName,
|
|
141
|
+
description: 'GetServerSideProps',
|
|
142
|
+
supportSeparateFile: false,
|
|
143
|
+
target: 'node', // ๆๅก็ซฏๅฝๆฐ
|
|
144
|
+
format: 'esm', // esm ๆ ผๅผ
|
|
145
|
+
// ๆ้ค็ไพ่ต, ้่ฆ่ทๅ็ซฏไฟๆไธ่ด
|
|
146
|
+
external: [...Object.keys(builtin_1.BuiltinModules)],
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
/**
|
|
150
|
+
* ๅๆ็ปไปถๆไปถไธญ็ๆๆๅฏผๅบ
|
|
151
|
+
*/
|
|
152
|
+
function analyzeAllExports(sourceFile) {
|
|
153
|
+
const result = {
|
|
154
|
+
namedExports: new Map(),
|
|
155
|
+
exportDeclarations: [],
|
|
156
|
+
};
|
|
19
157
|
function visit(node) {
|
|
20
|
-
//
|
|
21
|
-
if (typescript_1.default.isExportAssignment(node)) {
|
|
22
|
-
result.defaultExport = {
|
|
23
|
-
pos: node.pos,
|
|
24
|
-
end: node.end,
|
|
25
|
-
};
|
|
158
|
+
// ้ป่ฎคๅฏผๅบ - export default xxx
|
|
159
|
+
if (typescript_1.default.isExportAssignment(node) && !node.isExportEquals) {
|
|
160
|
+
result.defaultExport = { pos: node.pos, end: node.end };
|
|
26
161
|
}
|
|
27
|
-
//
|
|
162
|
+
// ๅฝๆฐๅฃฐๆ็้ป่ฎคๅฏผๅบ - export default function
|
|
28
163
|
if (typescript_1.default.isFunctionDeclaration(node) && node.modifiers) {
|
|
29
164
|
const isExport = node.modifiers.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
30
165
|
const isDefault = node.modifiers.some((m) => m.kind === typescript_1.default.SyntaxKind.DefaultKeyword);
|
|
31
166
|
if (isExport && isDefault) {
|
|
32
|
-
result.defaultExport = {
|
|
33
|
-
pos: node.pos,
|
|
34
|
-
end: node.end,
|
|
35
|
-
};
|
|
167
|
+
result.defaultExport = { pos: node.pos, end: node.end };
|
|
36
168
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
result.
|
|
40
|
-
pos: node.pos,
|
|
41
|
-
end: node.end,
|
|
42
|
-
};
|
|
169
|
+
else if (isExport && !isDefault && node.name) {
|
|
170
|
+
// ๅฝๅๅฏผๅบ็ๅฝๆฐ - export function xxx
|
|
171
|
+
result.namedExports.set(node.name.text, { pos: node.pos, end: node.end });
|
|
43
172
|
}
|
|
44
173
|
}
|
|
45
|
-
//
|
|
174
|
+
// ็ฑปๅฃฐๆ็ๅฏผๅบ
|
|
46
175
|
if (typescript_1.default.isClassDeclaration(node) && node.modifiers) {
|
|
47
176
|
const isExport = node.modifiers.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
result.editComponent = {
|
|
51
|
-
pos: node.pos,
|
|
52
|
-
end: node.end,
|
|
53
|
-
};
|
|
177
|
+
if (isExport && node.name) {
|
|
178
|
+
result.namedExports.set(node.name.text, { pos: node.pos, end: node.end });
|
|
54
179
|
}
|
|
55
180
|
}
|
|
56
|
-
//
|
|
181
|
+
// ๅ้ๅฃฐๆ็ๅฏผๅบ - export const xxx
|
|
57
182
|
if (typescript_1.default.isVariableStatement(node) && node.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword)) {
|
|
58
183
|
const { declarations } = node.declarationList;
|
|
59
184
|
for (const decl of declarations) {
|
|
60
|
-
if (typescript_1.default.isIdentifier(decl.name)
|
|
61
|
-
result.
|
|
62
|
-
pos: node.pos,
|
|
63
|
-
end: node.end,
|
|
64
|
-
};
|
|
65
|
-
break;
|
|
185
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
186
|
+
result.namedExports.set(decl.name.text, { pos: node.pos, end: node.end });
|
|
66
187
|
}
|
|
67
188
|
}
|
|
68
189
|
}
|
|
69
|
-
//
|
|
70
|
-
if (typescript_1.default.isExportDeclaration(node)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
pos: node.pos,
|
|
79
|
-
end: node.end,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
// ๅค็ๅฏผๅบ็็ฎญๅคดๅฝๆฐ/ๅฝๆฐ่กจ่พพๅผ
|
|
85
|
-
if (typescript_1.default.isVariableStatement(node)) {
|
|
86
|
-
const { declarations } = node.declarationList;
|
|
87
|
-
for (const decl of declarations) {
|
|
88
|
-
if (typescript_1.default.isIdentifier(decl.name) && decl.name.text === helper_1.EDIT_COMPONENT_NAME) {
|
|
89
|
-
if (node.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword)) {
|
|
90
|
-
result.editComponent = {
|
|
91
|
-
pos: node.pos,
|
|
92
|
-
end: node.end,
|
|
93
|
-
};
|
|
94
|
-
break;
|
|
190
|
+
// ๅฏผๅบๅฃฐๆ - export { xxx, yyy }
|
|
191
|
+
if (typescript_1.default.isExportDeclaration(node)) {
|
|
192
|
+
result.exportDeclarations.push({ pos: node.pos, end: node.end });
|
|
193
|
+
if (node.exportClause && typescript_1.default.isNamedExports(node.exportClause)) {
|
|
194
|
+
// ่ฎฐๅฝ่ฟไธชๅฏผๅบๅฃฐๆๅ
ๅซ็ๆๆๅฏผๅบๅ
|
|
195
|
+
node.exportClause.elements.forEach((element) => {
|
|
196
|
+
if (typescript_1.default.isExportSpecifier(element)) {
|
|
197
|
+
const exportName = element.propertyName ? element.name.text : element.name.text;
|
|
198
|
+
result.namedExports.set(exportName, { pos: node.pos, end: node.end });
|
|
95
199
|
}
|
|
96
|
-
}
|
|
200
|
+
});
|
|
97
201
|
}
|
|
98
202
|
}
|
|
99
|
-
// ้ๅฝๅค็ๆๆๅญ่็น
|
|
100
203
|
typescript_1.default.forEachChild(node, visit);
|
|
101
204
|
}
|
|
102
|
-
// ๅผๅง้ๅ
|
|
103
205
|
visit(sourceFile);
|
|
104
206
|
return result;
|
|
105
207
|
}
|
|
106
208
|
/**
|
|
107
|
-
*
|
|
209
|
+
* ่งฃๆ exportName ๅๆฐ
|
|
108
210
|
*/
|
|
109
|
-
function
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (renderType === 'view') {
|
|
115
|
-
// ็งป้ค EditComponent
|
|
116
|
-
if (analysis.editComponent) {
|
|
117
|
-
// ๆ นๆฎไฝ็ฝฎๆฟๆขไธบ็ฉบๅ
ๅฎน
|
|
118
|
-
const beforeEdit = code.substring(0, analysis.editComponent.pos);
|
|
119
|
-
const afterEdit = code.substring(analysis.editComponent.end);
|
|
120
|
-
return beforeEdit + afterEdit;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else if (renderType === 'setting') {
|
|
124
|
-
// ็งป้คๆๆฟๆข้ป่ฎคๅฏผๅบ๏ผ็ดๆฅๅฏผๅบEditComponent
|
|
125
|
-
if (analysis.defaultExport && analysis.editComponent) {
|
|
126
|
-
// ็ผ่พๆจกๅผ๏ผไฟๆๅฝๅๅฏผๅบ๏ผไฝ่ฎฉEditComponentๅๆถไนไฝไธบ้ป่ฎคๅฏผๅบ
|
|
127
|
-
const defaultExport = `
|
|
128
|
-
// Export EditComponent as both named export and default
|
|
129
|
-
export { ${helper_1.EDIT_COMPONENT_NAME} as default };
|
|
130
|
-
`;
|
|
131
|
-
const beforeDefault = code.substring(0, analysis.defaultExport.pos);
|
|
132
|
-
const afterDefault = code.substring(analysis.defaultExport.end);
|
|
133
|
-
// ๆฟๆข้ป่ฎคๅฏผๅบไธบEditComponent
|
|
134
|
-
return beforeDefault + defaultExport + afterDefault;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
// ๅฆๆๆฒกๆ่ฟ่กไฟฎๆน๏ผ่ฟๅๅๅงไปฃ็
|
|
138
|
-
return code;
|
|
211
|
+
function parseExportNames(exportNameParam) {
|
|
212
|
+
return exportNameParam
|
|
213
|
+
.split(',')
|
|
214
|
+
.map((name) => name.trim())
|
|
215
|
+
.filter(Boolean);
|
|
139
216
|
}
|
|
140
217
|
/**
|
|
141
|
-
*
|
|
218
|
+
* ่ฝฌๆขไปฃ็ ๏ผๅชไฟ็ๆๅฎ็ๅฏผๅบ
|
|
142
219
|
*/
|
|
143
|
-
function
|
|
220
|
+
function transformCodeWithExports(code, exportNames) {
|
|
144
221
|
try {
|
|
145
|
-
// ๅๅปบๆบๆไปถ
|
|
146
222
|
const sourceFile = typescript_1.default.createSourceFile('temp.tsx', code, typescript_1.default.ScriptTarget.Latest, true);
|
|
147
|
-
//
|
|
223
|
+
// ๆ ๅๅๅฏผๅบๅ็งฐ๏ผdefault ๅค็๏ผ
|
|
224
|
+
const normalizedExportNames = new Set(exportNames.map((name) => (name === 'default' ? 'default' : name)));
|
|
148
225
|
const transformerFactory = (context) => {
|
|
149
226
|
return (sourceFile) => {
|
|
150
|
-
// ่ฎฟ้ฎๅนถ่ฝฌๆข่็น
|
|
151
227
|
const visitor = (node) => {
|
|
152
|
-
//
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
228
|
+
// ๅค็้ป่ฎคๅฏผๅบ
|
|
229
|
+
if (typescript_1.default.isExportAssignment(node) && !node.isExportEquals) {
|
|
230
|
+
return normalizedExportNames.has('default') ? node : typescript_1.default.factory.createEmptyStatement();
|
|
231
|
+
}
|
|
232
|
+
// ๅค็ๅฝๆฐ/็ฑป็้ป่ฎคๅฏผๅบ
|
|
233
|
+
if (typescript_1.default.isFunctionDeclaration(node) && node.modifiers) {
|
|
234
|
+
const isExport = node.modifiers.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
235
|
+
const isDefault = node.modifiers.some((m) => m.kind === typescript_1.default.SyntaxKind.DefaultKeyword);
|
|
236
|
+
if (isExport && isDefault) {
|
|
237
|
+
return normalizedExportNames.has('default') ? node : typescript_1.default.factory.createEmptyStatement();
|
|
160
238
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const { elements } = node.exportClause;
|
|
164
|
-
if (elements.some((e) => typescript_1.default.isExportSpecifier(e) && e.name.text === helper_1.EDIT_COMPONENT_NAME)) {
|
|
165
|
-
// ๅฆๆๅชๆEditComponentไธไธชๅฏผๅบ๏ผๅฐฑๅฎๅ
จ็งป้ค
|
|
166
|
-
if (elements.length === 1) {
|
|
167
|
-
return typescript_1.default.factory.createEmptyStatement();
|
|
168
|
-
}
|
|
169
|
-
// ๅฆๅๅๅปบๆฐ็ๅฏผๅบๅฃฐๆ๏ผไฝไธๅ
ๅซEditComponent
|
|
170
|
-
const newElements = elements.filter((e) => !(typescript_1.default.isExportSpecifier(e) && e.name.text === helper_1.EDIT_COMPONENT_NAME));
|
|
171
|
-
return typescript_1.default.factory.createExportDeclaration(node.modifiers, node.isTypeOnly, typescript_1.default.factory.createNamedExports(newElements), node.moduleSpecifier);
|
|
172
|
-
}
|
|
239
|
+
if (isExport && !isDefault && node.name) {
|
|
240
|
+
return normalizedExportNames.has(node.name.text) ? node : typescript_1.default.factory.createEmptyStatement();
|
|
173
241
|
}
|
|
174
242
|
}
|
|
175
|
-
//
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
243
|
+
// ๅค็็ฑปๅฃฐๆ็ๅฏผๅบ
|
|
244
|
+
if (typescript_1.default.isClassDeclaration(node) && node.modifiers) {
|
|
245
|
+
const isExport = node.modifiers.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword);
|
|
246
|
+
if (isExport && node.name) {
|
|
247
|
+
return normalizedExportNames.has(node.name.text) ? node : typescript_1.default.factory.createEmptyStatement();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// ๅค็ๅ้ๅฃฐๆ็ๅฏผๅบ
|
|
251
|
+
if (typescript_1.default.isVariableStatement(node) && node.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.ExportKeyword)) {
|
|
252
|
+
const { declarations } = node.declarationList;
|
|
253
|
+
const shouldKeep = declarations.some((decl) => typescript_1.default.isIdentifier(decl.name) && normalizedExportNames.has(decl.name.text));
|
|
254
|
+
return shouldKeep ? node : typescript_1.default.factory.createEmptyStatement();
|
|
255
|
+
}
|
|
256
|
+
// ๅค็ๅฏผๅบๅฃฐๆ - export { xxx, yyy }
|
|
257
|
+
if (typescript_1.default.isExportDeclaration(node) && node.exportClause && typescript_1.default.isNamedExports(node.exportClause)) {
|
|
258
|
+
const { elements } = node.exportClause;
|
|
259
|
+
const keptElements = elements.filter((element) => {
|
|
260
|
+
if (typescript_1.default.isExportSpecifier(element)) {
|
|
261
|
+
const exportName = element.propertyName ? element.name.text : element.name.text;
|
|
262
|
+
return normalizedExportNames.has(exportName);
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
});
|
|
266
|
+
if (keptElements.length === 0) {
|
|
267
|
+
return typescript_1.default.factory.createEmptyStatement();
|
|
183
268
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
node.modifiers
|
|
187
|
-
node.modifiers?.some((m) => m.kind === typescript_1.default.SyntaxKind.DefaultKeyword)) {
|
|
188
|
-
// ๅๅปบๆฐ็้ป่ฎคๅฏผๅบ๏ผๅฏผๅบEditComponentไฝไธบdefault
|
|
189
|
-
return typescript_1.default.factory.createExportDeclaration(undefined, false, typescript_1.default.factory.createNamedExports([
|
|
190
|
-
typescript_1.default.factory.createExportSpecifier(false, typescript_1.default.factory.createIdentifier(helper_1.EDIT_COMPONENT_NAME), typescript_1.default.factory.createIdentifier('default')),
|
|
191
|
-
]));
|
|
269
|
+
if (keptElements.length < elements.length) {
|
|
270
|
+
// ๅๅปบๆฐ็ๅฏผๅบๅฃฐๆ๏ผๅชๅ
ๅซ้่ฆไฟ็็ๅฏผๅบ
|
|
271
|
+
return typescript_1.default.factory.createExportDeclaration(node.modifiers, node.isTypeOnly, typescript_1.default.factory.createNamedExports(keptElements), node.moduleSpecifier);
|
|
192
272
|
}
|
|
193
273
|
}
|
|
194
274
|
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
@@ -201,10 +281,9 @@ function transformCodeWithPrinter(code, renderType) {
|
|
|
201
281
|
const printer = typescript_1.default.createPrinter({ newLine: typescript_1.default.NewLineKind.LineFeed });
|
|
202
282
|
if (result.transformed.length > 0) {
|
|
203
283
|
const transformedSourceFile = result.transformed[0];
|
|
204
|
-
// TypeScript ็ฑปๅไฟ่ฏ
|
|
205
284
|
if (transformedSourceFile) {
|
|
206
285
|
const transformedCode = printer.printFile(transformedSourceFile);
|
|
207
|
-
result.dispose();
|
|
286
|
+
result.dispose();
|
|
208
287
|
return transformedCode;
|
|
209
288
|
}
|
|
210
289
|
}
|
|
@@ -212,40 +291,68 @@ function transformCodeWithPrinter(code, renderType) {
|
|
|
212
291
|
return code;
|
|
213
292
|
}
|
|
214
293
|
catch (error) {
|
|
215
|
-
helper_1.logger.error('Error transforming with
|
|
216
|
-
|
|
217
|
-
|
|
294
|
+
helper_1.logger.error('Error transforming with exports:', error);
|
|
295
|
+
return code;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* ็ฎๅ็ไปฃ็ ่ฝฌๆข๏ผ้่ฟๅญ็ฌฆไธฒๆฟๆข๏ผfallback๏ผ
|
|
300
|
+
*/
|
|
301
|
+
function transformCodeSimple(code, exportNames) {
|
|
302
|
+
const sourceFile = typescript_1.default.createSourceFile('temp.tsx', code, typescript_1.default.ScriptTarget.Latest, true);
|
|
303
|
+
const analysis = analyzeAllExports(sourceFile);
|
|
304
|
+
const normalizedExportNames = new Set(exportNames.map((name) => (name === 'default' ? 'default' : name)));
|
|
305
|
+
let result = code;
|
|
306
|
+
const toRemove = [];
|
|
307
|
+
// ๆถ้้่ฆ็งป้ค็่็น
|
|
308
|
+
if (analysis.defaultExport && !normalizedExportNames.has('default')) {
|
|
309
|
+
toRemove.push(analysis.defaultExport);
|
|
310
|
+
}
|
|
311
|
+
analysis.namedExports.forEach((range, name) => {
|
|
312
|
+
if (!normalizedExportNames.has(name)) {
|
|
313
|
+
toRemove.push(range);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
// ๆไฝ็ฝฎๅๅบๆๅ๏ผ้ฟๅ
ไฝ็ฝฎๅ็งป
|
|
317
|
+
toRemove.sort((a, b) => b.pos - a.pos);
|
|
318
|
+
// ็งป้คไธ้่ฆ็ๅฏผๅบ
|
|
319
|
+
for (const range of toRemove) {
|
|
320
|
+
const before = result.substring(0, range.pos);
|
|
321
|
+
const after = result.substring(range.end);
|
|
322
|
+
result = before + after;
|
|
218
323
|
}
|
|
324
|
+
return result;
|
|
219
325
|
}
|
|
220
326
|
/**
|
|
221
|
-
*
|
|
327
|
+
* ่ทๅๆไปถไธญ็ๆๆๅฏผๅบๅ็งฐ
|
|
222
328
|
*/
|
|
223
|
-
function
|
|
329
|
+
function getFileExports(filePath) {
|
|
224
330
|
try {
|
|
225
331
|
if (!fs_1.default.existsSync(filePath)) {
|
|
226
|
-
return
|
|
332
|
+
return [];
|
|
227
333
|
}
|
|
228
|
-
// ่ฏปๅๆไปถๅ
ๅฎน
|
|
229
334
|
const content = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
230
|
-
// ๅๅปบๆบๆไปถ
|
|
231
335
|
const sourceFile = typescript_1.default.createSourceFile(filePath, content, typescript_1.default.ScriptTarget.Latest, true);
|
|
232
|
-
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
336
|
+
const analysis = analyzeAllExports(sourceFile);
|
|
337
|
+
const exports = [];
|
|
338
|
+
if (analysis.defaultExport) {
|
|
339
|
+
exports.push('default');
|
|
340
|
+
}
|
|
341
|
+
exports.push(...Array.from(analysis.namedExports.keys()));
|
|
342
|
+
return exports;
|
|
236
343
|
}
|
|
237
344
|
catch (error) {
|
|
238
|
-
helper_1.logger.warn(`Error
|
|
239
|
-
return
|
|
345
|
+
helper_1.logger.warn(`Error analyzing exports in ${filePath}:`, error);
|
|
346
|
+
return [];
|
|
240
347
|
}
|
|
241
348
|
}
|
|
242
|
-
|
|
349
|
+
/**
|
|
350
|
+
* ๆฃๆฅ็ฎๅฝไธญๆฏๅฆๅญๅจ@edit-componentๆไปถ
|
|
351
|
+
*/
|
|
243
352
|
function findEditComponentFileInDir(filePath) {
|
|
244
353
|
const dirPath = path_1.default.dirname(filePath);
|
|
245
|
-
// ่ทๅ็ฎๅฝไธญ็ๆๆๆไปถ
|
|
246
354
|
try {
|
|
247
355
|
const files = fs_1.default.readdirSync(dirPath);
|
|
248
|
-
// ๆฃๆฅๆฏๅฆๆๅน้
็ๆไปถ
|
|
249
356
|
const file = files.find((file) => constants_1.EDIT_COMPONENT_FILE_NAME_REGEX.test(file));
|
|
250
357
|
if (file) {
|
|
251
358
|
return path_1.default.join(dirPath, file);
|
|
@@ -258,105 +365,346 @@ function findEditComponentFileInDir(filePath) {
|
|
|
258
365
|
}
|
|
259
366
|
}
|
|
260
367
|
/**
|
|
261
|
-
* Vite
|
|
262
|
-
*
|
|
368
|
+
* ๐ฏ MAIN EXPORT: Vite Plugin Factory
|
|
369
|
+
* Creates two plugins that work together to split and optimize component code
|
|
263
370
|
*/
|
|
264
|
-
function vitePluginCodeSplitter() {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
371
|
+
function vitePluginCodeSplitter(options) {
|
|
372
|
+
const formats = options?.formats || ['es', 'cjs'];
|
|
373
|
+
const transpileBuiltinModule = options?.transpileBuiltinModule ?? true;
|
|
374
|
+
const skipBundleNodeTarget = options?.skipBundleNodeTarget ?? false;
|
|
375
|
+
return [
|
|
376
|
+
// ๐ง PLUGIN 1: CODE SPLITTER & TRANSFORMER
|
|
377
|
+
{
|
|
378
|
+
name: 'vite-plugin-code-splitter',
|
|
379
|
+
/**
|
|
380
|
+
* ๐ PHASE 1: CONFIG STAGE
|
|
381
|
+
* Analyzes entry files and creates separate entry points for each export type
|
|
382
|
+
*/
|
|
383
|
+
config(config) {
|
|
384
|
+
if (config.build && config.build.lib && typeof config.build.lib === 'object') {
|
|
385
|
+
const libConfig = config.build.lib;
|
|
386
|
+
if (libConfig.entry && typeof libConfig.entry === 'object' && !Array.isArray(libConfig.entry)) {
|
|
387
|
+
const newEntry = {};
|
|
388
|
+
Object.entries(libConfig.entry).forEach(([key, filePath]) => {
|
|
389
|
+
if (typeof filePath === 'string') {
|
|
390
|
+
try {
|
|
391
|
+
// ๅๆๆไปถไธญ็ๆๆๅฏผๅบ
|
|
392
|
+
const exports = getFileExports(filePath);
|
|
393
|
+
const fileName = path_1.default.basename(filePath);
|
|
394
|
+
helper_1.logger.info(`Found exports in ${fileName}: ${exports.join(', ')}`);
|
|
395
|
+
// ๅค็ๆๆ้
็ฝฎ็ๅฏผๅบ็ฑปๅ
|
|
396
|
+
EXPORT_CONFIGS.forEach(({ exportName, getBlockName, description, supportSeparateFile, target }) => {
|
|
397
|
+
if (exports.includes(exportName)) {
|
|
398
|
+
newEntry[getBlockName(key)] = `${filePath}?exportName=${exportName}&target=${target}`;
|
|
399
|
+
helper_1.logger.debug(`Added ${description} entry for ${fileName} (target: ${target})`);
|
|
400
|
+
}
|
|
401
|
+
else if (supportSeparateFile && exportName === helper_1.EDIT_COMPONENT_NAME) {
|
|
402
|
+
// ๆฃๆฅๆฏๅฆๆ็ฌ็ซ็ @edit-component ๆไปถ
|
|
403
|
+
const editComponentFile = findEditComponentFileInDir(filePath);
|
|
404
|
+
if (editComponentFile) {
|
|
405
|
+
const editExports = getFileExports(editComponentFile);
|
|
406
|
+
if (editExports.includes(helper_1.EDIT_COMPONENT_NAME)) {
|
|
407
|
+
newEntry[(0, helper_1.getEditComponentBlockName)(key)] =
|
|
408
|
+
`${editComponentFile}?exportName=${helper_1.EDIT_COMPONENT_NAME}&target=${target}`;
|
|
409
|
+
helper_1.logger.info(`Found separate @edit-component file for ${path_1.default.basename(editComponentFile)} (target: ${target})`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
});
|
|
288
414
|
}
|
|
289
|
-
|
|
290
|
-
helper_1.logger.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if (editComponentFilePath) {
|
|
294
|
-
hasEditComponent = true;
|
|
295
|
-
helper_1.logger.info(`Found separate @edit-component file for ${editComponentFilePath}`);
|
|
296
|
-
}
|
|
415
|
+
catch (err) {
|
|
416
|
+
helper_1.logger.warn(`Failed to analyze exports in ${filePath}: ${err}`);
|
|
417
|
+
// fallback ๅฐๅๅงๆไปถ
|
|
418
|
+
newEntry[key] = filePath;
|
|
297
419
|
}
|
|
298
420
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
newEntry[key] = `${filePath}?renderType=view`;
|
|
304
|
-
// ๅชไธบๅ
ๅซEditComponent็ๆไปถๅๅปบ็ผ่พๅ
ฅๅฃ
|
|
305
|
-
if (hasEditComponent) {
|
|
306
|
-
newEntry[(0, helper_1.getEditComponentBlockName)(key)] = `${editComponentFilePath}?renderType=setting`;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
// ๆดๆฐ้
็ฝฎ
|
|
311
|
-
libConfig.entry = newEntry;
|
|
312
|
-
helper_1.logger.info('Auto-split components enabled, entries updated');
|
|
421
|
+
});
|
|
422
|
+
libConfig.entry = newEntry;
|
|
423
|
+
helper_1.logger.info('Auto-split components enabled with export-based splitting');
|
|
424
|
+
}
|
|
313
425
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
},
|
|
324
|
-
load(id) {
|
|
325
|
-
if (!id.includes('?renderType=')) {
|
|
326
|
-
return null;
|
|
327
|
-
}
|
|
328
|
-
try {
|
|
329
|
-
// ่งฃๆ id๏ผๆๅๆไปถ่ทฏๅพๅๆฅ่ฏขๅๆฐ
|
|
330
|
-
const [filePath, query] = id.split('?');
|
|
331
|
-
const params = new URLSearchParams(query);
|
|
332
|
-
const renderType = params.get('renderType');
|
|
333
|
-
if (!filePath || !renderType || (renderType !== 'view' && renderType !== 'setting')) {
|
|
334
|
-
return null;
|
|
426
|
+
return config;
|
|
427
|
+
},
|
|
428
|
+
/**
|
|
429
|
+
* ๐ PHASE 2A: RESOLVE STAGE
|
|
430
|
+
* Identifies virtual modules with exportName parameters
|
|
431
|
+
*/
|
|
432
|
+
resolveId(id) {
|
|
433
|
+
if (id.includes('?exportName=')) {
|
|
434
|
+
return id; // Mark as resolved to trigger load() for this virtual module
|
|
335
435
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
436
|
+
return null;
|
|
437
|
+
},
|
|
438
|
+
/**
|
|
439
|
+
* ๐ PHASE 2B: LOAD & TRANSFORM STAGE
|
|
440
|
+
* Loads and transforms code, keeping only specified exports
|
|
441
|
+
*/
|
|
442
|
+
async load(id) {
|
|
443
|
+
if (!id.includes('?exportName=')) {
|
|
339
444
|
return null;
|
|
340
445
|
}
|
|
341
|
-
// ่ฏปๅๆไปถๅ
ๅฎน
|
|
342
|
-
const code = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
343
|
-
// ๆ นๆฎๆธฒๆ็ฑปๅ่ฟ่กไปฃ็ ่ฝฌๆข
|
|
344
|
-
// logger.info(`Splitting code for ${renderType}: ${filePath}`);
|
|
345
446
|
try {
|
|
346
|
-
|
|
347
|
-
|
|
447
|
+
const [filePath, query] = id.split('?');
|
|
448
|
+
const params = new URLSearchParams(query);
|
|
449
|
+
const exportNameParam = params.get('exportName');
|
|
450
|
+
const target = params.get('target') || 'browser';
|
|
451
|
+
if (!filePath || !exportNameParam) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
455
|
+
helper_1.logger.error(`File not found: ${filePath}`);
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
const exportNames = parseExportNames(exportNameParam);
|
|
459
|
+
helper_1.logger.debug(`Processing exports [${exportNames.join(', ')}] with esbuild for: ${path_1.default.basename(filePath)} (target: ${target})`);
|
|
460
|
+
try {
|
|
461
|
+
// Use esbuild for transform + tree-shaking in one step
|
|
462
|
+
const result = await esbuild.transform(transformCodeWithExports(fs_1.default.readFileSync(filePath, 'utf-8'), exportNames), {
|
|
463
|
+
loader: path_1.default.extname(filePath).slice(1), // .tsx -> tsx
|
|
464
|
+
target: target === 'node' ? 'node18' : 'es2020',
|
|
465
|
+
platform: target === 'node' ? 'node' : 'browser',
|
|
466
|
+
format: 'esm',
|
|
467
|
+
jsx: 'automatic',
|
|
468
|
+
treeShaking: true,
|
|
469
|
+
minify,
|
|
470
|
+
sourcemap: false,
|
|
471
|
+
});
|
|
472
|
+
const transformedCode = result.code;
|
|
473
|
+
return transformedCode;
|
|
474
|
+
}
|
|
475
|
+
catch (esbuildError) {
|
|
476
|
+
helper_1.logger.warn(`esbuild transform failed, falling back to TypeScript transform: ${esbuildError}`);
|
|
477
|
+
// Fallback to original method
|
|
478
|
+
const code = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
479
|
+
try {
|
|
480
|
+
return transformCodeWithExports(code, exportNames);
|
|
481
|
+
}
|
|
482
|
+
catch (transformError) {
|
|
483
|
+
helper_1.logger.warn(`TypeScript transform also failed, using simple transform: ${transformError}`);
|
|
484
|
+
return transformCodeSimple(code, exportNames);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
348
487
|
}
|
|
349
|
-
catch (
|
|
350
|
-
helper_1.logger.
|
|
351
|
-
// ๅฆๆๅคฑ่ดฅ๏ผๅ้ๅฐๅบๆฌ่ฝฌๆข
|
|
352
|
-
return transformCode(code, renderType);
|
|
488
|
+
catch (error) {
|
|
489
|
+
helper_1.logger.error(`Error processing module ${id}:`, error);
|
|
353
490
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
helper_1.logger.error(`Error processing module ${id}:`, error);
|
|
357
|
-
}
|
|
358
|
-
return null;
|
|
491
|
+
return null;
|
|
492
|
+
},
|
|
359
493
|
},
|
|
360
|
-
|
|
494
|
+
// ๐ ๏ธ PLUGIN 2: POST-BUILD PROCESSOR
|
|
495
|
+
{
|
|
496
|
+
name: 'vite-plugin-code-splitter-post-build',
|
|
497
|
+
apply: 'build',
|
|
498
|
+
enforce: 'post',
|
|
499
|
+
/**
|
|
500
|
+
* ๐ง PHASE 3: POST-BUILD OPTIMIZATION
|
|
501
|
+
* Processes generated files based on their target environment
|
|
502
|
+
*/
|
|
503
|
+
async writeBundle(options) {
|
|
504
|
+
if (!transpileBuiltinModule) {
|
|
505
|
+
helper_1.logger.info('Transpile builtin module is disabled, skipping post-build processing');
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
// ็จไบๅญๅจๆฏไธชๆ ผๅผ็ chunks ๆ ๅฐ
|
|
509
|
+
const allChunksMap = {};
|
|
510
|
+
const getExportConfig = (fileName) => {
|
|
511
|
+
// Extract export type from filename pattern: Component(ExportType).js
|
|
512
|
+
const match = fileName.match(/\(([^)]+)\)\.js$/);
|
|
513
|
+
if (!match || !match[1]) {
|
|
514
|
+
return null; // Regular component file, defaults to browser
|
|
515
|
+
}
|
|
516
|
+
const exportName = match[1];
|
|
517
|
+
return EXPORT_CONFIGS.find((config) => config.exportName === exportName || config.exportName.toLowerCase().includes(exportName.toLowerCase()));
|
|
518
|
+
};
|
|
519
|
+
/**
|
|
520
|
+
* ๐ฏ FILE TYPE CLASSIFIER
|
|
521
|
+
* Determines if a generated file should be treated as Node.js target
|
|
522
|
+
* Examples: Timeline(getServerSideProps).js โ Node.js target
|
|
523
|
+
* Timeline.js โ Browser target
|
|
524
|
+
*/
|
|
525
|
+
const isNodeTargetFile = (fileName) => {
|
|
526
|
+
// Look up target environment in EXPORT_CONFIGS
|
|
527
|
+
const config = getExportConfig(fileName);
|
|
528
|
+
return config?.target === 'node';
|
|
529
|
+
};
|
|
530
|
+
// ๆถ้ๆๆ Node.js ็ฎๆ ๆไปถ๏ผๅๅค้ๆฐๆๅปบ
|
|
531
|
+
const nodeTargetFiles = [];
|
|
532
|
+
// ๆซๆๆๅปบ่พๅบ๏ผๆพๅฐ Node.js ็ฎๆ ๆไปถ
|
|
533
|
+
const scanForNodeFiles = (dir) => {
|
|
534
|
+
const files = (0, fs_1.readdirSync)(dir);
|
|
535
|
+
files.forEach((file) => {
|
|
536
|
+
const filePath = path_1.default.join(dir, file);
|
|
537
|
+
const stats = (0, fs_1.statSync)(filePath);
|
|
538
|
+
if (stats.isDirectory()) {
|
|
539
|
+
scanForNodeFiles(filePath); // ้ๅฝๅค็ๅญ็ฎๅฝ
|
|
540
|
+
}
|
|
541
|
+
else if (file.endsWith('.js') && isNodeTargetFile(file)) {
|
|
542
|
+
helper_1.logger.debug(`Found Node.js target file: ${file}, external: ${getExportConfig(file)?.external?.length ?? 0}`);
|
|
543
|
+
nodeTargetFiles.push({
|
|
544
|
+
filePath,
|
|
545
|
+
external: getExportConfig(file)?.external || [],
|
|
546
|
+
format: getExportConfig(file)?.format,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
};
|
|
551
|
+
formats.forEach((format) => {
|
|
552
|
+
const formatDir = path_1.default.resolve(options.dir || 'dist', `${format}`);
|
|
553
|
+
if ((0, fs_1.existsSync)(formatDir)) {
|
|
554
|
+
scanForNodeFiles(formatDir);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
// ๅฆๆๆ Node.js ็ฎๆ ๆไปถ๏ผไธบๅฎไปฌ้ขๅค่งฆๅ Vite build
|
|
558
|
+
if (nodeTargetFiles.length > 0) {
|
|
559
|
+
helper_1.logger.info(`Found ${nodeTargetFiles.length} Node.js target files, triggering clean Vite build...`);
|
|
560
|
+
await Promise.all(nodeTargetFiles.map(async ({ filePath, external, format }) => {
|
|
561
|
+
try {
|
|
562
|
+
const fileName = path_1.default.basename(filePath, '.js');
|
|
563
|
+
helper_1.logger.debug(`Rebuilding Node.js target file: ${fileName}`);
|
|
564
|
+
// ไฝฟ็จ esbuild ่ฟ่กๅๆไปถๆๅ
|
|
565
|
+
const result = await esbuild.build({
|
|
566
|
+
entryPoints: [filePath],
|
|
567
|
+
bundle: !skipBundleNodeTarget, // ๆฏๅฆๆๅ
ๆๆไพ่ต
|
|
568
|
+
platform: 'node', // Node.js ๅนณๅฐ
|
|
569
|
+
format: format ?? 'cjs', // CommonJS ๆ ผๅผ
|
|
570
|
+
target: 'node18', // Node.js ็ฎๆ ็ๆฌ
|
|
571
|
+
outfile: filePath, // ็ดๆฅ่ฆ็ๅๆไปถ
|
|
572
|
+
allowOverwrite: true, // ๅ
่ฎธ่ฆ็่พๅ
ฅๆไปถ
|
|
573
|
+
external: external ?? [], // ๆ้ค็ไพ่ต
|
|
574
|
+
minify, // ๅฏๅๅฐ 50-70% ๅคงๅฐ
|
|
575
|
+
treeShaking: true, // ๅป้คๆชไฝฟ็จไปฃ็
|
|
576
|
+
sourcemap: false, // ไธ็ๆ sourcemap
|
|
577
|
+
write: true, // ็ดๆฅๅๅ
ฅๆไปถ
|
|
578
|
+
logLevel: 'error', // ๅชๆพ็คบ้่ฏฏ
|
|
579
|
+
// ่งฃๆ JSX ๅ TypeScript
|
|
580
|
+
loader: {
|
|
581
|
+
'.tsx': 'tsx',
|
|
582
|
+
'.ts': 'ts',
|
|
583
|
+
'.jsx': 'jsx',
|
|
584
|
+
'.js': 'js',
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
if (result.errors.length === 0) {
|
|
588
|
+
helper_1.logger.info(`Successfully rebuilt ${fileName} as single CJS file using esbuild`);
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
helper_1.logger.error(`esbuild errors for ${fileName}:`, result.errors);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
catch (error) {
|
|
595
|
+
helper_1.logger.error(`Failed to rebuild Node.js target file ${filePath}:`, error);
|
|
596
|
+
}
|
|
597
|
+
}));
|
|
598
|
+
}
|
|
599
|
+
// ๅฏน็ๆ็ JavaScript ๆไปถ่ฟ่ก transpileModule ๅค็
|
|
600
|
+
const transpileBuiltinModuleFn = (dir, format) => {
|
|
601
|
+
const files = (0, fs_1.readdirSync)(dir);
|
|
602
|
+
files.forEach((file) => {
|
|
603
|
+
const filePath = path_1.default.join(dir, file);
|
|
604
|
+
const stats = (0, fs_1.statSync)(filePath);
|
|
605
|
+
if (stats.isDirectory()) {
|
|
606
|
+
transpileBuiltinModuleFn(filePath, format); // ้ๅฝๅค็ๅญ็ฎๅฝ
|
|
607
|
+
}
|
|
608
|
+
else if (file.endsWith('.js')) {
|
|
609
|
+
try {
|
|
610
|
+
// ่ทณ่ฟ node target ๆไปถ็ transpile
|
|
611
|
+
if (isNodeTargetFile(file)) {
|
|
612
|
+
helper_1.logger.info(`Skipping transpile for Node.js target file: ${file}`);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const script = (0, fs_1.readFileSync)(filePath, 'utf8');
|
|
616
|
+
// @ts-ignore
|
|
617
|
+
const chunks = (0, chunks_analyzer_transformer_1.analyzeFileChunks)(typescript_1.default, script);
|
|
618
|
+
// ensure chunksMap is with all chunks
|
|
619
|
+
allChunksMap[(0, path_1.basename)(filePath)] = new Set(chunks);
|
|
620
|
+
const moduleMap = {
|
|
621
|
+
es: typescript_1.default.ModuleKind.ESNext,
|
|
622
|
+
cjs: typescript_1.default.ModuleKind.CommonJS,
|
|
623
|
+
umd: typescript_1.default.ModuleKind.ESNext,
|
|
624
|
+
};
|
|
625
|
+
const code = typescript_1.default.transpileModule(script, {
|
|
626
|
+
compilerOptions: {
|
|
627
|
+
jsx: typescript_1.default.JsxEmit.React,
|
|
628
|
+
target: typescript_1.default.ScriptTarget.ES2016,
|
|
629
|
+
module: moduleMap[format],
|
|
630
|
+
},
|
|
631
|
+
transformers: {
|
|
632
|
+
// @ts-ignore
|
|
633
|
+
before: [(0, builtin_module_transformer_1.createBuiltinModuleTransformer)(typescript_1.default)],
|
|
634
|
+
},
|
|
635
|
+
}).outputText;
|
|
636
|
+
(0, fs_1.writeFileSync)(filePath, code);
|
|
637
|
+
helper_1.logger.info(`Transpiled browser target file: ${filePath}`);
|
|
638
|
+
}
|
|
639
|
+
catch (error) {
|
|
640
|
+
helper_1.logger.error(`Failed to transpile ${filePath}:`, error);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
// ่ฟๅไธไธช Promise ไปฅไพฟ await
|
|
645
|
+
return new Promise((resolve, reject) => {
|
|
646
|
+
try {
|
|
647
|
+
resolve();
|
|
648
|
+
}
|
|
649
|
+
catch (error) {
|
|
650
|
+
reject(error);
|
|
651
|
+
}
|
|
652
|
+
});
|
|
653
|
+
};
|
|
654
|
+
// ่ทๅ่พๅบ็ฎๅฝ
|
|
655
|
+
const outDir = options.dir || 'dist';
|
|
656
|
+
const limit = (0, p_limit_1.default)(20);
|
|
657
|
+
// ไฝฟ็จ Promise.all ็ญๅพ
ๆๆๆ ผๅผๅค็ๅฎๆ
|
|
658
|
+
await Promise.all(formats.map(async (format) => {
|
|
659
|
+
const formatDir = path_1.default.resolve(outDir, `${format}`);
|
|
660
|
+
const chunkDir = path_1.default.resolve(formatDir, 'chunks');
|
|
661
|
+
// if not exists, create it
|
|
662
|
+
if (!(0, fs_1.existsSync)(chunkDir)) {
|
|
663
|
+
(0, fs_1.mkdirSync)(chunkDir, { recursive: true });
|
|
664
|
+
}
|
|
665
|
+
await limit(() => transpileBuiltinModuleFn(formatDir, format));
|
|
666
|
+
}));
|
|
667
|
+
// ็ฐๅจๅฏไปฅๅค็ๅฎๆดไพ่ต้พ
|
|
668
|
+
helper_1.logger.info('All transpile tasks done, start to handle dependency chain...');
|
|
669
|
+
// ๅจ่ฟ้ๅค็ allChunksMap ็ๅฎๆดไพ่ต้พ
|
|
670
|
+
Object.entries(allChunksMap).forEach(([entryFile, directDeps]) => {
|
|
671
|
+
// ๆถ้ๆๆ้ดๆฅไพ่ต
|
|
672
|
+
const allDeps = [...directDeps];
|
|
673
|
+
// ้ๅฝๅฏปๆพ้ดๆฅไพ่ต
|
|
674
|
+
function findTransitiveDeps(chunks) {
|
|
675
|
+
chunks.forEach((chunk) => {
|
|
676
|
+
// ๅฆๆ่ฏฅchunkๆฌ่บซไนๆฏไธชๅ
ฅๅฃ(ๆไพ่ตๅ่กจ)
|
|
677
|
+
if (chunk in allChunksMap) {
|
|
678
|
+
const subDeps = allChunksMap[chunk];
|
|
679
|
+
// ๆทปๅ ๆชๅ
ๅซ็ไพ่ต
|
|
680
|
+
if (subDeps) {
|
|
681
|
+
subDeps.forEach((dep) => {
|
|
682
|
+
if (!allDeps.includes(dep)) {
|
|
683
|
+
allDeps.push(dep);
|
|
684
|
+
// ้ๅฝๅฏปๆพ่ฟไธชไพ่ต็ไพ่ต
|
|
685
|
+
findTransitiveDeps([dep]);
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
// ๅผๅง้ๅฝๆฅๆพ
|
|
693
|
+
findTransitiveDeps([...directDeps]);
|
|
694
|
+
// ๆดๆฐไธบๅฎๆดไพ่ตๅ่กจ
|
|
695
|
+
allChunksMap[entryFile] = new Set(allDeps);
|
|
696
|
+
});
|
|
697
|
+
// ่ฝฌๆข Set ไธบๆฐ็ปไปฅไพฟๆญฃ็กฎๅบๅๅ
|
|
698
|
+
const serializedMap = Object.entries(allChunksMap).reduce((result, [key, deps]) => {
|
|
699
|
+
result[key] = Array.from(deps);
|
|
700
|
+
return result;
|
|
701
|
+
}, {});
|
|
702
|
+
formats.forEach((format) => {
|
|
703
|
+
// ๅญไธๆฅ
|
|
704
|
+
(0, fs_1.writeFileSync)(path_1.default.join(outDir, `${format}/chunks-map.json`), JSON.stringify(serializedMap, null, 2));
|
|
705
|
+
});
|
|
706
|
+
},
|
|
707
|
+
},
|
|
708
|
+
];
|
|
361
709
|
}
|
|
362
710
|
exports.default = vitePluginCodeSplitter;
|