Skip to content

Commit ae70493

Browse files
authored
refactor(socket.io): Switch to V2 + Vite (#490)
1 parent 35dfc53 commit ae70493

File tree

11 files changed

+246
-147
lines changed

11 files changed

+246
-147
lines changed

socket.io/.eslintrc.cjs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* This is intended to be a basic starting point for linting in your app.
3+
* It relies on recommended configs out of the box for simplicity, but you can
4+
* and should modify this configuration to best suit your team's needs.
5+
*/
6+
7+
/** @type {import('eslint').Linter.Config} */
8+
module.exports = {
9+
root: true,
10+
parserOptions: {
11+
ecmaVersion: "latest",
12+
sourceType: "module",
13+
ecmaFeatures: {
14+
jsx: true,
15+
},
16+
},
17+
env: {
18+
browser: true,
19+
commonjs: true,
20+
es6: true,
21+
},
22+
ignorePatterns: ["!**/.server", "!**/.client"],
23+
24+
// Base config
25+
extends: ["eslint:recommended"],
26+
27+
overrides: [
28+
// React
29+
{
30+
files: ["**/*.{js,jsx,ts,tsx}"],
31+
plugins: ["react", "jsx-a11y"],
32+
extends: [
33+
"plugin:react/recommended",
34+
"plugin:react/jsx-runtime",
35+
"plugin:react-hooks/recommended",
36+
"plugin:jsx-a11y/recommended",
37+
],
38+
settings: {
39+
react: {
40+
version: "detect",
41+
},
42+
formComponents: ["Form"],
43+
linkComponents: [
44+
{ name: "Link", linkAttribute: "to" },
45+
{ name: "NavLink", linkAttribute: "to" },
46+
],
47+
"import/resolver": {
48+
typescript: {},
49+
},
50+
},
51+
},
52+
53+
// Typescript
54+
{
55+
files: ["**/*.{ts,tsx}"],
56+
plugins: ["@typescript-eslint", "import"],
57+
parser: "@typescript-eslint/parser",
58+
settings: {
59+
"import/internal-regex": "^~/",
60+
"import/resolver": {
61+
node: {
62+
extensions: [".ts", ".tsx"],
63+
},
64+
typescript: {
65+
alwaysTryTypes: true,
66+
},
67+
},
68+
},
69+
extends: [
70+
"plugin:@typescript-eslint/recommended",
71+
"plugin:import/recommended",
72+
"plugin:import/typescript",
73+
],
74+
},
75+
76+
// Node
77+
{
78+
files: [".eslintrc.cjs", "server.js"],
79+
env: {
80+
node: true,
81+
},
82+
},
83+
],
84+
};

socket.io/.eslintrc.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

socket.io/.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
node_modules
22

33
/.cache
4-
/server/build
5-
/public/build
4+
/build
65
.env

socket.io/app/root.tsx

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import type { MetaFunction } from "@remix-run/node";
21
import {
32
Links,
4-
LiveReload,
53
Meta,
64
Outlet,
75
Scripts,
@@ -13,11 +11,23 @@ import io from "socket.io-client";
1311

1412
import { SocketProvider } from "~/context";
1513

16-
export const meta: MetaFunction = () => ({
17-
charset: "utf-8",
18-
title: "New Remix App",
19-
viewport: "width=device-width,initial-scale=1",
20-
});
14+
export function Layout({ children }: { children: React.ReactNode }) {
15+
return (
16+
<html lang="en">
17+
<head>
18+
<meta charSet="utf-8" />
19+
<meta name="viewport" content="width=device-width, initial-scale=1" />
20+
<Meta />
21+
<Links />
22+
</head>
23+
<body>
24+
{children}
25+
<ScrollRestoration />
26+
<Scripts />
27+
</body>
28+
</html>
29+
);
30+
}
2131

2232
export default function App() {
2333
const [socket, setSocket] = useState<Socket>();
@@ -38,19 +48,7 @@ export default function App() {
3848
}, [socket]);
3949

4050
return (
41-
<html lang="en">
42-
<head>
43-
<Meta />
44-
<Links />
45-
</head>
46-
<body>
47-
<SocketProvider socket={socket}>
48-
<Outlet />
49-
</SocketProvider>
50-
<ScrollRestoration />
51-
<Scripts />
52-
<LiveReload />
53-
</body>
54-
</html>
55-
);
51+
<SocketProvider socket={socket}>
52+
<Outlet />
53+
</SocketProvider>);
5654
}

socket.io/package.json

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,49 @@
11
{
2+
"name": "eps",
23
"private": true,
34
"sideEffects": false,
5+
"type": "module",
46
"scripts": {
5-
"build": "remix build",
6-
"dev": "remix watch",
7-
"start": "cross-env NODE_ENV=production node server/index.js",
8-
"start:dev": "cross-env NODE_ENV=development node server/index.js",
7+
"build": "remix vite:build",
8+
"dev": "node ./server.js",
9+
"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
10+
"start": "cross-env NODE_ENV=production node ./server.js",
911
"typecheck": "tsc"
1012
},
1113
"dependencies": {
12-
"@remix-run/express": "^1.19.3",
13-
"@remix-run/node": "^1.19.3",
14-
"@remix-run/react": "^1.19.3",
14+
"@remix-run/express": "^2.9.2",
15+
"@remix-run/node": "^2.9.2",
16+
"@remix-run/react": "^2.9.2",
1517
"compression": "^1.7.4",
16-
"cross-env": "^7.0.3",
17-
"express": "^4.17.3",
18+
"express": "^4.18.2",
19+
"isbot": "^4.1.0",
1820
"morgan": "^1.10.0",
19-
"isbot": "^3.6.5",
2021
"react": "^18.2.0",
2122
"react-dom": "^18.2.0",
22-
"socket.io": "^4.4.1",
23-
"socket.io-client": "^4.4.1"
23+
"socket.io": "^4.7.5",
24+
"socket.io-client": "^4.7.5"
2425
},
2526
"devDependencies": {
26-
"@remix-run/dev": "^1.19.3",
27-
"@remix-run/eslint-config": "^1.19.3",
28-
"@types/react": "^18.0.25",
29-
"@types/react-dom": "^18.0.8",
30-
"eslint": "^8.27.0",
31-
"typescript": "^4.8.4"
27+
"@remix-run/dev": "^2.9.2",
28+
"@types/compression": "^1.7.5",
29+
"@types/express": "^4.17.20",
30+
"@types/morgan": "^1.9.9",
31+
"@types/react": "^18.2.20",
32+
"@types/react-dom": "^18.2.7",
33+
"@typescript-eslint/eslint-plugin": "^6.7.4",
34+
"@typescript-eslint/parser": "^6.7.4",
35+
"cross-env": "^7.0.3",
36+
"eslint": "^8.38.0",
37+
"eslint-import-resolver-typescript": "^3.6.1",
38+
"eslint-plugin-import": "^2.28.1",
39+
"eslint-plugin-jsx-a11y": "^6.7.1",
40+
"eslint-plugin-react": "^7.33.2",
41+
"eslint-plugin-react-hooks": "^4.6.0",
42+
"typescript": "^5.1.6",
43+
"vite": "^5.1.0",
44+
"vite-tsconfig-paths": "^4.2.1"
3245
},
3346
"engines": {
34-
"node": ">=14.0.0"
47+
"node": ">=20.0.0"
3548
}
36-
}
49+
}

socket.io/remix.config.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

socket.io/remix.env.d.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

socket.io/server.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { createRequestHandler } from "@remix-run/express";
2+
import compression from "compression";
3+
import express from "express";
4+
import morgan from "morgan";
5+
import { createServer } from "http";
6+
import { Server } from "socket.io";
7+
8+
const viteDevServer =
9+
process.env.NODE_ENV === "production"
10+
? undefined
11+
: await import("vite").then((vite) =>
12+
vite.createServer({
13+
server: { middlewareMode: true },
14+
})
15+
);
16+
17+
const remixHandler = createRequestHandler({
18+
build: viteDevServer
19+
? () => viteDevServer.ssrLoadModule("virtual:remix/server-build")
20+
: await import("./build/server/index.js"),
21+
});
22+
23+
const app = express();
24+
25+
// You need to create the HTTP server from the Express app
26+
const httpServer = createServer(app);
27+
28+
// And then attach the socket.io server to the HTTP server
29+
const io = new Server(httpServer);
30+
31+
// Then you can use `io` to listen the `connection` event and get a socket
32+
// from a client
33+
io.on("connection", (socket) => {
34+
// from this point you are on the WS connection with a specific client
35+
console.log(socket.id, "connected");
36+
37+
socket.emit("confirmation", "connected!");
38+
39+
socket.on("event", (data) => {
40+
console.log(socket.id, data);
41+
socket.emit("event", "pong");
42+
});
43+
});
44+
45+
46+
app.use(compression());
47+
48+
// http://expressjs.com/en/advanced/best-practice-security.html#at-a-minimum-disable-x-powered-by-header
49+
app.disable("x-powered-by");
50+
51+
// handle asset requests
52+
if (viteDevServer) {
53+
app.use(viteDevServer.middlewares);
54+
} else {
55+
// Vite fingerprints its assets so we can cache forever.
56+
app.use(
57+
"/assets",
58+
express.static("build/client/assets", { immutable: true, maxAge: "1y" })
59+
);
60+
}
61+
62+
// Everything else (like favicon.ico) is cached for an hour. You may want to be
63+
// more aggressive with this caching.
64+
app.use(express.static("build/client", { maxAge: "1h" }));
65+
66+
app.use(morgan("tiny"));
67+
68+
// handle SSR requests
69+
app.all("*", remixHandler);
70+
71+
const port = process.env.PORT || 3000;
72+
73+
// instead of running listen on the Express app, do it on the HTTP server
74+
httpServer.listen(port, () => {
75+
console.log(`Express server listening at http://localhost:${port}`)
76+
});
77+

0 commit comments

Comments
 (0)