bertui 1.0.1 → 1.0.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/index.js +1 -1
- package/package.json +1 -1
- package/src/build.js +53 -51
package/index.js
CHANGED
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/build.js - COMPLETE
|
|
1
|
+
// src/build.js - COMPLETE v1.0.0 FIXED VERSION
|
|
2
2
|
import { join, relative, basename, extname, dirname } from 'path';
|
|
3
3
|
import { existsSync, mkdirSync, rmSync, cpSync, readdirSync, statSync } from 'fs';
|
|
4
4
|
import logger from './logger/logger.js';
|
|
@@ -11,7 +11,8 @@ export async function buildProduction(options = {}) {
|
|
|
11
11
|
const buildDir = join(root, '.bertuibuild');
|
|
12
12
|
const outDir = join(root, 'dist');
|
|
13
13
|
|
|
14
|
-
logger.bigLog('BUILDING FOR PRODUCTION', { color: 'green' });
|
|
14
|
+
logger.bigLog('BUILDING FOR PRODUCTION v1.0.0', { color: 'green' });
|
|
15
|
+
logger.info('🔥 SINGLE CSS FILE SOLUTION - NO BULLSHIT');
|
|
15
16
|
|
|
16
17
|
// Clean up old builds
|
|
17
18
|
if (existsSync(buildDir)) {
|
|
@@ -38,7 +39,7 @@ export async function buildProduction(options = {}) {
|
|
|
38
39
|
const { routes } = await compileForBuild(root, buildDir, envVars);
|
|
39
40
|
logger.success(`Production compilation complete - ${routes.length} routes`);
|
|
40
41
|
|
|
41
|
-
logger.info('Step 2:
|
|
42
|
+
logger.info('Step 2: Combining ALL CSS into ONE file...');
|
|
42
43
|
await buildAllCSS(root, outDir);
|
|
43
44
|
|
|
44
45
|
logger.info('Step 3: Checking image optimization tools...');
|
|
@@ -87,15 +88,7 @@ export async function buildProduction(options = {}) {
|
|
|
87
88
|
|
|
88
89
|
logger.success('JavaScript bundled successfully');
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
logger.info('Built outputs:');
|
|
92
|
-
result.outputs.forEach((output, i) => {
|
|
93
|
-
const relativePath = relative(outDir, output.path);
|
|
94
|
-
logger.info(` ${i + 1}. ${relativePath} (${output.kind}, ${output.size} bytes)`);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
logger.info('Step 6: Generating HTML files...');
|
|
98
|
-
// ✅ CRITICAL FIX: Generate HTML files WITH CSS
|
|
91
|
+
logger.info('Step 6: Generating HTML files with SINGLE CSS...');
|
|
99
92
|
await generateProductionHTML(root, outDir, result, routes);
|
|
100
93
|
|
|
101
94
|
// Clean up build directory
|
|
@@ -108,7 +101,6 @@ export async function buildProduction(options = {}) {
|
|
|
108
101
|
logger.success(`✨ Build complete in ${duration}ms`);
|
|
109
102
|
logger.info(`📦 Output: ${outDir}`);
|
|
110
103
|
|
|
111
|
-
// Show build summary
|
|
112
104
|
logger.table(result.outputs.map(o => ({
|
|
113
105
|
file: o.path.replace(outDir, ''),
|
|
114
106
|
size: `${(o.size / 1024).toFixed(2)} KB`,
|
|
@@ -136,7 +128,7 @@ export async function buildProduction(options = {}) {
|
|
|
136
128
|
}
|
|
137
129
|
}
|
|
138
130
|
|
|
139
|
-
//
|
|
131
|
+
// SIMPLE asset copying
|
|
140
132
|
async function copyAllStaticAssets(root, outDir, optimize = true) {
|
|
141
133
|
const publicDir = join(root, 'public');
|
|
142
134
|
const srcImagesDir = join(root, 'src', 'images');
|
|
@@ -164,6 +156,8 @@ async function copyAllStaticAssets(root, outDir, optimize = true) {
|
|
|
164
156
|
logger.success('✅ All assets copied');
|
|
165
157
|
}
|
|
166
158
|
|
|
159
|
+
// COMBINE ALL CSS INTO ONE FILE
|
|
160
|
+
// COMBINE ALL CSS INTO ONE FILE - FIXED BUN API
|
|
167
161
|
async function buildAllCSS(root, outDir) {
|
|
168
162
|
const srcStylesDir = join(root, 'src', 'styles');
|
|
169
163
|
const stylesOutDir = join(outDir, 'styles');
|
|
@@ -172,15 +166,47 @@ async function buildAllCSS(root, outDir) {
|
|
|
172
166
|
|
|
173
167
|
if (existsSync(srcStylesDir)) {
|
|
174
168
|
const cssFiles = readdirSync(srcStylesDir).filter(f => f.endsWith('.css'));
|
|
175
|
-
logger.info(
|
|
169
|
+
logger.info(`📦 Found ${cssFiles.length} CSS files to combine`);
|
|
170
|
+
|
|
171
|
+
if (cssFiles.length === 0) {
|
|
172
|
+
logger.warn('⚠️ No CSS files found in src/styles/');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// COMBINE ALL CSS INTO ONE FILE
|
|
177
|
+
let combinedCSS = '';
|
|
178
|
+
let totalOriginalSize = 0;
|
|
179
|
+
|
|
176
180
|
for (const cssFile of cssFiles) {
|
|
177
181
|
const srcPath = join(srcStylesDir, cssFile);
|
|
178
|
-
const
|
|
179
|
-
await
|
|
182
|
+
const file = Bun.file(srcPath);
|
|
183
|
+
const cssContent = await file.text();
|
|
184
|
+
totalOriginalSize += file.size;
|
|
185
|
+
combinedCSS += `/* === ${cssFile} === */\n${cssContent}\n\n`;
|
|
180
186
|
}
|
|
187
|
+
|
|
188
|
+
// Write combined CSS
|
|
189
|
+
const combinedPath = join(stylesOutDir, 'bertui.min.css');
|
|
190
|
+
await Bun.write(combinedPath, combinedCSS);
|
|
191
|
+
|
|
192
|
+
// Minify it
|
|
193
|
+
const minified = await buildCSS(combinedPath, combinedPath);
|
|
194
|
+
|
|
195
|
+
// Get final size
|
|
196
|
+
const finalFile = Bun.file(combinedPath);
|
|
197
|
+
const finalSize = finalFile.size / 1024;
|
|
198
|
+
const originalSize = totalOriginalSize / 1024;
|
|
199
|
+
const savings = ((originalSize - finalSize) / originalSize * 100).toFixed(1);
|
|
200
|
+
|
|
201
|
+
logger.success(`✅ Combined ${cssFiles.length} CSS files (${originalSize.toFixed(1)}KB) → bertui.min.css (${finalSize.toFixed(1)}KB, -${savings}%)`);
|
|
202
|
+
|
|
203
|
+
} else {
|
|
204
|
+
logger.warn('⚠️ No src/styles/ directory found');
|
|
205
|
+
// Create empty CSS file so build doesn't fail
|
|
206
|
+
const emptyPath = join(stylesOutDir, 'bertui.min.css');
|
|
207
|
+
await Bun.write(emptyPath, '/* No CSS files found */');
|
|
181
208
|
}
|
|
182
209
|
}
|
|
183
|
-
|
|
184
210
|
async function compileForBuild(root, buildDir, envVars) {
|
|
185
211
|
const srcDir = join(root, 'src');
|
|
186
212
|
const pagesDir = join(srcDir, 'pages');
|
|
@@ -552,11 +578,10 @@ function extractMetaFromSource(code) {
|
|
|
552
578
|
}
|
|
553
579
|
}
|
|
554
580
|
|
|
555
|
-
//
|
|
581
|
+
// GENERATE HTML WITH SINGLE CSS FILE
|
|
556
582
|
async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
557
|
-
logger.info('Step 6: Generating HTML files with CSS...');
|
|
583
|
+
logger.info('Step 6: Generating HTML files with SINGLE CSS...');
|
|
558
584
|
|
|
559
|
-
// Find main JS bundle
|
|
560
585
|
const mainBundle = buildResult.outputs.find(o =>
|
|
561
586
|
o.path.includes('main') && o.kind === 'entry-point'
|
|
562
587
|
);
|
|
@@ -569,28 +594,6 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
|
569
594
|
const bundlePath = relative(outDir, mainBundle.path).replace(/\\/g, '/');
|
|
570
595
|
logger.info(`Main JS bundle: /${bundlePath}`);
|
|
571
596
|
|
|
572
|
-
// ✅ CRITICAL FIX: Get CSS files from DIST directory
|
|
573
|
-
const stylesOutDir = join(outDir, 'styles');
|
|
574
|
-
let cssLinks = '';
|
|
575
|
-
|
|
576
|
-
if (existsSync(stylesOutDir)) {
|
|
577
|
-
const cssFiles = readdirSync(stylesOutDir).filter(f => f.endsWith('.min.css'));
|
|
578
|
-
logger.info(`Found ${cssFiles.length} CSS files: ${cssFiles.join(', ')}`);
|
|
579
|
-
|
|
580
|
-
if (cssFiles.length > 0) {
|
|
581
|
-
// Create CSS link tags
|
|
582
|
-
cssLinks = cssFiles.map(cssFile =>
|
|
583
|
-
` <link rel="stylesheet" href="/styles/${cssFile}">`
|
|
584
|
-
).join('\n');
|
|
585
|
-
|
|
586
|
-
logger.info(`Generated CSS links:\n${cssLinks}`);
|
|
587
|
-
} else {
|
|
588
|
-
logger.warn('⚠️ No .min.css files found in dist/styles/');
|
|
589
|
-
}
|
|
590
|
-
} else {
|
|
591
|
-
logger.error('❌ dist/styles/ directory not found!');
|
|
592
|
-
}
|
|
593
|
-
|
|
594
597
|
// Load config
|
|
595
598
|
const { loadConfig } = await import('./config/loadConfig.js');
|
|
596
599
|
const config = await loadConfig(root);
|
|
@@ -598,20 +601,18 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
|
598
601
|
|
|
599
602
|
logger.info(`Generating HTML for ${routes.length} routes...`);
|
|
600
603
|
|
|
601
|
-
// Generate HTML for each route
|
|
602
604
|
for (const route of routes) {
|
|
603
605
|
try {
|
|
604
606
|
const sourceCode = await Bun.file(route.path).text();
|
|
605
607
|
const pageMeta = extractMetaFromSource(sourceCode);
|
|
606
608
|
const meta = { ...defaultMeta, ...pageMeta };
|
|
607
609
|
|
|
608
|
-
const html = generateHTML(meta, route, bundlePath
|
|
610
|
+
const html = generateHTML(meta, route, bundlePath);
|
|
609
611
|
|
|
610
612
|
let htmlPath;
|
|
611
613
|
if (route.route === '/') {
|
|
612
614
|
htmlPath = join(outDir, 'index.html');
|
|
613
615
|
} else {
|
|
614
|
-
// Remove leading slash for directory creation
|
|
615
616
|
const routeDir = join(outDir, route.route.replace(/^\//, ''));
|
|
616
617
|
mkdirSync(routeDir, { recursive: true });
|
|
617
618
|
htmlPath = join(routeDir, 'index.html');
|
|
@@ -625,10 +626,10 @@ async function generateProductionHTML(root, outDir, buildResult, routes) {
|
|
|
625
626
|
}
|
|
626
627
|
}
|
|
627
628
|
|
|
628
|
-
logger.success('✨ All HTML files generated with CSS!');
|
|
629
|
+
logger.success('✨ All HTML files generated with SINGLE CSS file!');
|
|
629
630
|
}
|
|
630
631
|
|
|
631
|
-
function generateHTML(meta, route, bundlePath
|
|
632
|
+
function generateHTML(meta, route, bundlePath) {
|
|
632
633
|
return `<!DOCTYPE html>
|
|
633
634
|
<html lang="${meta.lang || 'en'}">
|
|
634
635
|
<head>
|
|
@@ -636,7 +637,7 @@ function generateHTML(meta, route, bundlePath, cssLinks) {
|
|
|
636
637
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
637
638
|
<title>${meta.title || 'BertUI App'}</title>
|
|
638
639
|
|
|
639
|
-
<meta name="description" content="${meta.description || 'Built with BertUI'}">
|
|
640
|
+
<meta name="description" content="${meta.description || 'Built with BertUI - Lightning fast React development'}">
|
|
640
641
|
${meta.keywords ? `<meta name="keywords" content="${meta.keywords}">` : ''}
|
|
641
642
|
${meta.author ? `<meta name="author" content="${meta.author}">` : ''}
|
|
642
643
|
${meta.themeColor ? `<meta name="theme-color" content="${meta.themeColor}">` : ''}
|
|
@@ -652,11 +653,12 @@ function generateHTML(meta, route, bundlePath, cssLinks) {
|
|
|
652
653
|
<meta name="twitter:description" content="${meta.twitterDescription || meta.ogDescription || meta.description || 'Built with BertUI'}">
|
|
653
654
|
${meta.twitterImage || meta.ogImage ? `<meta name="twitter:image" content="${meta.twitterImage || meta.ogImage}">` : ''}
|
|
654
655
|
|
|
656
|
+
<!-- 🔥 ONE CSS FILE FOR ALL PAGES - NO BULLSHIT -->
|
|
657
|
+
<link rel="stylesheet" href="/styles/bertui.min.css">
|
|
658
|
+
|
|
655
659
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
|
656
660
|
<link rel="canonical" href="${route.route}">
|
|
657
661
|
|
|
658
|
-
${cssLinks}
|
|
659
|
-
|
|
660
662
|
<script type="importmap">
|
|
661
663
|
{
|
|
662
664
|
"imports": {
|