56 lines
2.1 KiB
JavaScript
56 lines
2.1 KiB
JavaScript
// 極簡靜態伺服器:服務 client/dist(前端 build 產物),並把 /api 代理到後端 :3000
|
||
// 用法:node scripts/serve_dist.js [port] (預設 5173)
|
||
const http = require('http');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const port = parseInt(process.argv[2] || '5173', 10);
|
||
const backendPort = parseInt(process.argv[3] || '3000', 10);
|
||
const distDir = path.resolve(__dirname, '../client/dist');
|
||
const types = {
|
||
'.html': 'text/html; charset=utf-8',
|
||
'.js': 'application/javascript; charset=utf-8',
|
||
'.css': 'text/css; charset=utf-8',
|
||
'.json': 'application/json',
|
||
'.png': 'image/png',
|
||
'.svg': 'image/svg+xml',
|
||
'.ico': 'image/x-icon',
|
||
'.map': 'application/json'
|
||
};
|
||
|
||
if (!fs.existsSync(distDir)) {
|
||
console.error('找不到 client/dist,請先執行 scripts/build_frontend.ps1');
|
||
process.exit(1);
|
||
}
|
||
|
||
// /api -> 後端 proxy
|
||
function proxyApi(req, res) {
|
||
const proxyReq = http.request({
|
||
host: 'localhost',
|
||
port: backendPort,
|
||
path: req.url,
|
||
method: req.method,
|
||
headers: Object.assign({}, req.headers, { host: 'localhost:' + backendPort })
|
||
}, (proxyRes) => {
|
||
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
||
proxyRes.pipe(res);
|
||
});
|
||
proxyReq.on('error', (e) => { res.writeHead(502); res.end('Bad Gateway: ' + e.message); });
|
||
req.pipe(proxyReq);
|
||
}
|
||
|
||
const server = http.createServer((req, res) => {
|
||
if (req.url.startsWith('/api')) { proxyApi(req, res); return; }
|
||
let urlPath = decodeURIComponent(req.url.split('?')[0]);
|
||
if (urlPath === '/') urlPath = '/index.html';
|
||
const filePath = path.join(distDir, urlPath);
|
||
if (!filePath.startsWith(distDir)) { res.writeHead(403); res.end('Forbidden'); return; }
|
||
if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) { res.writeHead(404); res.end('Not Found'); return; }
|
||
res.writeHead(200, { 'Content-Type': types[path.extname(filePath)] || 'application/octet-stream' });
|
||
fs.createReadStream(filePath).pipe(res);
|
||
});
|
||
|
||
server.listen(port, () => {
|
||
console.log('靜態伺服器啟動於 http://localhost:' + port + '(服務 client/dist,/api 代理至 :' + backendPort + ')');
|
||
});
|