Skip to content

Commit

Permalink
Hacky Fix for HMR, did not like, no current alternative
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryCraft committed Jul 2, 2024
1 parent 07037cf commit e47d97d
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 85 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"dependencies": {
"@garycraft/orizuru": "^0.2.2",
"@spaceproject/findrecursive": "^1.0.4",
"axios": "^1.7.2",
"chalk": "^4.1.2",
"cookie-parser": "^1.4.6",
"discord.js": "^14.14.1",
Expand Down
7 changes: 5 additions & 2 deletions src/engine/utils/Process.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { SpawnOptionsWithoutStdio, spawn } from 'child_process';
import { clear } from './Logger';

type SpawnChildResult = {
code: number | null;
stdout: string;
stderr: string;
};

export function spawnChild(command: string, options?: SpawnOptionsWithoutStdio): Promise<SpawnChildResult> {
export function spawnChild(command: string, options?: SpawnOptionsWithoutStdio, log: boolean = false): Promise<SpawnChildResult> {
const actualCommand = command.split(" ")[0];
const args = command.split(" ").slice(1);
let p = spawn(actualCommand, args, options);
return new Promise((resolve) => {
const stdout: string[] = [];
const stderr: string[] = [];
p.stdout.on("data", (x) => {
if (log) clear(x.toString());
stdout.push(x.toString());
});
p.stderr.on("data", (x) => {
stderr.push(x.toString());
if (log) clear(x.toString());
clear(x.toString());
});
p.on("exit", (code) => {
resolve({ code, stdout: stdout.join(""), stderr: stderr.join("") });
Expand Down
164 changes: 83 additions & 81 deletions src/modules/webui/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Module from "@src/engine/modules";
import { debug, error, info } from "@src/engine/utils/Logger";
import { spawnChild } from "@src/engine/utils/Process";
import { getProcessPath, getTempPath, getWebPublicDir, isRunningAsCompiled } from "@src/engine/utils/Runtime";
import EventEmitter from "events";
import path from "path";
import EventEmitter from "node:events";
import fs from "fs-extra";
import { getAppContext } from "@src/engine/utils/Composable";
import express from "express";
import { pathToFileURL } from "url";
import { buildWebUI } from "./utilities";
import axios from "axios";

import Module from "@src/engine/modules";
import { debug, error, info } from "@src/engine/utils/Logger";
import { getProcessPath, getWebPublicDir } from "@src/engine/utils/Runtime";
import { getAppContext } from "@src/engine/utils/Composable";

import { buildWebUI, devWebUI, listenSSR } from "./utilities";


/* WebUI Module
Expand All @@ -17,39 +18,22 @@ import { buildWebUI } from "./utilities";
*/
export const WebBuildFromPath = path.join(getProcessPath(), "web");
const WebBuildToPath = path.join(getWebPublicDir());
const HMR_PORT = 1421;

export default {
name: "webui",

loadFunction: async (config) => {
return new EventEmitter();
},
initFunction: async (ctx, config) => {

const appCtx = getAppContext();
const isProduction = process.env.NODE_ENV === "production";
const HMR_PORT = appCtx.config.http.port + 1;
const isProduction = appCtx.config.node_env === "production";
const v = await import("vite");
let vite;

// When HMR is working, move this to the isProduction block
const result = await buildWebUI(WebBuildFromPath, WebBuildToPath);
if (!result) {
error("Failed to build webui");
return;
} else {
info("WebUI built successfully");
}

const clientPath = path.join(WebBuildToPath, "client");
// Expect the web build to be in the public directory
if (!fs.existsSync(clientPath)) {
error("Web build not found in public directory");
return;
}
appCtx.http.server.use(express.static("web/dist/client"));

// Watch for changes in the web directory and rebuild
fs.watch(path.join(
/* fs.watch(path.join(
WebBuildFromPath,
"src"
), { recursive: true }, async (event, filename) => {
Expand All @@ -62,13 +46,35 @@ export default {
info("WebUI built successfully");
}
}
});
/* if (isProduction) {
// provisionally empty
}); */
const ssrManifest = await fs.readFile(path.join(WebBuildToPath, '/client/.vite/ssr-manifest.json'), 'utf-8')
if (isProduction) {
const result = await buildWebUI(WebBuildFromPath, WebBuildToPath);
if (!result) {
error("Failed to build webui");
return;
} else {
info("WebUI built successfully");
}
const clientPath = path.join(WebBuildToPath, "client");
// Expect the web build to be in the public directory
if (!fs.existsSync(clientPath)) {
error("Web build not found in public directory");
return;
}
appCtx.http.server.use(express.static("web/dist/client"));

listenSSR(
appCtx.http.server,
(require(`${WebBuildToPath}/server/entry-server.js`)).render,
(await fs.readFile(path.join(WebBuildToPath, '/client/index.html'), 'utf-8')),
JSON.parse(ssrManifest)
);
} else {
// Vite dev server
// Vite dev server (HMR, NOT WORKING)
// TODO: Fix HMR
debug("Starting Vite dev server");
vite = await v.createServer({
/* vite = await v.createServer({
configFile: path.join(WebBuildFromPath, "vite.config.ts"),
root: WebBuildFromPath,
server: { middlewareMode: true, hmr: { port: HMR_PORT } },
Expand All @@ -81,54 +87,50 @@ export default {
error("Vite dev server failed to start");
return;
}
appCtx.http.server.use(viteDevMiddleware);
debug("Vite dev server started");
}
appCtx.http.server.use(viteDevMiddleware); */
/*
if (!vite) {
error("Vite not initialized")
return
}
listenSSR(
appCtx.http.server,
(
await vite.ssrLoadModule(
path.join(WebBuildFromPath, '/src/entry-server')
)
).render,
(
await vite.transformIndexHtml(
"",
await fs.readFile(path.join(WebBuildFromPath, '/index.html'), 'utf-8')
)
),
undefined
);
*/
// Start vite in dev mode
devWebUI(WebBuildFromPath, HMR_PORT)
// Forward catch-all to vite, passing along the request and return the response
appCtx.http.server.use("*", async (req, res) => {
//debug("Forwarding request to vite dev server", req.originalUrl, req.headers, req.cookies);
const response = await axios.get(`http://localhost:${HMR_PORT}${req.originalUrl}`,{
headers: req.headers,
validateStatus: () => true
}).catch((e) => {
error("Failed to forward request to vite dev server", e)
res.status(500).send("Internal Server Error")
})
if (!response) {
error("Failed to forward request to vite dev server")
res.status(500).send("Internal Server Error")
return;
}
res.status(response.status).set(response.headers).send(response.data)

if(!vite){
error("Vite not initialized")
return
});
debug("Vite dev server started");
ctx.emit("ready");
}
const template = isProduction ?
(await fs.readFile(path.join(WebBuildToPath, '/client/index.html'), 'utf-8')) :
(
await vite.transformIndexHtml(
"",
await fs.readFile(path.join(WebBuildFromPath, '/index.html'), 'utf-8')
)
)
const render = isProduction ?
(require(`${WebBuildToPath}/server/entry-server.js`)).render :
(
await vite.ssrLoadModule(
path.join(WebBuildFromPath, '/src/entry-server')
)
).render
const ssrManifest = await fs.readFile(path.join(WebBuildToPath, '/client/.vite/ssr-manifest.json'), 'utf-8')
appCtx.http.server.use('*', async (req, res) => {
try {
console.log(req.originalUrl)
const url = req.originalUrl.replace("/", '')
const { stream } = render(url, isProduction ? ssrManifest : undefined, 'utf-8')
const [htmlStart, htmlEnd] = template.split('<!--app-html-->')
res.status(200).set({ 'Content-Type': 'text/html' })
res.write(htmlStart)
for await (const chunk of stream) {
if (res.closed) break
res.write(chunk)
}
res.write(htmlEnd)
res.end()
} catch (e) {
error("Error serving web page", e)
res.status(500).send("Internal Server Error")
}
}) */
}
} satisfies Module<EventEmitter, "none">;
39 changes: 39 additions & 0 deletions src/modules/webui/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { fileURLToPath } from "url";
import fs from "fs-extra";
import { Application } from "express";
import { spawnChild } from "@src/engine/utils/Process";
import { debug, error } from "@src/engine/utils/Logger";

Expand Down Expand Up @@ -41,4 +42,42 @@ export async function buildWebUI(from: string, to: string) {
if (errored) return false;

return true;
}

export async function devWebUI(from: string, port: number) {
const fromPath = from;
// Start vite in dev mode
let errored = false;
await spawnChild(`npm run dev -- --port ${port} --host`, { cwd: fromPath }).catch((e) => {
error("Failed to start vite in dev mode", e);
errored = true;
return e;
});
if (errored) return false;
return true;
}

export function listenSSR(http: Application, render: any, template: string, ssrManifest: any) {
http.use('*', async (req, res) => {
try {
console.log(req.originalUrl)
const url = req.originalUrl.replace("/", '')
const { stream } = render(url, ssrManifest, 'utf-8')

const [htmlStart, htmlEnd] = template.split('<!--app-html-->')

res.status(200).set({ 'Content-Type': 'text/html' })

res.write(htmlStart)
for await (const chunk of stream) {
if (res.closed) break
res.write(chunk)
}
res.write(htmlEnd)
res.end()
} catch (e) {
error("Error serving web page", e)
res.status(500).send("Internal Server Error")
}
})
}
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "node server",
"dev": "vite",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --ssrManifest --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.ts --outDir dist/server",
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/NavBar.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div>
<div class="logo">
<h1>My Site</h1>
<h1>UtilityDust</h1>
</div>
<nav class="flex justify-center">
<ul class="flex space-x-4">
Expand Down
7 changes: 7 additions & 0 deletions web/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,11 @@ export default defineConfig({
outDir: '../public',
emptyOutDir: true,
},
server: {
hmr: {
port: 5002,
host: "localhost",
protocol: "http"
}
}
})

0 comments on commit e47d97d

Please sign in to comment.