Skip to content

Commit

Permalink
feat: bump deps, clean up code, serve static assets correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
jonluca committed Oct 3, 2023
1 parent b98b9b7 commit 11516fb
Show file tree
Hide file tree
Showing 15 changed files with 1,518 additions and 1,644 deletions.
1 change: 0 additions & 1 deletion gpg

This file was deleted.

14 changes: 7 additions & 7 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
Expand All @@ -8,18 +8,18 @@
name="viewport"
/>
<meta content="text/html; charset=utf-8" http-equiv="content-type" />

<!--head-->
<!-- ### Manifest and icons ### -->
<!-- General -->
<link rel="manifest" href="/static/site.webmanifest" />
<link rel="manifest" href="/site.webmanifest" />
<meta name="theme-color" content="#ffffff" />
<meta name="application-name" content="App" />
<link rel="shortcut icon" href="/static/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<!-- Apple -->
<meta name="apple-mobile-web-app-title" content="App" />
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
</head>
<body>
<div id="app" style="height: 100%; width: 100%"><!--app-html--></div>
Expand Down
62 changes: 31 additions & 31 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "vite-typescript-ssr-react",
"version": "1.0.1",
"type": "module",
"description": "Boilerplate for a modern web stack",
"repository": {
"type": "git",
Expand All @@ -9,61 +10,60 @@
"author": "JonLuca DeCaro",
"license": "MIT",
"scripts": {
"dev:server": "nodemon --watch server.ts --watch src/server --exec 'ts-node server.ts'",
"dev:server": "tsx server.ts",
"dev:client": "yarn build:client && vite --config vite.config.ts dev",
"build": "rimraf dist && tsc -p tsconfig.prod.json && yarn build:client && yarn build:server && yarn copy-files",
"build": "rimraf dist && tsc -p tsconfig.json && yarn build:client && yarn build:server && yarn copy-files",
"build:client": "vite build --outDir dist/client --ssrManifest",
"build:server": "vite build --ssr src/client/entry-server.tsx --outDir dist/server",
"test": "vitest",
"test:watch": "vitest --watch",
"coverage": "vitest --coverage",
"typecheck": "tsc --noEmit",
"serve": "yarn build && cross-env NODE_ENV=production yarn ts-node ./server",
"serve": "yarn build && cross-env NODE_ENV=production node ./dist/server",
"serve:local": "vite serve",
"clean": "rimraf dist/",
"copy-files": "copyfiles static/* dist/assets && copyfiles index.html dist && copyfiles -f dist/client/assets/* dist/assets",
"copy-files": "copyfiles \"public/**/*\" dist && copyfiles -u 2 \"dist/client/**/*\" dist && copyfiles -u 2 \"dist/client/assets/**/*\" dist/public",
"format": "prettier --write ."
},
"dependencies": {
"autoprefixer": "^10.4.14",
"autoprefixer": "^10.4.16",
"compression": "1.7.4",
"cross-env": "^7.0.3",
"express": "4.18.2",
"nodemon": "^2.0.22",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.10.0",
"react-router-dom": "^6.16.0",
"serve-static": "^1.15.0",
"ts-node": "^10.9.1"
"tsx": "^3.13.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^14.0.0",
"@types/compression": "1.7.2",
"@types/compression": "1.7.3",
"@types/concurrently": "6.4.0",
"@types/eslint": "8.37.0",
"@types/express": "^4.17.17",
"@types/node": "18.15.12",
"@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11",
"@types/eslint": "8.44.3",
"@types/express": "^4.17.18",
"@types/node": "20.8.2",
"@types/react": "^18.2.24",
"@types/react-dom": "^18.2.8",
"@types/react-router-dom": "^5.3.3",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"@vitejs/plugin-react": "^4.0.0",
"concurrently": "8.0.1",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"@vitejs/plugin-react": "^4.1.0",
"concurrently": "8.2.1",
"copyfiles": "^2.4.1",
"eslint": "^8.38.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-react": "^7.32.2",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"jsdom": "^21.1.1",
"postcss": "8.4.23",
"prettier": "^2.8.7",
"rimraf": "^5.0.0",
"tailwindcss": "3.3.1",
"typescript": "5.0.4",
"vite": "4.3.0",
"vitest": "^0.30.1"
"jsdom": "^22.1.0",
"postcss": "8.4.31",
"prettier": "^3.0.3",
"rimraf": "^5.0.5",
"tailwindcss": "3.3.3",
"typescript": "5.2.2",
"vite": "4.4.10",
"vitest": "^0.34.6"
}
}
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
36 changes: 22 additions & 14 deletions server.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import type { Request, Response, NextFunction } from "express";
import fs from "fs/promises";
import path from "path";
import path, { dirname } from "path";
import express from "express";
import compression from "compression";
import serveStatic from "serve-static";
import { createServer as createViteServer } from "vite";
import { fileURLToPath } from "url";
const isTest = process.env.NODE_ENV === "test" || !!process.env.VITE_TEST_BUILD;

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const resolve = (p: string) => path.resolve(__dirname, p);

const getStyleSheets = async () => {
try {
const assetpath = resolve("dist/assets");
const assetpath = resolve("public");
const files = await fs.readdir(assetpath);
const cssAssets = files.filter(l => l.endsWith(".css"));
const allContent = [];
Expand All @@ -34,48 +38,52 @@ async function createServer(isProd = process.env.NODE_ENV === "production") {
server: { middlewareMode: true },
appType: "custom",
logLevel: isTest ? "error" : "info",
root: isProd ? "dist" : "",
optimizeDeps: { include: [] },
});

// use vite's connect instance as middleware
// if you use your own express router (express.Router()), you should use router.use
app.use(vite.middlewares);
const requestHandler = express.static(resolve("assets"));
const assetsDir = resolve("public");
const requestHandler = express.static(assetsDir);
app.use(requestHandler);
app.use("/assets", requestHandler);
app.use("/public", requestHandler);

if (isProd) {
app.use(compression());
app.use(
serveStatic(resolve("dist/client"), {
serveStatic(resolve("client"), {
index: false,
}),
);
}
const stylesheets = getStyleSheets();

// 1. Read index.html
const baseTemplate = await fs.readFile(isProd ? resolve("client/index.html") : resolve("index.html"), "utf-8");
const productionBuildPath = path.join(__dirname, "./server/entry-server.js");
const devBuildPath = path.join(__dirname, "./src/client/entry-server.tsx");
const buildModule = isProd ? productionBuildPath : devBuildPath;
const { render } = await vite.ssrLoadModule(buildModule);

app.use("*", async (req: Request, res: Response, next: NextFunction) => {
const url = req.originalUrl;

try {
// 1. Read index.html
let template = await fs.readFile(isProd ? resolve("dist/client/index.html") : resolve("index.html"), "utf-8");

// 2. Apply Vite HTML transforms. This injects the Vite HMR client, and
// also applies HTML transforms from Vite plugins, e.g. global preambles
// from @vitejs/plugin-react
template = await vite.transformIndexHtml(url, template);

const template = await vite.transformIndexHtml(url, baseTemplate);
// 3. Load the server entry. vite.ssrLoadModule automatically transforms
// your ESM source code to be usable in Node.js! There is no bundling
// required, and provides efficient invalidation similar to HMR.
let productionBuildPath = path.join(__dirname, "./dist/server/entry-server.mjs");
let devBuildPath = path.join(__dirname, "./src/client/entry-server.tsx");
const { render } = await vite.ssrLoadModule(isProd ? productionBuildPath : devBuildPath);

// 4. render the app HTML. This assumes entry-server.js's exported `render`
// function calls appropriate framework SSR APIs,
// e.g. ReactDOMServer.renderToString()
const appHtml = await render(url);
const cssAssets = isProd ? "" : await stylesheets;
const cssAssets = await stylesheets;

// 5. Inject the app-rendered HTML into the template.
const html = template.replace(`<!--app-html-->`, appHtml).replace(`<!--head-->`, cssAssets);
Expand Down
6 changes: 0 additions & 6 deletions tsconfig.prod.json

This file was deleted.

3 changes: 1 addition & 2 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ const test = {
} as UserConfig["test"];

// https://vitejs.dev/config/
const isProd = process.env.NODE_ENV === "production";
export default defineConfig({
plugins: [react()],
server: { port: 3000 },
build: {
minify: false,
},
root: "",
// @ts-ignore
test,
});
Loading

1 comment on commit 11516fb

@vercel
Copy link

@vercel vercel bot commented on 11516fb Oct 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.