rework/lightweight #12
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"biome.searchInPath": false,
|
||||||
|
"biome.lspBin": "app/node_modules/@biomejs/biome/bin/biome",
|
||||||
|
}
|
||||||
@ -6,8 +6,16 @@ function getEnvironmentVariable<T = undefined>(key: string, defaultValue: T, for
|
|||||||
return value as T;
|
return value as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PORT = getEnvironmentVariable<number>('PORT', 3000, (data) => parseInt(data, 10));
|
function getEnvironmentVariableOrThrow<T = undefined>(key: string, formatter?: (data: string) => T): T {
|
||||||
const HMR_PORT = getEnvironmentVariable<number>('HMR_PORT', PORT + 1, (data) => parseInt(data, 10));
|
const value = process.env[key];
|
||||||
|
|
||||||
|
if (value === undefined) throw new Error(`Missing environment variable: ${key}`);
|
||||||
|
if (formatter) return formatter(value);
|
||||||
|
return value as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PORT = getEnvironmentVariableOrThrow<number>('PORT', (data) => parseInt(data, 10));
|
||||||
|
const HMR_PORT = getEnvironmentVariableOrThrow<number>('HMR_PORT', (data) => parseInt(data, 10));
|
||||||
const BASE_URL = getEnvironmentVariable<string>('BASE_URL', `http://localhost:${PORT}`);
|
const BASE_URL = getEnvironmentVariable<string>('BASE_URL', `http://localhost:${PORT}`);
|
||||||
const NODE_ENV = getEnvironmentVariable<string>('NODE_ENV', 'development');
|
const NODE_ENV = getEnvironmentVariable<string>('NODE_ENV', 'development');
|
||||||
|
|
||||||
|
|||||||
@ -1,67 +1,64 @@
|
|||||||
import { dirname } from "node:path";
|
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { dirname } from "node:path";
|
||||||
|
|
||||||
import { vikeHandler } from "./server/vike-handler";
|
|
||||||
import { telefuncHandler } from "./server/telefunc-handler";
|
|
||||||
import Fastify from "fastify";
|
|
||||||
import { createHandler } from "@universal-middleware/fastify";
|
import { createHandler } from "@universal-middleware/fastify";
|
||||||
|
import { telefuncHandler } from "./server/telefunc-handler";
|
||||||
|
import { vikeHandler } from "./server/vike-handler";
|
||||||
|
import { config } from "./config";
|
||||||
|
import Fastify from "fastify";
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = dirname(__filename);
|
const __dirname = dirname(__filename);
|
||||||
const root = __dirname;
|
const root = __dirname;
|
||||||
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000;
|
|
||||||
const hmrPort = process.env.HMR_PORT ? parseInt(process.env.HMR_PORT, 10) : 24678;
|
|
||||||
|
|
||||||
async function startServer() {
|
async function startServer() {
|
||||||
const app = Fastify();
|
const app = Fastify();
|
||||||
|
|
||||||
// Avoid pre-parsing body, otherwise it will cause issue with universal handlers
|
// Avoid pre-parsing body, otherwise it will cause issue with universal handlers
|
||||||
// This will probably change in the future though, you can follow https://github.com/magne4000/universal-middleware for updates
|
// This will probably change in the future though, you can follow https://github.com/magne4000/universal-middleware for updates
|
||||||
app.removeAllContentTypeParsers();
|
app.removeAllContentTypeParsers();
|
||||||
app.addContentTypeParser("*", function (_request, _payload, done) {
|
app.addContentTypeParser("*", (_request, _payload, done) => done(null, ""));
|
||||||
done(null, "");
|
|
||||||
});
|
|
||||||
|
|
||||||
await app.register(await import("@fastify/middie"));
|
await app.register(await import("@fastify/middie"));
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "production") {
|
if (process.env.NODE_ENV === "production") {
|
||||||
await app.register(await import("@fastify/static"), {
|
await app.register(await import("@fastify/static"), {
|
||||||
root: `${root}/dist/client`,
|
root: `${root}/dist/client`,
|
||||||
wildcard: false,
|
wildcard: false,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Instantiate Vite's development server and integrate its middleware to our server.
|
// Instantiate Vite's development server and integrate its middleware to our server.
|
||||||
// ⚠️ We should instantiate it *only* in development. (It isn't needed in production
|
// ⚠️ We should instantiate it *only* in development. (It isn't needed in production
|
||||||
// and would unnecessarily bloat our server in production.)
|
// and would unnecessarily bloat our server in production.)
|
||||||
const vite = await import("vite");
|
const vite = await import("vite");
|
||||||
const viteDevMiddleware = (
|
const viteDevMiddleware = (
|
||||||
await vite.createServer({
|
await vite.createServer({
|
||||||
root,
|
root,
|
||||||
server: { middlewareMode: true, hmr: { port: hmrPort } },
|
server: { middlewareMode: true, hmr: { port: config.HMR_PORT } },
|
||||||
})
|
})
|
||||||
).middlewares;
|
).middlewares;
|
||||||
app.use(viteDevMiddleware);
|
app.use(viteDevMiddleware);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.post<{ Body: string }>("/_telefunc", createHandler(telefuncHandler)());
|
app.post<{ Body: string }>("/_telefunc", createHandler(telefuncHandler)());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vike route
|
* Vike route
|
||||||
*
|
*
|
||||||
* @link {@see https://vike.dev}
|
* @link {@see https://vike.dev}
|
||||||
**/
|
**/
|
||||||
app.all("/*", createHandler(vikeHandler)());
|
app.all("/*", createHandler(vikeHandler)());
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = await startServer();
|
const app = await startServer();
|
||||||
|
|
||||||
app.listen(
|
app.listen({ port: config.PORT, host: "0.0.0.0" }, (error, address) => {
|
||||||
{
|
if (error) {
|
||||||
port: port,
|
app.log.error(error);
|
||||||
},
|
process.exit(1);
|
||||||
() => {
|
}
|
||||||
console.log(`Server listening on http://localhost:${port}`);
|
|
||||||
},
|
console.log(`Server listening on ${address}`);
|
||||||
);
|
});
|
||||||
|
|||||||
@ -1,50 +1,52 @@
|
|||||||
import "./style.css";
|
import type { JSX } from "solid-js";
|
||||||
|
|
||||||
import "./tailwind.css";
|
import "./tailwind.css";
|
||||||
|
|
||||||
import type { JSX } from "solid-js";
|
|
||||||
import logoUrl from "../assets/logo.svg";
|
import logoUrl from "../assets/logo.svg";
|
||||||
import { Link } from "../components/Link.js";
|
import { Link } from "../components/Link.js";
|
||||||
|
|
||||||
export default function LayoutDefault(props: { children?: JSX.Element }) {
|
export default function LayoutDefault(props: { children?: JSX.Element }) {
|
||||||
return (
|
return (
|
||||||
<div class={"flex max-w-5xl m-auto"}>
|
<div class={"flex max-w-5xl m-auto"}>
|
||||||
<Sidebar>
|
<Sidebar>
|
||||||
<Logo />
|
<Logo />
|
||||||
<Link href="/">Welcome</Link>
|
<Link href="/">Welcome</Link>
|
||||||
<Link href="/todo">Todo</Link>
|
<Link href="/todo">Todo</Link>
|
||||||
<Link href="/star-wars">Data Fetching</Link>
|
<Link href="/star-wars">Data Fetching</Link>
|
||||||
{""}
|
{""}
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
<Content>{props.children}</Content>
|
<Content>{props.children}</Content>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Sidebar(props: { children: JSX.Element }) {
|
function Sidebar(props: { children: JSX.Element }) {
|
||||||
return (
|
return (
|
||||||
<div id="sidebar" class={"p-5 flex flex-col shrink-0 border-r-2 border-r-gray-200"}>
|
<div
|
||||||
{props.children}
|
id="sidebar"
|
||||||
</div>
|
class={"p-5 flex flex-col shrink-0 border-r-2 border-r-gray-200"}
|
||||||
);
|
>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Content(props: { children: JSX.Element }) {
|
function Content(props: { children: JSX.Element }) {
|
||||||
return (
|
return (
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
<div id="page-content" class={"p-5 pb-12 min-h-screen"}>
|
<div id="page-content" class={"p-5 pb-12 min-h-screen"}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Logo() {
|
function Logo() {
|
||||||
return (
|
return (
|
||||||
<div class={"p-5 mb-2"}>
|
<div class={"p-5 mb-2"}>
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src={logoUrl} height={64} width={64} alt="logo" />
|
<img src={logoUrl} height={64} width={64} alt="logo" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
|
@import "./style.css";
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|||||||
@ -1,38 +1,39 @@
|
|||||||
{
|
{
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun ./fastify-entry.ts",
|
"dev": "bun ./fastify-entry.ts",
|
||||||
"build": "vike build",
|
"build": "vike build",
|
||||||
"preview": "cross-env NODE_ENV=production bun ./fastify-entry.ts",
|
"preview": "cross-env NODE_ENV=production bun ./fastify-entry.ts",
|
||||||
"lint": "biome lint --write .",
|
"production": "bun run build && bun run preview",
|
||||||
"format": "biome format --write ."
|
"lint": "biome lint --write .",
|
||||||
},
|
"format": "biome format --write ."
|
||||||
"dependencies": {
|
},
|
||||||
"vike": "^0.4.228",
|
"dependencies": {
|
||||||
"@fastify/middie": "^9.0.3",
|
"vike": "^0.4.228",
|
||||||
"@fastify/static": "^8.1.1",
|
"@fastify/middie": "^9.0.3",
|
||||||
"@universal-middleware/fastify": "^0.5.16",
|
"@fastify/static": "^8.1.1",
|
||||||
"fastify": "^5.3.0",
|
"@universal-middleware/fastify": "^0.5.16",
|
||||||
"@universal-middleware/core": "^0.4.7",
|
"fastify": "^5.3.0",
|
||||||
"solid-js": "^1.9.5",
|
"@universal-middleware/core": "^0.4.7",
|
||||||
"vike-solid": "^0.7.9",
|
"solid-js": "^1.9.5",
|
||||||
"telefunc": "^0.2.3"
|
"vike-solid": "^0.7.9",
|
||||||
},
|
"telefunc": "^0.2.3"
|
||||||
"devDependencies": {
|
},
|
||||||
"@biomejs/biome": "1.9.4",
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.24.0",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@tailwindcss/vite": "^4.1.3",
|
"@eslint/js": "^9.24.0",
|
||||||
"@types/node": "^18.19.86",
|
"@tailwindcss/vite": "^4.1.3",
|
||||||
"cross-env": "^7.0.3",
|
"@types/node": "^18.19.86",
|
||||||
"eslint": "^9.24.0",
|
"cross-env": "^7.0.3",
|
||||||
"eslint-config-prettier": "^10.1.2",
|
"eslint": "^9.24.0",
|
||||||
"eslint-plugin-prettier": "^5.2.6",
|
"eslint-config-prettier": "^10.1.2",
|
||||||
"eslint-plugin-solid": "^0.14.5",
|
"eslint-plugin-prettier": "^5.2.6",
|
||||||
"globals": "^16.0.0",
|
"eslint-plugin-solid": "^0.14.5",
|
||||||
"prettier": "^3.5.3",
|
"globals": "^16.0.0",
|
||||||
"tailwindcss": "^4.1.3",
|
"prettier": "^3.5.3",
|
||||||
"typescript": "^5.8.3",
|
"tailwindcss": "^4.1.3",
|
||||||
"typescript-eslint": "^8.29.1",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^6.2.6"
|
"typescript-eslint": "^8.29.1",
|
||||||
},
|
"vite": "^6.2.6"
|
||||||
"type": "module"
|
},
|
||||||
|
"type": "module"
|
||||||
}
|
}
|
||||||
@ -1,17 +1,20 @@
|
|||||||
import vikeSolid from "vike-solid/config";
|
|
||||||
import type { Config } from "vike/types";
|
import type { Config } from "vike/types";
|
||||||
|
|
||||||
|
import vikeSolid from "vike-solid/config";
|
||||||
import Layout from "../layouts/LayoutDefault.js";
|
import Layout from "../layouts/LayoutDefault.js";
|
||||||
|
|
||||||
// Default config (can be overridden by pages)
|
// Default config (can be overridden by pages)
|
||||||
// https://vike.dev/config
|
// https://vike.dev/config
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// https://vike.dev/Layout
|
// https://vike.dev/Layout
|
||||||
Layout,
|
Layout,
|
||||||
|
|
||||||
// https://vike.dev/head-tags
|
// https://vike.dev/head-tags
|
||||||
title: "My Vike App",
|
title: "My Vike App",
|
||||||
description: "Demo showcasing Vike",
|
description: "Demo showcasing Vike",
|
||||||
|
|
||||||
extends: vikeSolid,
|
prerender: true,
|
||||||
|
|
||||||
|
extends: vikeSolid,
|
||||||
} satisfies Config;
|
} satisfies Config;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://biomejs.dev/schemas/1.7.3/schema.json",
|
"$schema": "./app/node_modules/@biomejs/biome/configuration_schema.json",
|
||||||
"organizeImports": {
|
"organizeImports": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
15
compose.yml
15
compose.yml
@ -1,5 +1,5 @@
|
|||||||
services:
|
services:
|
||||||
app:
|
dev:
|
||||||
container_name: memento-dev
|
container_name: memento-dev
|
||||||
image: oven/bun:alpine
|
image: oven/bun:alpine
|
||||||
env_file:
|
env_file:
|
||||||
@ -11,3 +11,16 @@ services:
|
|||||||
- ./app:/app
|
- ./app:/app
|
||||||
working_dir: /app
|
working_dir: /app
|
||||||
command: bun run dev
|
command: bun run dev
|
||||||
|
|
||||||
|
prod:
|
||||||
|
container_name: memento-prod
|
||||||
|
image: oven/bun:alpine
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
ports:
|
||||||
|
- "${PORT}:${PORT}"
|
||||||
|
- "${HMR_PORT}:${HMR_PORT}"
|
||||||
|
volumes:
|
||||||
|
- ./app:/app
|
||||||
|
working_dir: /app
|
||||||
|
command: bun run production
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user