angular-cn/aio/tools/prerender/serve.js

64 lines
1.6 KiB
JavaScript

'use strict';
// Imports
const fs = require('fs');
const http = require('http');
const path = require('path');
const { BASE_URL, DIST_DIR, PORT } = require('./constants');
// Constants
const CONTENT_TYPES = {
'.css': 'text/css',
'.html': 'text/html',
'.ico': 'image/x-icon',
'.jpg': 'image/jpeg',
'.js': 'text/javascript',
'.json': 'application/json',
'.png': 'image/png',
'.svg': 'image/svg+xml'
};
const CACHE = {};
const VERBOSE = process.argv.includes('--verbose');
// Helpers
const urlToFile = url => path.join(DIST_DIR, url);
const getFile = filePath => new Promise((resolve, reject) => CACHE.hasOwnProperty(filePath) ?
resolve(CACHE[filePath]) :
fs.readFile(filePath, 'utf-8', (err, content) => err ? reject(err) : resolve(CACHE[filePath] = content)));
const middleware = (req, res) => {
const method = req.method;
let url = req.url;
if (VERBOSE) console.log(`Request: ${method} ${url}`);
if (method !== 'GET') return;
if (url.endsWith('/')) url += 'index';
if (!url.includes('.')) url += '.html';
let filePath = urlToFile(url);
if (!fs.existsSync(filePath)) filePath = urlToFile('index.html');
getFile(filePath).
then(content => {
const contentType = CONTENT_TYPES[path.extname(filePath)] || 'application/octet-stream';
res.setHeader('Content-Type', contentType);
res.end(content);
}).
catch(err => {
console.error(err);
res.statusCode = 500;
res.end(http.STATUS_CODES[500]);
});
};
// Run
const server = http.
createServer(middleware).
on('error', err => console.error(err)).
on('listening', () => console.log(`Server listening at ${BASE_URL}.`)).
listen(PORT);