Skip to content

Commit fa75c7d

Browse files
docs: rework of the tutorial
1 parent 08cf30a commit fa75c7d

33 files changed

+3989
-9
lines changed

docs/tutorial/01-introduction.md

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
title: Tutorial - Introduction
3+
sidebar_label: Introduction
4+
slug: introduction
5+
---
6+
7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
10+
# Getting started
11+
12+
Welcome to the Socket.IO tutorial!
13+
14+
In this tutorial we'll create a basic chat application. It requires almost no basic prior knowledge of Node.JS or Socket.IO, so it’s ideal for users of all knowledge levels.
15+
16+
## Introduction
17+
18+
Writing a chat application with popular web applications stacks like LAMP (PHP) has normally been very hard. It involves polling the server for changes, keeping track of timestamps, and it’s a lot slower than it should be.
19+
20+
Sockets have traditionally been the solution around which most real-time chat systems are architected, providing a bi-directional communication channel between a client and a server.
21+
22+
This means that the server can *push* messages to clients. Whenever you write a chat message, the idea is that the server will get it and push it to all other connected clients.
23+
24+
## How to use this tutorial
25+
26+
### Tooling
27+
28+
Any text editor (from a basic text editor to a complete IDE such as [VS Code](https://code.visualstudio.com/)) should be sufficient to complete this tutorial.
29+
30+
Additionally, at the end of each step you will find a link to some online platforms ([CodeSandbox](https://codesandbox.io) and [StackBlitz](https://stackblitz.com), namely), allowing you to run the code directly from your browser:
31+
32+
![Screenshot of the CodeSandbox platform](/images/codesandbox.png)
33+
34+
### Syntax settings
35+
36+
In the Node.js world, there are two ways to import modules:
37+
38+
- the standard way: ECMAScript modules (or ESM)
39+
40+
```js
41+
import { Server } from "socket.io";
42+
```
43+
44+
Reference: https://nodejs.org/api/esm.html
45+
46+
- the legacy way: CommonJS
47+
48+
```js
49+
const { Server } = require("socket.io");
50+
```
51+
52+
Reference: https://nodejs.org/api/modules.html
53+
54+
Socket.IO supports both syntax.
55+
56+
:::tip
57+
58+
We recommend using the ESM syntax in your project, though this might not always be feasible due to some packages not supporting this syntax.
59+
60+
:::
61+
62+
For your convenience, throughout the tutorial, each code block allows you to select your preferred syntax:
63+
64+
<Tabs groupId="lang">
65+
<TabItem value="cjs" label="CommonJS" default>
66+
67+
```js
68+
const { Server } = require("socket.io");
69+
```
70+
71+
</TabItem>
72+
<TabItem value="mjs" label="ES modules">
73+
74+
```js
75+
import { Server } from "socket.io";
76+
```
77+
78+
</TabItem>
79+
</Tabs>
80+
81+
82+
Ready? Click "Next" to get started.
+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
title: "Tutorial step #1 - Project initialization"
3+
sidebar_label: "Step #1: Project initialization"
4+
slug: step-1
5+
---
6+
7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
10+
# Project initialization
11+
12+
The first goal is to set up a simple HTML webpage that serves out a form and a list of messages. We’re going to use the Node.JS web framework `express` to this end. Make sure [Node.JS](https://nodejs.org) is installed.
13+
14+
First let’s create a `package.json` manifest file that describes our project. I recommend you place it in a dedicated empty directory (I’ll call mine `socket-chat-example`).
15+
16+
<Tabs groupId="lang">
17+
<TabItem value="cjs" label="CommonJS" default>
18+
19+
```json
20+
{
21+
"name": "socket-chat-example",
22+
"version": "0.0.1",
23+
"description": "my first socket.io app",
24+
"type": "commonjs",
25+
"dependencies": {}
26+
}
27+
```
28+
29+
</TabItem>
30+
<TabItem value="mjs" label="ES modules">
31+
32+
```json
33+
{
34+
"name": "socket-chat-example",
35+
"version": "0.0.1",
36+
"description": "my first socket.io app",
37+
"type": "module",
38+
"dependencies": {}
39+
}
40+
```
41+
42+
</TabItem>
43+
</Tabs>
44+
45+
:::caution
46+
47+
The "name" property must be unique, you cannot use a value like "socket.io" or "express", because npm will complain when installing the dependency.
48+
49+
:::
50+
51+
Now, in order to easily populate the `dependencies` property with the things we need, we’ll use `npm install`:
52+
53+
```
54+
npm install express@4
55+
```
56+
57+
Once it's installed we can create an `index.js` file that will set up our application.
58+
59+
<Tabs groupId="lang">
60+
<TabItem value="cjs" label="CommonJS" default>
61+
62+
```js
63+
const express = require('express');
64+
const { createServer } = require('node:http');
65+
66+
const app = express();
67+
const server = createServer(app);
68+
69+
app.get('/', (req, res) => {
70+
res.send('<h1>Hello world</h1>');
71+
});
72+
73+
server.listen(3000, () => {
74+
console.log('server running at http://localhost:3000');
75+
});
76+
```
77+
78+
</TabItem>
79+
<TabItem value="mjs" label="ES modules">
80+
81+
```js
82+
import express from 'express';
83+
import { createServer } from 'node:http';
84+
85+
const app = express();
86+
const server = createServer(app);
87+
88+
app.get('/', (req, res) => {
89+
res.send('<h1>Hello world</h1>');
90+
});
91+
92+
server.listen(3000, () => {
93+
console.log('server running at http://localhost:3000');
94+
});
95+
```
96+
97+
</TabItem>
98+
</Tabs>
99+
100+
This means that:
101+
102+
- Express initializes `app` to be a function handler that you can supply to an HTTP server (as seen in line 5).
103+
- We define a route handler `/` that gets called when we hit our website home.
104+
- We make the http server listen on port 3000.
105+
106+
If you run `node index.js` you should see the following:
107+
108+
<img src="/images/chat-1.png" alt="A console saying that the server has started listening on port 3000" />
109+
110+
And if you point your browser to `http://localhost:3000`:
111+
112+
<img src="/images/chat-2.png" alt="A browser displaying a big 'Hello World'" />
113+
114+
So far, so good!
115+
116+
:::tip
117+
118+
<Tabs groupId="lang">
119+
<TabItem value="cjs" label="CommonJS" default attributes={{ className: 'display-none' }}>
120+
121+
You can run this example directly in your browser on:
122+
123+
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/cjs/step1?file=index.js)
124+
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/cjs/step1?file=index.js)
125+
126+
127+
</TabItem>
128+
<TabItem value="mjs" label="ES modules" attributes={{ className: 'display-none' }}>
129+
130+
You can run this example directly in your browser on:
131+
132+
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/esm/step1?file=index.js)
133+
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/esm/step1?file=index.js)
134+
135+
136+
</TabItem>
137+
</Tabs>
138+
139+
:::

docs/tutorial/03-serving-html.md

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
title: "Tutorial step #2 - Serving HTML"
3+
sidebar_label: "Step #2: Serving HTML"
4+
slug: step-2
5+
---
6+
7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
10+
# Serving HTML
11+
12+
So far in `index.js` we’re calling `res.send` and passing it a string of HTML. Our code would look very confusing if we just placed our entire application’s HTML there, so instead we're going to create a `index.html` file and serve that instead.
13+
14+
Let’s refactor our route handler to use `sendFile` instead.
15+
16+
<Tabs groupId="lang">
17+
<TabItem value="cjs" label="CommonJS" default>
18+
19+
```js
20+
const express = require('express');
21+
const { createServer } = require('node:http');
22+
// highlight-start
23+
const { join } = require('node:path');
24+
// highlight-end
25+
26+
const app = express();
27+
const server = createServer(app);
28+
29+
// highlight-start
30+
app.get('/', (req, res) => {
31+
res.sendFile(join(__dirname, 'index.html'));
32+
});
33+
// highlight-end
34+
35+
server.listen(3000, () => {
36+
console.log('server running at http://localhost:3000');
37+
});
38+
```
39+
40+
</TabItem>
41+
<TabItem value="mjs" label="ES modules">
42+
43+
```js
44+
import express from 'express';
45+
import { createServer } from 'node:http';
46+
47+
const app = express();
48+
const server = createServer(app);
49+
50+
// highlight-start
51+
app.get('/', (req, res) => {
52+
res.sendFile(new URL('./index.html', import.meta.url).pathname);
53+
});
54+
// highlight-end
55+
56+
server.listen(3000, () => {
57+
console.log('server running at http://localhost:3000');
58+
});
59+
```
60+
61+
</TabItem>
62+
</Tabs>
63+
64+
Put the following in your `index.html` file:
65+
66+
```html
67+
<!DOCTYPE html>
68+
<html>
69+
<head>
70+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
71+
<title>Socket.IO chat</title>
72+
<style>
73+
body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
74+
75+
#form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }
76+
#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }
77+
#input:focus { outline: none; }
78+
#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }
79+
80+
#messages { list-style-type: none; margin: 0; padding: 0; }
81+
#messages > li { padding: 0.5rem 1rem; }
82+
#messages > li:nth-child(odd) { background: #efefef; }
83+
</style>
84+
</head>
85+
<body>
86+
<ul id="messages"></ul>
87+
<form id="form" action="">
88+
<input id="input" autocomplete="off" /><button>Send</button>
89+
</form>
90+
</body>
91+
</html>
92+
```
93+
94+
If you restart the process (by hitting Control+C and running `node index.js` again) and refresh the page it should look like this:
95+
96+
<img src="/images/chat-3.png" alt="A browser displaying an input and a 'Send' button" />
97+
98+
:::tip
99+
100+
<Tabs groupId="lang">
101+
<TabItem value="cjs" label="CommonJS" default attributes={{ className: 'display-none' }}>
102+
103+
You can run this example directly in your browser on:
104+
105+
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/cjs/step2?file=index.js)
106+
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/cjs/step2?file=index.js)
107+
108+
109+
</TabItem>
110+
<TabItem value="mjs" label="ES modules" attributes={{ className: 'display-none' }}>
111+
112+
You can run this example directly in your browser on:
113+
114+
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/esm/step2?file=index.js)
115+
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/esm/step2?file=index.js)
116+
117+
118+
</TabItem>
119+
</Tabs>
120+
121+
:::

0 commit comments

Comments
 (0)