ESBuild integration

This commit is contained in:
msowho 2022-07-18 01:34:22 +05:00
parent 99cf7a238c
commit 7d3d1ca229
4 changed files with 89 additions and 4 deletions

View File

@ -24,10 +24,12 @@
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.0.1",
"esbuild": "^0.14.49",
"express": "^4.17.1",
"express-rate-limit": "^6.3.0",
"ffmpeg-static": "^5.0.0",
"got": "^12.1.0",
"mime-types": "^2.1.35",
"node-cache": "^5.1.2",
"url-pattern": "^1.0.3",
"xml-js": "^1.6.11",

View File

@ -13,6 +13,10 @@ import { apiJSON } from "./modules/sub/utils.js";
import loc from "./modules/sub/i18n.js";
import { Bright, Cyan } from "./modules/sub/consoleText.js";
import stream from "./modules/stream/stream.js";
import { UUID } from "./modules/sub/crypto.js";
import { buildJS, buildCSS } from "./modules/builder.js";
import { lookup } from "mime-types";
import { Readable } from "stream";
const commitHash = shortCommit();
const app = express();
@ -109,18 +113,69 @@ if (fs.existsSync('./.env')) {
"hash": commitHash,
"type": "default",
"lang": req.header('Accept-Language') ? req.header('Accept-Language').slice(0, 2) : "en",
"useragent": req.header('user-agent') ? req.header('user-agent') : genericUserAgent
"useragent": req.header('user-agent') ? req.header('user-agent') : genericUserAgent,
"distUUID": req.app.get('currentDistUUID'),
}))
}
});
app.get("/favicon.ico", async (req, res) => {
res.redirect('/icons/favicon.ico');
});
app.head("/dist/:uuid/:file", (req, res) => {
let { uuid, file } = req.params,
dist = req.app.get(`dist~${uuid}`);
if (!dist || !dist.files.hasOwnProperty(file)) {
res.sendStatus(404);
}
res.setHeader('Content-Type', lookup(file));
res.setHeader('Content-Length', dist.files[file].length);
res.status(204);
res.end();
res.sendStatus(500);
});
app.get("/dist/:uuid/:file", (req, res) => {
let { uuid, file } = req.params,
dist = req.app.get(`dist~${uuid}`);
if (!dist || !dist.files.hasOwnProperty(file)) {
res.sendStatus(404);
}
res.setHeader('Content-Type', lookup(file));
const readableStream = Readable.from(dist.files[file]);
readableStream.pipe(res);
});
app.get("/*", async (req, res) => {
res.redirect('/')
});
app.listen(process.env.port, () => {
console.log(`\n${Bright(`${appName} (${version})`)}\n\nURL: ${Cyan(`${process.env.selfURL}`)}\nPort: ${process.env.port}\nCurrent commit: ${Bright(`${commitHash}`)}\nStart time: ${Bright(Math.floor(new Date().getTime()))}\n`)
// Building JS and CSS with builder module
Promise.all([
buildJS(),
buildCSS()
]).then(([js, css]) => {
let currentDistUUID = UUID(),
// TODO: Move deep copy to utils
currentDist = {
uuid: currentDistUUID,
files: JSON.parse(JSON.stringify(css.fontData))
};
currentDist.files[`bundle.${commitHash}.js`] = js;
currentDist.files[`bundle.${commitHash}.css`] = css.code;
// e is real 2401
app.set('currentDistUUID', currentDistUUID);
app.set(`dist~${currentDistUUID}`, currentDist);
});
});
} else {
console.log('Required config files are missing. Please run "npm run setup" first.')

29
src/modules/builder.js Normal file
View File

@ -0,0 +1,29 @@
import { readFile, readdir } from "fs/promises";
import * as esbuild from "esbuild";
export async function buildJS () {
let originalJS = await readFile('./src/static/cobalt.js', { encoding: 'utf-8' }),
transformedJS = await esbuild.transform(originalJS, { minify: true });
return transformedJS.code
}
// TODO: Make it work with new fonts
export async function buildCSS () {
let mainCSS = await readFile('./src/static/cobalt.css', { encoding: 'utf-8' }),
fontCSS = await readFile('./src/static/fonts/notosansmono/notosansmono.css', { encoding: 'utf-8' }),
fontFiles = (await readdir('./src/static/fonts/notosansmono/')).filter((f) => f.endsWith('.woff2')),
transformedCSS = await esbuild.transform(fontCSS + mainCSS, { minify: true, loader: 'css' });
const fontData = {}
for (let index in fontFiles) {
const filename = fontFiles[index]
fontData[filename] = await readFile(`./src/static/fonts/notosansmono/${filename}`, { encoding: 'utf-8' })
}
return {
code: transformedCSS.code,
fontData: fontData
}
}

View File

@ -47,8 +47,7 @@ export default function(obj) {
<link rel="apple-touch-icon" sizes="180x180" href="icons/apple-touch-icon.png" />
<link rel="manifest" href="cobalt.webmanifest" />
<link rel="stylesheet" href="cobalt.css" />
<link rel="stylesheet" href="fonts/notosansmono/notosansmono.css" />
<link rel="stylesheet" href="dist/${obj.distUUID}/bundle.${obj.hash}.css" />
<noscript><div style="margin: 2rem;">${loc(obj.lang, 'strings', 'noScript')}</div></noscript>
</head>
@ -194,7 +193,7 @@ export default function(obj) {
</footer>
</body>
<script type="text/javascript">const loc = {noInternet:"${loc(obj.lang, 'apiError', 'noInternet')}"}</script>
<script type="text/javascript" src="cobalt.js"></script>
<script type="text/javascript" src="dist/${obj.distUUID}/bundle.${obj.hash}.js"></script>
</html>`;
} catch (err) {
return `${loc('en', 'apiError', 'noRender', obj.hash)}`;