bertui 0.3.2 ā 0.3.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/package.json +1 -1
- package/src/build.js +26 -29
- package/src/client/compiler.js +22 -20
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -11,7 +11,6 @@ export async function buildProduction(options = {}) {
|
|
|
11
11
|
|
|
12
12
|
logger.bigLog('BUILDING FOR PRODUCTION', { color: 'green' });
|
|
13
13
|
|
|
14
|
-
// Clean folders
|
|
15
14
|
if (existsSync(buildDir)) {
|
|
16
15
|
rmSync(buildDir, { recursive: true });
|
|
17
16
|
}
|
|
@@ -26,16 +25,13 @@ export async function buildProduction(options = {}) {
|
|
|
26
25
|
const startTime = Date.now();
|
|
27
26
|
|
|
28
27
|
try {
|
|
29
|
-
// Step 1: Compile for production
|
|
30
28
|
logger.info('Step 1: Compiling for production...');
|
|
31
29
|
await compileForBuild(root, buildDir);
|
|
32
30
|
logger.success('Production compilation complete');
|
|
33
31
|
|
|
34
|
-
// Step 2: Build CSS with Lightning CSS
|
|
35
32
|
logger.info('Step 2: Building CSS with Lightning CSS...');
|
|
36
33
|
await buildAllCSS(root, outDir);
|
|
37
34
|
|
|
38
|
-
// Step 3: Copy public assets if they exist
|
|
39
35
|
const publicDir = join(root, 'public');
|
|
40
36
|
if (existsSync(publicDir)) {
|
|
41
37
|
logger.info('Step 3: Copying public assets...');
|
|
@@ -45,7 +41,6 @@ export async function buildProduction(options = {}) {
|
|
|
45
41
|
logger.info('Step 3: No public directory found, skipping...');
|
|
46
42
|
}
|
|
47
43
|
|
|
48
|
-
// Step 4: Build JavaScript with Bun's bundler
|
|
49
44
|
logger.info('Step 4: Bundling JavaScript with Bun...');
|
|
50
45
|
const buildEntry = join(buildDir, 'main.js');
|
|
51
46
|
|
|
@@ -54,7 +49,6 @@ export async function buildProduction(options = {}) {
|
|
|
54
49
|
process.exit(1);
|
|
55
50
|
}
|
|
56
51
|
|
|
57
|
-
// FIXED: Let Bun handle ALL imports with proper externals
|
|
58
52
|
const result = await Bun.build({
|
|
59
53
|
entrypoints: [buildEntry],
|
|
60
54
|
outdir: join(outDir, 'assets'),
|
|
@@ -67,7 +61,6 @@ export async function buildProduction(options = {}) {
|
|
|
67
61
|
chunk: 'chunks/[name]-[hash].js',
|
|
68
62
|
asset: '[name]-[hash].[ext]'
|
|
69
63
|
},
|
|
70
|
-
// FIXED: Use CDN externals - Bun handles tree shaking automatically
|
|
71
64
|
external: ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime']
|
|
72
65
|
});
|
|
73
66
|
|
|
@@ -79,11 +72,9 @@ export async function buildProduction(options = {}) {
|
|
|
79
72
|
|
|
80
73
|
logger.success('JavaScript bundled with tree-shaking');
|
|
81
74
|
|
|
82
|
-
// Step 5: Generate index.html
|
|
83
75
|
logger.info('Step 5: Generating index.html...');
|
|
84
76
|
await generateProductionHTML(root, outDir, result);
|
|
85
77
|
|
|
86
|
-
// Step 6: Clean up build folder
|
|
87
78
|
rmSync(buildDir, { recursive: true });
|
|
88
79
|
logger.info('Cleaned up .bertuibuild/');
|
|
89
80
|
|
|
@@ -91,13 +82,11 @@ export async function buildProduction(options = {}) {
|
|
|
91
82
|
logger.success(`⨠Build complete in ${duration}ms`);
|
|
92
83
|
logger.info(`š¦ Output: ${outDir}`);
|
|
93
84
|
|
|
94
|
-
// Display build stats
|
|
95
85
|
logger.table(result.outputs.map(o => ({
|
|
96
86
|
file: o.path.replace(outDir, ''),
|
|
97
87
|
size: `${(o.size / 1024).toFixed(2)} KB`
|
|
98
88
|
})));
|
|
99
89
|
|
|
100
|
-
// Show deployment instructions
|
|
101
90
|
logger.bigLog('READY TO DEPLOY', { color: 'green' });
|
|
102
91
|
console.log('\nš¤ Deploy your app:\n');
|
|
103
92
|
console.log(' Vercel: bunx vercel');
|
|
@@ -111,7 +100,6 @@ export async function buildProduction(options = {}) {
|
|
|
111
100
|
logger.error(error.stack);
|
|
112
101
|
}
|
|
113
102
|
|
|
114
|
-
// Clean up on error
|
|
115
103
|
if (existsSync(buildDir)) {
|
|
116
104
|
rmSync(buildDir, { recursive: true });
|
|
117
105
|
}
|
|
@@ -122,15 +110,10 @@ export async function buildProduction(options = {}) {
|
|
|
122
110
|
|
|
123
111
|
async function buildAllCSS(root, outDir) {
|
|
124
112
|
const srcStylesDir = join(root, 'src', 'styles');
|
|
125
|
-
const bertuiCssSource = join(import.meta.dir, 'styles/bertui.css');
|
|
126
113
|
const stylesOutDir = join(outDir, 'styles');
|
|
127
114
|
|
|
128
115
|
mkdirSync(stylesOutDir, { recursive: true });
|
|
129
116
|
|
|
130
|
-
// Build BertUI's built-in CSS
|
|
131
|
-
await buildCSS(bertuiCssSource, join(stylesOutDir, 'bertui.min.css'));
|
|
132
|
-
|
|
133
|
-
// Build user's CSS files if they exist
|
|
134
117
|
if (existsSync(srcStylesDir)) {
|
|
135
118
|
const cssFiles = readdirSync(srcStylesDir).filter(f => f.endsWith('.css'));
|
|
136
119
|
for (const cssFile of cssFiles) {
|
|
@@ -149,17 +132,14 @@ async function compileForBuild(root, buildDir) {
|
|
|
149
132
|
throw new Error('src/ directory not found!');
|
|
150
133
|
}
|
|
151
134
|
|
|
152
|
-
// Discover routes
|
|
153
135
|
let routes = [];
|
|
154
136
|
if (existsSync(pagesDir)) {
|
|
155
137
|
routes = await discoverRoutes(pagesDir);
|
|
156
138
|
logger.info(`Found ${routes.length} routes`);
|
|
157
139
|
}
|
|
158
140
|
|
|
159
|
-
// Compile all source files
|
|
160
141
|
await compileBuildDirectory(srcDir, buildDir, root);
|
|
161
142
|
|
|
162
|
-
// Generate router if we have routes
|
|
163
143
|
if (routes.length > 0) {
|
|
164
144
|
await generateBuildRouter(routes, buildDir);
|
|
165
145
|
logger.info('Generated router for build');
|
|
@@ -181,7 +161,6 @@ async function discoverRoutes(pagesDir) {
|
|
|
181
161
|
} else if (entry.isFile()) {
|
|
182
162
|
const ext = extname(entry.name);
|
|
183
163
|
|
|
184
|
-
// FIXED: Ignore CSS files
|
|
185
164
|
if (ext === '.css') continue;
|
|
186
165
|
|
|
187
166
|
if (['.jsx', '.tsx', '.js', '.ts'].includes(ext)) {
|
|
@@ -369,7 +348,6 @@ async function compileBuildDirectory(srcDir, buildDir, root) {
|
|
|
369
348
|
} else {
|
|
370
349
|
const ext = extname(file);
|
|
371
350
|
|
|
372
|
-
// FIXED: Skip CSS files in build
|
|
373
351
|
if (ext === '.css') continue;
|
|
374
352
|
|
|
375
353
|
if (['.jsx', '.tsx', '.ts'].includes(ext)) {
|
|
@@ -377,7 +355,11 @@ async function compileBuildDirectory(srcDir, buildDir, root) {
|
|
|
377
355
|
} else if (ext === '.js') {
|
|
378
356
|
const outPath = join(buildDir, file);
|
|
379
357
|
let code = await Bun.file(srcPath).text();
|
|
358
|
+
|
|
359
|
+
// CRITICAL FIX: Remove CSS imports
|
|
360
|
+
code = removeCSSImports(code);
|
|
380
361
|
code = fixBuildImports(code, srcPath, outPath, root);
|
|
362
|
+
|
|
381
363
|
await Bun.write(outPath, code);
|
|
382
364
|
}
|
|
383
365
|
}
|
|
@@ -391,6 +373,9 @@ async function compileBuildFile(srcPath, buildDir, filename, root) {
|
|
|
391
373
|
try {
|
|
392
374
|
let code = await Bun.file(srcPath).text();
|
|
393
375
|
|
|
376
|
+
// CRITICAL FIX: Remove CSS imports before transpilation
|
|
377
|
+
code = removeCSSImports(code);
|
|
378
|
+
|
|
394
379
|
const outFilename = filename.replace(/\.(jsx|tsx|ts)$/, '.js');
|
|
395
380
|
const outPath = join(buildDir, outFilename);
|
|
396
381
|
|
|
@@ -422,19 +407,20 @@ async function compileBuildFile(srcPath, buildDir, filename, root) {
|
|
|
422
407
|
}
|
|
423
408
|
}
|
|
424
409
|
|
|
425
|
-
//
|
|
426
|
-
function
|
|
427
|
-
|
|
410
|
+
// NEW FUNCTION: Remove all CSS imports
|
|
411
|
+
function removeCSSImports(code) {
|
|
412
|
+
code = code.replace(/import\s+['"][^'"]*\.css['"];?\s*/g, '');
|
|
428
413
|
code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
|
|
429
|
-
|
|
414
|
+
return code;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function fixBuildImports(code, srcPath, outPath, root) {
|
|
430
418
|
const buildDir = join(root, '.bertuibuild');
|
|
431
419
|
const routerPath = join(buildDir, 'router.js');
|
|
432
420
|
|
|
433
|
-
// Calculate relative path from output file to router.js
|
|
434
421
|
const relativeToRouter = relative(dirname(outPath), routerPath).replace(/\\/g, '/');
|
|
435
422
|
const routerImport = relativeToRouter.startsWith('.') ? relativeToRouter : './' + relativeToRouter;
|
|
436
423
|
|
|
437
|
-
// ONLY replace bertui/router imports
|
|
438
424
|
code = code.replace(
|
|
439
425
|
/from\s+['"]bertui\/router['"]/g,
|
|
440
426
|
`from '${routerImport}'`
|
|
@@ -467,6 +453,17 @@ async function generateProductionHTML(root, outDir, buildResult) {
|
|
|
467
453
|
|
|
468
454
|
const bundlePath = mainBundle.path.replace(outDir, '').replace(/^\//, '');
|
|
469
455
|
|
|
456
|
+
// Find user CSS files
|
|
457
|
+
const srcStylesDir = join(root, 'src', 'styles');
|
|
458
|
+
let userStylesheets = '';
|
|
459
|
+
|
|
460
|
+
if (existsSync(srcStylesDir)) {
|
|
461
|
+
const cssFiles = readdirSync(srcStylesDir).filter(f => f.endsWith('.css'));
|
|
462
|
+
userStylesheets = cssFiles.map(f =>
|
|
463
|
+
` <link rel="stylesheet" href="/styles/${f.replace('.css', '.min.css')}">`
|
|
464
|
+
).join('\n');
|
|
465
|
+
}
|
|
466
|
+
|
|
470
467
|
const html = `<!DOCTYPE html>
|
|
471
468
|
<html lang="en">
|
|
472
469
|
<head>
|
|
@@ -474,7 +471,7 @@ async function generateProductionHTML(root, outDir, buildResult) {
|
|
|
474
471
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
475
472
|
<meta name="description" content="Built with BertUI - Lightning fast React development">
|
|
476
473
|
<title>BertUI App</title>
|
|
477
|
-
|
|
474
|
+
${userStylesheets}
|
|
478
475
|
<script type="importmap">
|
|
479
476
|
{
|
|
480
477
|
"imports": {
|
package/src/client/compiler.js
CHANGED
|
@@ -65,13 +65,8 @@ async function discoverRoutes(pagesDir) {
|
|
|
65
65
|
} else if (entry.isFile()) {
|
|
66
66
|
const ext = extname(entry.name);
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
if (ext === '.css') {
|
|
70
|
-
logger.debug(`Skipping CSS file: ${relativePath}`);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
68
|
+
if (ext === '.css') continue;
|
|
73
69
|
|
|
74
|
-
// Only process valid page files
|
|
75
70
|
if (['.jsx', '.tsx', '.js', '.ts'].includes(ext)) {
|
|
76
71
|
const fileName = entry.name.replace(ext, '');
|
|
77
72
|
|
|
@@ -263,7 +258,6 @@ async function compileDirectory(srcDir, outDir, root) {
|
|
|
263
258
|
const ext = extname(file);
|
|
264
259
|
const relativePath = relative(join(root, 'src'), srcPath);
|
|
265
260
|
|
|
266
|
-
// FIXED: Handle CSS files properly - copy to styles output
|
|
267
261
|
if (ext === '.css') {
|
|
268
262
|
const stylesOutDir = join(root, '.bertui', 'styles');
|
|
269
263
|
if (!existsSync(stylesOutDir)) {
|
|
@@ -274,14 +268,15 @@ async function compileDirectory(srcDir, outDir, root) {
|
|
|
274
268
|
logger.debug(`Copied CSS: ${relativePath}`);
|
|
275
269
|
stats.files++;
|
|
276
270
|
} else if (['.jsx', '.tsx', '.ts'].includes(ext)) {
|
|
277
|
-
await compileFile(srcPath, outDir, file, relativePath);
|
|
271
|
+
await compileFile(srcPath, outDir, file, relativePath, root);
|
|
278
272
|
stats.files++;
|
|
279
273
|
} else if (ext === '.js') {
|
|
280
274
|
const outPath = join(outDir, file);
|
|
281
275
|
let code = await Bun.file(srcPath).text();
|
|
282
276
|
|
|
283
|
-
//
|
|
284
|
-
|
|
277
|
+
// Remove ALL CSS imports
|
|
278
|
+
code = removeCSSImports(code);
|
|
279
|
+
// Fix router imports
|
|
285
280
|
code = fixRouterImports(code, outPath, root);
|
|
286
281
|
|
|
287
282
|
await Bun.write(outPath, code);
|
|
@@ -297,17 +292,18 @@ async function compileDirectory(srcDir, outDir, root) {
|
|
|
297
292
|
return stats;
|
|
298
293
|
}
|
|
299
294
|
|
|
300
|
-
async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
295
|
+
async function compileFile(srcPath, outDir, filename, relativePath, root) {
|
|
301
296
|
const ext = extname(filename);
|
|
302
297
|
const loader = ext === '.tsx' ? 'tsx' : ext === '.ts' ? 'ts' : 'jsx';
|
|
303
298
|
|
|
304
299
|
try {
|
|
305
300
|
let code = await Bun.file(srcPath).text();
|
|
306
301
|
|
|
307
|
-
//
|
|
308
|
-
|
|
302
|
+
// CRITICAL FIX: Remove ALL CSS imports before transpilation
|
|
303
|
+
code = removeCSSImports(code);
|
|
304
|
+
|
|
309
305
|
const outPath = join(outDir, filename.replace(/\.(jsx|tsx|ts)$/, '.js'));
|
|
310
|
-
code = fixRouterImports(code, outPath,
|
|
306
|
+
code = fixRouterImports(code, outPath, root);
|
|
311
307
|
|
|
312
308
|
const transpiler = new Bun.Transpiler({
|
|
313
309
|
loader,
|
|
@@ -335,24 +331,30 @@ async function compileFile(srcPath, outDir, filename, relativePath) {
|
|
|
335
331
|
}
|
|
336
332
|
}
|
|
337
333
|
|
|
338
|
-
//
|
|
334
|
+
// NEW FUNCTION: Remove all CSS imports
|
|
335
|
+
function removeCSSImports(code) {
|
|
336
|
+
// Remove CSS imports (with or without quotes, single or double)
|
|
337
|
+
// Matches: import './styles.css', import "./styles.css", import "styles.css", import 'styles.css'
|
|
338
|
+
code = code.replace(/import\s+['"][^'"]*\.css['"];?\s*/g, '');
|
|
339
|
+
|
|
340
|
+
// Also remove bertui/styles imports
|
|
341
|
+
code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
|
|
342
|
+
|
|
343
|
+
return code;
|
|
344
|
+
}
|
|
345
|
+
|
|
339
346
|
function fixRouterImports(code, outPath, root) {
|
|
340
347
|
const buildDir = join(root, '.bertui', 'compiled');
|
|
341
348
|
const routerPath = join(buildDir, 'router.js');
|
|
342
349
|
|
|
343
|
-
// Calculate relative path from output file to router.js
|
|
344
350
|
const relativeToRouter = relative(dirname(outPath), routerPath).replace(/\\/g, '/');
|
|
345
351
|
const routerImport = relativeToRouter.startsWith('.') ? relativeToRouter : './' + relativeToRouter;
|
|
346
352
|
|
|
347
|
-
// ONLY replace bertui/router imports
|
|
348
353
|
code = code.replace(
|
|
349
354
|
/from\s+['"]bertui\/router['"]/g,
|
|
350
355
|
`from '${routerImport}'`
|
|
351
356
|
);
|
|
352
357
|
|
|
353
|
-
// Remove bertui/styles imports (CSS handled separately)
|
|
354
|
-
code = code.replace(/import\s+['"]bertui\/styles['"]\s*;?\s*/g, '');
|
|
355
|
-
|
|
356
358
|
return code;
|
|
357
359
|
}
|
|
358
360
|
|