init commit
This commit is contained in:
279
.history/scripts/build_20251019162023.js
Normal file
279
.history/scripts/build_20251019162023.js
Normal file
@@ -0,0 +1,279 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Build script for production deployment
|
||||
* Handles CSS compilation, asset optimization, and production setup
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { exec } = require('child_process');
|
||||
const { promisify } = require('util');
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
// Configuration
|
||||
const BUILD_DIR = path.join(__dirname, '..', 'dist');
|
||||
const PUBLIC_DIR = path.join(__dirname, '..', 'public');
|
||||
const VIEWS_DIR = path.join(__dirname, '..', 'views');
|
||||
|
||||
async function buildForProduction() {
|
||||
try {
|
||||
console.log('🏗️ Starting production build...');
|
||||
|
||||
// Create build directory
|
||||
await createBuildDirectory();
|
||||
|
||||
// Install production dependencies
|
||||
await installProductionDependencies();
|
||||
|
||||
// Optimize assets
|
||||
await optimizeAssets();
|
||||
|
||||
// Generate service worker with workbox
|
||||
await generateServiceWorker();
|
||||
|
||||
// Create production environment file
|
||||
await createProductionEnv();
|
||||
|
||||
// Copy necessary files
|
||||
await copyProductionFiles();
|
||||
|
||||
console.log('✅ Production build completed successfully!');
|
||||
console.log('📦 Build output available in:', BUILD_DIR);
|
||||
console.log('🚀 Ready for deployment!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Production build failed:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function createBuildDirectory() {
|
||||
try {
|
||||
if (fs.existsSync(BUILD_DIR)) {
|
||||
console.log('🗑️ Cleaning existing build directory...');
|
||||
await execAsync(`rm -rf ${BUILD_DIR}`);
|
||||
}
|
||||
|
||||
fs.mkdirSync(BUILD_DIR, { recursive: true });
|
||||
console.log('📁 Created build directory');
|
||||
} catch (error) {
|
||||
console.error('❌ Error creating build directory:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function installProductionDependencies() {
|
||||
try {
|
||||
console.log('📦 Installing production dependencies...');
|
||||
await execAsync('npm ci --only=production');
|
||||
console.log('✅ Production dependencies installed');
|
||||
} catch (error) {
|
||||
console.error('❌ Error installing dependencies:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function optimizeAssets() {
|
||||
try {
|
||||
console.log('🎨 Optimizing CSS and JavaScript...');
|
||||
|
||||
// Create optimized CSS
|
||||
const cssContent = fs.readFileSync(path.join(PUBLIC_DIR, 'css', 'main.css'), 'utf8');
|
||||
const optimizedCSS = await optimizeCSS(cssContent);
|
||||
|
||||
const buildCSSDir = path.join(BUILD_DIR, 'public', 'css');
|
||||
fs.mkdirSync(buildCSSDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(buildCSSDir, 'main.min.css'), optimizedCSS);
|
||||
|
||||
// Create optimized JavaScript
|
||||
const jsContent = fs.readFileSync(path.join(PUBLIC_DIR, 'js', 'main.js'), 'utf8');
|
||||
const optimizedJS = await optimizeJS(jsContent);
|
||||
|
||||
const buildJSDir = path.join(BUILD_DIR, 'public', 'js');
|
||||
fs.mkdirSync(buildJSDir, { recursive: true });
|
||||
fs.writeFileSync(path.join(buildJSDir, 'main.min.js'), optimizedJS);
|
||||
|
||||
// Copy other assets
|
||||
await copyDirectory(path.join(PUBLIC_DIR, 'images'), path.join(BUILD_DIR, 'public', 'images'));
|
||||
|
||||
console.log('✅ Assets optimized');
|
||||
} catch (error) {
|
||||
console.error('❌ Error optimizing assets:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function optimizeCSS(css) {
|
||||
// Simple CSS minification (remove comments, extra whitespace)
|
||||
return css
|
||||
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove comments
|
||||
.replace(/\s{2,}/g, ' ') // Replace multiple spaces with single space
|
||||
.replace(/;\s*}/g, '}') // Remove semicolon before closing brace
|
||||
.replace(/\s*{\s*/g, '{') // Remove spaces around opening brace
|
||||
.replace(/;\s*/g, ';') // Remove spaces after semicolons
|
||||
.replace(/,\s*/g, ',') // Remove spaces after commas
|
||||
.trim();
|
||||
}
|
||||
|
||||
async function optimizeJS(js) {
|
||||
// Simple JS minification (remove comments, extra whitespace)
|
||||
return js
|
||||
.replace(/\/\/.*$/gm, '') // Remove single-line comments
|
||||
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove multi-line comments
|
||||
.replace(/\s{2,}/g, ' ') // Replace multiple spaces with single space
|
||||
.replace(/\n\s*/g, '') // Remove newlines and indentation
|
||||
.trim();
|
||||
}
|
||||
|
||||
async function generateServiceWorker() {
|
||||
try {
|
||||
console.log('⚙️ Generating optimized service worker...');
|
||||
|
||||
const swContent = fs.readFileSync(path.join(PUBLIC_DIR, 'sw.js'), 'utf8');
|
||||
const optimizedSW = await optimizeJS(swContent);
|
||||
|
||||
fs.writeFileSync(path.join(BUILD_DIR, 'public', 'sw.js'), optimizedSW);
|
||||
|
||||
// Copy manifest
|
||||
fs.copyFileSync(
|
||||
path.join(PUBLIC_DIR, 'manifest.json'),
|
||||
path.join(BUILD_DIR, 'public', 'manifest.json')
|
||||
);
|
||||
|
||||
console.log('✅ Service worker generated');
|
||||
} catch (error) {
|
||||
console.error('❌ Error generating service worker:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function createProductionEnv() {
|
||||
try {
|
||||
console.log('🔧 Creating production environment configuration...');
|
||||
|
||||
const prodEnv = `
|
||||
# Production Environment Configuration
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
|
||||
# Database
|
||||
MONGODB_URI=mongodb://localhost:27017/smartsoltech
|
||||
|
||||
# Security
|
||||
SESSION_SECRET=your-super-secret-session-key-change-this-in-production
|
||||
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
|
||||
|
||||
# File Upload
|
||||
UPLOAD_PATH=./uploads
|
||||
MAX_FILE_SIZE=10485760
|
||||
|
||||
# Email Configuration
|
||||
SMTP_HOST=smtp.gmail.com
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=your-email@gmail.com
|
||||
SMTP_PASS=your-app-password
|
||||
|
||||
# Telegram Bot (Optional)
|
||||
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
|
||||
|
||||
# Admin Account
|
||||
ADMIN_EMAIL=admin@smartsoltech.kr
|
||||
ADMIN_PASSWORD=change-this-password
|
||||
|
||||
# Security Headers
|
||||
RATE_LIMIT_WINDOW_MS=900000
|
||||
RATE_LIMIT_MAX_REQUESTS=100
|
||||
`.trim();
|
||||
|
||||
fs.writeFileSync(path.join(BUILD_DIR, '.env.production'), prodEnv);
|
||||
console.log('✅ Production environment file created');
|
||||
} catch (error) {
|
||||
console.error('❌ Error creating production environment:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function copyProductionFiles() {
|
||||
try {
|
||||
console.log('📋 Copying production files...');
|
||||
|
||||
// Copy main application files
|
||||
const filesToCopy = [
|
||||
'server.js',
|
||||
'package.json',
|
||||
'package-lock.json'
|
||||
];
|
||||
|
||||
for (const file of filesToCopy) {
|
||||
fs.copyFileSync(
|
||||
path.join(__dirname, '..', file),
|
||||
path.join(BUILD_DIR, file)
|
||||
);
|
||||
}
|
||||
|
||||
// Copy directories
|
||||
await copyDirectory(
|
||||
path.join(__dirname, '..', 'models'),
|
||||
path.join(BUILD_DIR, 'models')
|
||||
);
|
||||
|
||||
await copyDirectory(
|
||||
path.join(__dirname, '..', 'routes'),
|
||||
path.join(BUILD_DIR, 'routes')
|
||||
);
|
||||
|
||||
await copyDirectory(
|
||||
path.join(__dirname, '..', 'views'),
|
||||
path.join(BUILD_DIR, 'views')
|
||||
);
|
||||
|
||||
await copyDirectory(
|
||||
path.join(__dirname, '..', 'middleware'),
|
||||
path.join(BUILD_DIR, 'middleware')
|
||||
);
|
||||
|
||||
// Create uploads directory
|
||||
fs.mkdirSync(path.join(BUILD_DIR, 'uploads'), { recursive: true });
|
||||
|
||||
console.log('✅ Production files copied');
|
||||
} catch (error) {
|
||||
console.error('❌ Error copying production files:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function copyDirectory(src, dest) {
|
||||
try {
|
||||
if (!fs.existsSync(src)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
|
||||
const items = fs.readdirSync(src);
|
||||
|
||||
for (const item of items) {
|
||||
const srcPath = path.join(src, item);
|
||||
const destPath = path.join(dest, item);
|
||||
|
||||
const stat = fs.statSync(srcPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
await copyDirectory(srcPath, destPath);
|
||||
} else {
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Error copying directory ${src}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
buildForProduction();
|
||||
}
|
||||
|
||||
module.exports = { buildForProduction };
|
||||
Reference in New Issue
Block a user