@flexireact/core 3.0.0 → 3.0.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/README.md +204 -52
- package/dist/cli/index.js +1514 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/client/index.js +373 -0
- package/dist/core/client/index.js.map +1 -0
- package/dist/core/index.js +6415 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/server/index.js +3094 -0
- package/dist/core/server/index.js.map +1 -0
- package/package.json +80 -80
- package/bin/flexireact.js +0 -23
- package/cli/generators.ts +0 -616
- package/cli/index.ts +0 -1182
- package/core/actions/index.ts +0 -364
- package/core/api.ts +0 -143
- package/core/build/index.ts +0 -425
- package/core/cli/logger.ts +0 -353
- package/core/client/Link.tsx +0 -345
- package/core/client/hydration.ts +0 -147
- package/core/client/index.ts +0 -12
- package/core/client/islands.ts +0 -143
- package/core/client/navigation.ts +0 -212
- package/core/client/runtime.ts +0 -52
- package/core/config.ts +0 -116
- package/core/context.ts +0 -83
- package/core/dev.ts +0 -47
- package/core/devtools/index.ts +0 -644
- package/core/edge/cache.ts +0 -344
- package/core/edge/fetch-polyfill.ts +0 -247
- package/core/edge/handler.ts +0 -248
- package/core/edge/index.ts +0 -81
- package/core/edge/ppr.ts +0 -264
- package/core/edge/runtime.ts +0 -161
- package/core/font/index.ts +0 -306
- package/core/helpers.ts +0 -494
- package/core/image/index.ts +0 -413
- package/core/index.ts +0 -218
- package/core/islands/index.ts +0 -293
- package/core/loader.ts +0 -111
- package/core/logger.ts +0 -242
- package/core/metadata/index.ts +0 -622
- package/core/middleware/index.ts +0 -416
- package/core/plugins/index.ts +0 -373
- package/core/render/index.ts +0 -1243
- package/core/render.ts +0 -136
- package/core/router/index.ts +0 -551
- package/core/router.ts +0 -141
- package/core/rsc/index.ts +0 -199
- package/core/server/index.ts +0 -779
- package/core/server.ts +0 -203
- package/core/ssg/index.ts +0 -346
- package/core/start-dev.ts +0 -6
- package/core/start-prod.ts +0 -6
- package/core/tsconfig.json +0 -30
- package/core/types.ts +0 -239
- package/core/utils.ts +0 -176
package/core/build/index.ts
DELETED
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FlexiReact Build System
|
|
3
|
-
* Uses esbuild for fast bundling of client and server code
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as esbuild from 'esbuild';
|
|
7
|
-
import fs from 'fs';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import { fileURLToPath } from 'url';
|
|
10
|
-
import { findFiles, ensureDir, cleanDir, generateHash, isClientComponent, isIsland } from '../utils.js';
|
|
11
|
-
import { buildRouteTree } from '../router/index.js';
|
|
12
|
-
|
|
13
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
-
const __dirname = path.dirname(__filename);
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Build configuration
|
|
18
|
-
*/
|
|
19
|
-
export const BuildMode = {
|
|
20
|
-
DEVELOPMENT: 'development',
|
|
21
|
-
PRODUCTION: 'production'
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Main build function
|
|
26
|
-
*/
|
|
27
|
-
export async function build(options) {
|
|
28
|
-
const {
|
|
29
|
-
projectRoot,
|
|
30
|
-
config,
|
|
31
|
-
mode = BuildMode.PRODUCTION,
|
|
32
|
-
analyze = false
|
|
33
|
-
} = options;
|
|
34
|
-
|
|
35
|
-
const startTime = Date.now();
|
|
36
|
-
const outDir = config.outDir;
|
|
37
|
-
const isDev = mode === BuildMode.DEVELOPMENT;
|
|
38
|
-
|
|
39
|
-
console.log('\n⚡ FlexiReact Build\n');
|
|
40
|
-
console.log(` Mode: ${mode}`);
|
|
41
|
-
console.log(` Output: ${outDir}\n`);
|
|
42
|
-
|
|
43
|
-
// Clean output directory
|
|
44
|
-
cleanDir(outDir);
|
|
45
|
-
ensureDir(path.join(outDir, 'client'));
|
|
46
|
-
ensureDir(path.join(outDir, 'server'));
|
|
47
|
-
ensureDir(path.join(outDir, 'static'));
|
|
48
|
-
|
|
49
|
-
// Build routes
|
|
50
|
-
const routes = buildRouteTree(config.pagesDir, config.layoutsDir);
|
|
51
|
-
|
|
52
|
-
// Find all client components and islands
|
|
53
|
-
const clientEntries = findClientEntries(config.pagesDir, config.layoutsDir);
|
|
54
|
-
|
|
55
|
-
// Build client bundle
|
|
56
|
-
console.log('📦 Building client bundle...');
|
|
57
|
-
const clientResult = await buildClient({
|
|
58
|
-
entries: clientEntries,
|
|
59
|
-
outDir: path.join(outDir, 'client'),
|
|
60
|
-
config,
|
|
61
|
-
isDev
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Build server bundle
|
|
65
|
-
console.log('📦 Building server bundle...');
|
|
66
|
-
const serverResult = await buildServer({
|
|
67
|
-
pagesDir: config.pagesDir,
|
|
68
|
-
layoutsDir: config.layoutsDir,
|
|
69
|
-
outDir: path.join(outDir, 'server'),
|
|
70
|
-
config,
|
|
71
|
-
isDev
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Copy public assets
|
|
75
|
-
console.log('📁 Copying public assets...');
|
|
76
|
-
await copyPublicAssets(config.publicDir, path.join(outDir, 'static'));
|
|
77
|
-
|
|
78
|
-
// Generate manifest
|
|
79
|
-
const manifest = generateManifest({
|
|
80
|
-
routes,
|
|
81
|
-
clientResult,
|
|
82
|
-
serverResult,
|
|
83
|
-
config
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
fs.writeFileSync(
|
|
87
|
-
path.join(outDir, 'manifest.json'),
|
|
88
|
-
JSON.stringify(manifest, null, 2)
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const duration = Date.now() - startTime;
|
|
92
|
-
|
|
93
|
-
console.log('\n✨ Build complete!\n');
|
|
94
|
-
console.log(` Duration: ${duration}ms`);
|
|
95
|
-
console.log(` Client chunks: ${clientResult.outputs.length}`);
|
|
96
|
-
console.log(` Server modules: ${serverResult.outputs.length}`);
|
|
97
|
-
console.log('');
|
|
98
|
-
|
|
99
|
-
// Generate bundle analysis if requested
|
|
100
|
-
let analysis = null;
|
|
101
|
-
if (analyze) {
|
|
102
|
-
analysis = generateBundleAnalysis(clientResult, serverResult, outDir);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
success: true,
|
|
107
|
-
duration,
|
|
108
|
-
manifest,
|
|
109
|
-
clientResult,
|
|
110
|
-
serverResult,
|
|
111
|
-
analysis
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Generates bundle analysis data
|
|
117
|
-
*/
|
|
118
|
-
function generateBundleAnalysis(clientResult, serverResult, outDir) {
|
|
119
|
-
const files: Record<string, { size: number; gzipSize?: number }> = {};
|
|
120
|
-
let totalSize = 0;
|
|
121
|
-
let totalGzipSize = 0;
|
|
122
|
-
|
|
123
|
-
// Analyze client outputs
|
|
124
|
-
for (const output of clientResult.outputs || []) {
|
|
125
|
-
if (output.path && fs.existsSync(output.path)) {
|
|
126
|
-
const stat = fs.statSync(output.path);
|
|
127
|
-
const relativePath = path.relative(outDir, output.path);
|
|
128
|
-
|
|
129
|
-
// Estimate gzip size (roughly 30% of original for JS)
|
|
130
|
-
const gzipSize = Math.round(stat.size * 0.3);
|
|
131
|
-
|
|
132
|
-
files[relativePath] = {
|
|
133
|
-
size: stat.size,
|
|
134
|
-
gzipSize
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
totalSize += stat.size;
|
|
138
|
-
totalGzipSize += gzipSize;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Analyze server outputs
|
|
143
|
-
for (const output of serverResult.outputs || []) {
|
|
144
|
-
if (output.path && fs.existsSync(output.path)) {
|
|
145
|
-
const stat = fs.statSync(output.path);
|
|
146
|
-
const relativePath = path.relative(outDir, output.path);
|
|
147
|
-
|
|
148
|
-
files[relativePath] = {
|
|
149
|
-
size: stat.size
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
totalSize += stat.size;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
files,
|
|
158
|
-
totalSize,
|
|
159
|
-
totalGzipSize,
|
|
160
|
-
clientSize: clientResult.outputs?.reduce((sum, o) => {
|
|
161
|
-
if (o.path && fs.existsSync(o.path)) {
|
|
162
|
-
return sum + fs.statSync(o.path).size;
|
|
163
|
-
}
|
|
164
|
-
return sum;
|
|
165
|
-
}, 0) || 0,
|
|
166
|
-
serverSize: serverResult.outputs?.reduce((sum, o) => {
|
|
167
|
-
if (o.path && fs.existsSync(o.path)) {
|
|
168
|
-
return sum + fs.statSync(o.path).size;
|
|
169
|
-
}
|
|
170
|
-
return sum;
|
|
171
|
-
}, 0) || 0
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Finds all client component entries
|
|
177
|
-
*/
|
|
178
|
-
function findClientEntries(pagesDir, layoutsDir) {
|
|
179
|
-
const entries = [];
|
|
180
|
-
const dirs = [pagesDir, layoutsDir].filter(d => fs.existsSync(d));
|
|
181
|
-
|
|
182
|
-
for (const dir of dirs) {
|
|
183
|
-
const files = findFiles(dir, /\.(jsx|tsx)$/);
|
|
184
|
-
|
|
185
|
-
for (const file of files) {
|
|
186
|
-
if (isClientComponent(file) || isIsland(file)) {
|
|
187
|
-
entries.push(file);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return entries;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Builds client-side JavaScript
|
|
197
|
-
*/
|
|
198
|
-
async function buildClient(options) {
|
|
199
|
-
const { entries, outDir, config, isDev } = options;
|
|
200
|
-
|
|
201
|
-
if (entries.length === 0) {
|
|
202
|
-
return { outputs: [] };
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Create entry points map
|
|
206
|
-
const entryPoints = {};
|
|
207
|
-
for (const entry of entries) {
|
|
208
|
-
const name = path.basename(entry, path.extname(entry));
|
|
209
|
-
const hash = generateHash(entry);
|
|
210
|
-
entryPoints[`${name}-${hash}`] = entry;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Add runtime entry
|
|
214
|
-
const runtimePath = path.join(__dirname, '..', 'client', 'runtime.js');
|
|
215
|
-
if (fs.existsSync(runtimePath)) {
|
|
216
|
-
entryPoints['runtime'] = runtimePath;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
const result = await esbuild.build({
|
|
221
|
-
entryPoints,
|
|
222
|
-
bundle: true,
|
|
223
|
-
splitting: true,
|
|
224
|
-
format: 'esm',
|
|
225
|
-
outdir: outDir,
|
|
226
|
-
minify: !isDev && config.build.minify,
|
|
227
|
-
sourcemap: config.build.sourcemap,
|
|
228
|
-
target: config.build.target,
|
|
229
|
-
jsx: 'automatic',
|
|
230
|
-
jsxImportSource: 'react',
|
|
231
|
-
metafile: true,
|
|
232
|
-
external: [],
|
|
233
|
-
define: {
|
|
234
|
-
'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production')
|
|
235
|
-
},
|
|
236
|
-
loader: {
|
|
237
|
-
'.js': 'jsx',
|
|
238
|
-
'.jsx': 'jsx',
|
|
239
|
-
'.ts': 'tsx',
|
|
240
|
-
'.tsx': 'tsx'
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
const outputs = Object.keys(result.metafile.outputs).map(file => ({
|
|
245
|
-
file: path.basename(file),
|
|
246
|
-
size: result.metafile.outputs[file].bytes
|
|
247
|
-
}));
|
|
248
|
-
|
|
249
|
-
return { outputs, metafile: result.metafile };
|
|
250
|
-
|
|
251
|
-
} catch (error) {
|
|
252
|
-
console.error('Client build failed:', error);
|
|
253
|
-
throw error;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Builds server-side modules
|
|
259
|
-
*/
|
|
260
|
-
async function buildServer(options) {
|
|
261
|
-
const { pagesDir, layoutsDir, outDir, config, isDev } = options;
|
|
262
|
-
|
|
263
|
-
const entries = [];
|
|
264
|
-
|
|
265
|
-
// Find all page and layout files
|
|
266
|
-
for (const dir of [pagesDir, layoutsDir]) {
|
|
267
|
-
if (fs.existsSync(dir)) {
|
|
268
|
-
entries.push(...findFiles(dir, /\.(jsx|tsx|js|ts)$/));
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (entries.length === 0) {
|
|
273
|
-
return { outputs: [] };
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Create entry points
|
|
277
|
-
const entryPoints = {};
|
|
278
|
-
for (const entry of entries) {
|
|
279
|
-
const relativePath = path.relative(pagesDir, entry);
|
|
280
|
-
const name = relativePath.replace(/[\/\\]/g, '_').replace(/\.(jsx|tsx|js|ts)$/, '');
|
|
281
|
-
entryPoints[name] = entry;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
try {
|
|
285
|
-
const result = await esbuild.build({
|
|
286
|
-
entryPoints,
|
|
287
|
-
bundle: true,
|
|
288
|
-
format: 'esm',
|
|
289
|
-
platform: 'node',
|
|
290
|
-
outdir: outDir,
|
|
291
|
-
minify: false, // Keep server code readable
|
|
292
|
-
sourcemap: true,
|
|
293
|
-
target: 'node18',
|
|
294
|
-
jsx: 'automatic',
|
|
295
|
-
jsxImportSource: 'react',
|
|
296
|
-
metafile: true,
|
|
297
|
-
packages: 'external', // Don't bundle node_modules
|
|
298
|
-
loader: {
|
|
299
|
-
'.js': 'jsx',
|
|
300
|
-
'.jsx': 'jsx',
|
|
301
|
-
'.ts': 'tsx',
|
|
302
|
-
'.tsx': 'tsx'
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
const outputs = Object.keys(result.metafile.outputs).map(file => ({
|
|
307
|
-
file: path.basename(file),
|
|
308
|
-
size: result.metafile.outputs[file].bytes
|
|
309
|
-
}));
|
|
310
|
-
|
|
311
|
-
return { outputs, metafile: result.metafile };
|
|
312
|
-
|
|
313
|
-
} catch (error) {
|
|
314
|
-
console.error('Server build failed:', error);
|
|
315
|
-
throw error;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Copies public assets to output directory
|
|
321
|
-
*/
|
|
322
|
-
async function copyPublicAssets(publicDir, outDir) {
|
|
323
|
-
if (!fs.existsSync(publicDir)) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const copyRecursive = (src, dest) => {
|
|
328
|
-
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
329
|
-
|
|
330
|
-
ensureDir(dest);
|
|
331
|
-
|
|
332
|
-
for (const entry of entries) {
|
|
333
|
-
const srcPath = path.join(src, entry.name);
|
|
334
|
-
const destPath = path.join(dest, entry.name);
|
|
335
|
-
|
|
336
|
-
if (entry.isDirectory()) {
|
|
337
|
-
copyRecursive(srcPath, destPath);
|
|
338
|
-
} else {
|
|
339
|
-
fs.copyFileSync(srcPath, destPath);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
copyRecursive(publicDir, outDir);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Generates build manifest
|
|
349
|
-
*/
|
|
350
|
-
function generateManifest(options) {
|
|
351
|
-
const { routes, clientResult, serverResult, config } = options;
|
|
352
|
-
|
|
353
|
-
return {
|
|
354
|
-
version: '2.0.0',
|
|
355
|
-
generatedAt: new Date().toISOString(),
|
|
356
|
-
routes: {
|
|
357
|
-
pages: routes.pages.map(r => ({
|
|
358
|
-
path: r.path,
|
|
359
|
-
file: r.filePath,
|
|
360
|
-
hasLayout: !!r.layout,
|
|
361
|
-
hasLoading: !!r.loading,
|
|
362
|
-
hasError: !!r.error
|
|
363
|
-
})),
|
|
364
|
-
api: routes.api.map(r => ({
|
|
365
|
-
path: r.path,
|
|
366
|
-
file: r.filePath
|
|
367
|
-
}))
|
|
368
|
-
},
|
|
369
|
-
client: {
|
|
370
|
-
chunks: clientResult.outputs || []
|
|
371
|
-
},
|
|
372
|
-
server: {
|
|
373
|
-
modules: serverResult.outputs || []
|
|
374
|
-
},
|
|
375
|
-
config: {
|
|
376
|
-
islands: config.islands.enabled,
|
|
377
|
-
rsc: config.rsc.enabled
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Development build with watch mode
|
|
384
|
-
*/
|
|
385
|
-
export async function buildDev(options) {
|
|
386
|
-
const { projectRoot, config, onChange } = options;
|
|
387
|
-
|
|
388
|
-
const outDir = config.outDir;
|
|
389
|
-
ensureDir(outDir);
|
|
390
|
-
|
|
391
|
-
// Use esbuild's watch mode
|
|
392
|
-
const ctx = await esbuild.context({
|
|
393
|
-
entryPoints: findFiles(config.pagesDir, /\.(jsx|tsx)$/),
|
|
394
|
-
bundle: true,
|
|
395
|
-
format: 'esm',
|
|
396
|
-
outdir: path.join(outDir, 'dev'),
|
|
397
|
-
sourcemap: true,
|
|
398
|
-
jsx: 'automatic',
|
|
399
|
-
jsxImportSource: 'react',
|
|
400
|
-
loader: {
|
|
401
|
-
'.js': 'jsx',
|
|
402
|
-
'.jsx': 'jsx'
|
|
403
|
-
},
|
|
404
|
-
plugins: [{
|
|
405
|
-
name: 'flexi-watch',
|
|
406
|
-
setup(build) {
|
|
407
|
-
build.onEnd(result => {
|
|
408
|
-
if (result.errors.length === 0) {
|
|
409
|
-
onChange?.();
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
}]
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
await ctx.watch();
|
|
417
|
-
|
|
418
|
-
return ctx;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
export default {
|
|
422
|
-
build,
|
|
423
|
-
buildDev,
|
|
424
|
-
BuildMode
|
|
425
|
-
};
|