-
Notifications
You must be signed in to change notification settings - Fork 736
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
08cf30a
commit fa75c7d
Showing
33 changed files
with
3,989 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
--- | ||
title: Tutorial - Introduction | ||
sidebar_label: Introduction | ||
slug: introduction | ||
--- | ||
|
||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
# Getting started | ||
|
||
Welcome to the Socket.IO tutorial! | ||
|
||
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. | ||
|
||
## Introduction | ||
|
||
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. | ||
|
||
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. | ||
|
||
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. | ||
|
||
## How to use this tutorial | ||
|
||
### Tooling | ||
|
||
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. | ||
|
||
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: | ||
|
||
 | ||
|
||
### Syntax settings | ||
|
||
In the Node.js world, there are two ways to import modules: | ||
|
||
- the standard way: ECMAScript modules (or ESM) | ||
|
||
```js | ||
import { Server } from "socket.io"; | ||
``` | ||
|
||
Reference: https://nodejs.org/api/esm.html | ||
|
||
- the legacy way: CommonJS | ||
|
||
```js | ||
const { Server } = require("socket.io"); | ||
``` | ||
|
||
Reference: https://nodejs.org/api/modules.html | ||
|
||
Socket.IO supports both syntax. | ||
|
||
:::tip | ||
|
||
We recommend using the ESM syntax in your project, though this might not always be feasible due to some packages not supporting this syntax. | ||
|
||
::: | ||
|
||
For your convenience, throughout the tutorial, each code block allows you to select your preferred syntax: | ||
|
||
<Tabs groupId="lang"> | ||
<TabItem value="cjs" label="CommonJS" default> | ||
|
||
```js | ||
const { Server } = require("socket.io"); | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="mjs" label="ES modules"> | ||
|
||
```js | ||
import { Server } from "socket.io"; | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
|
||
Ready? Click "Next" to get started. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
--- | ||
title: "Tutorial step #1 - Project initialization" | ||
sidebar_label: "Step #1: Project initialization" | ||
slug: step-1 | ||
--- | ||
|
||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
# Project initialization | ||
|
||
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. | ||
|
||
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`). | ||
|
||
<Tabs groupId="lang"> | ||
<TabItem value="cjs" label="CommonJS" default> | ||
|
||
```json | ||
{ | ||
"name": "socket-chat-example", | ||
"version": "0.0.1", | ||
"description": "my first socket.io app", | ||
"type": "commonjs", | ||
"dependencies": {} | ||
} | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="mjs" label="ES modules"> | ||
|
||
```json | ||
{ | ||
"name": "socket-chat-example", | ||
"version": "0.0.1", | ||
"description": "my first socket.io app", | ||
"type": "module", | ||
"dependencies": {} | ||
} | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
:::caution | ||
|
||
The "name" property must be unique, you cannot use a value like "socket.io" or "express", because npm will complain when installing the dependency. | ||
|
||
::: | ||
|
||
Now, in order to easily populate the `dependencies` property with the things we need, we’ll use `npm install`: | ||
|
||
``` | ||
npm install express@4 | ||
``` | ||
|
||
Once it's installed we can create an `index.js` file that will set up our application. | ||
|
||
<Tabs groupId="lang"> | ||
<TabItem value="cjs" label="CommonJS" default> | ||
|
||
```js | ||
const express = require('express'); | ||
const { createServer } = require('node:http'); | ||
|
||
const app = express(); | ||
const server = createServer(app); | ||
|
||
app.get('/', (req, res) => { | ||
res.send('<h1>Hello world</h1>'); | ||
}); | ||
|
||
server.listen(3000, () => { | ||
console.log('server running at http://localhost:3000'); | ||
}); | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="mjs" label="ES modules"> | ||
|
||
```js | ||
import express from 'express'; | ||
import { createServer } from 'node:http'; | ||
|
||
const app = express(); | ||
const server = createServer(app); | ||
|
||
app.get('/', (req, res) => { | ||
res.send('<h1>Hello world</h1>'); | ||
}); | ||
|
||
server.listen(3000, () => { | ||
console.log('server running at http://localhost:3000'); | ||
}); | ||
``` | ||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
This means that: | ||
|
||
- Express initializes `app` to be a function handler that you can supply to an HTTP server (as seen in line 5). | ||
- We define a route handler `/` that gets called when we hit our website home. | ||
- We make the http server listen on port 3000. | ||
|
||
If you run `node index.js` you should see the following: | ||
|
||
<img src="/images/chat-1.png" alt="A console saying that the server has started listening on port 3000" /> | ||
|
||
And if you point your browser to `http://localhost:3000`: | ||
|
||
<img src="/images/chat-2.png" alt="A browser displaying a big 'Hello World'" /> | ||
|
||
So far, so good! | ||
|
||
:::tip | ||
|
||
<Tabs groupId="lang"> | ||
<TabItem value="cjs" label="CommonJS" default attributes={{ className: 'display-none' }}> | ||
|
||
You can run this example directly in your browser on: | ||
|
||
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/cjs/step1?file=index.js) | ||
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/cjs/step1?file=index.js) | ||
|
||
|
||
</TabItem> | ||
<TabItem value="mjs" label="ES modules" attributes={{ className: 'display-none' }}> | ||
|
||
You can run this example directly in your browser on: | ||
|
||
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/esm/step1?file=index.js) | ||
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/esm/step1?file=index.js) | ||
|
||
|
||
</TabItem> | ||
</Tabs> | ||
|
||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
--- | ||
title: "Tutorial step #2 - Serving HTML" | ||
sidebar_label: "Step #2: Serving HTML" | ||
slug: step-2 | ||
--- | ||
|
||
import Tabs from '@theme/Tabs'; | ||
import TabItem from '@theme/TabItem'; | ||
|
||
# Serving HTML | ||
|
||
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. | ||
|
||
Let’s refactor our route handler to use `sendFile` instead. | ||
|
||
<Tabs groupId="lang"> | ||
<TabItem value="cjs" label="CommonJS" default> | ||
|
||
```js | ||
const express = require('express'); | ||
const { createServer } = require('node:http'); | ||
// highlight-start | ||
const { join } = require('node:path'); | ||
// highlight-end | ||
|
||
const app = express(); | ||
const server = createServer(app); | ||
|
||
// highlight-start | ||
app.get('/', (req, res) => { | ||
res.sendFile(join(__dirname, 'index.html')); | ||
}); | ||
// highlight-end | ||
|
||
server.listen(3000, () => { | ||
console.log('server running at http://localhost:3000'); | ||
}); | ||
``` | ||
|
||
</TabItem> | ||
<TabItem value="mjs" label="ES modules"> | ||
|
||
```js | ||
import express from 'express'; | ||
import { createServer } from 'node:http'; | ||
|
||
const app = express(); | ||
const server = createServer(app); | ||
|
||
// highlight-start | ||
app.get('/', (req, res) => { | ||
res.sendFile(new URL('./index.html', import.meta.url).pathname); | ||
}); | ||
// highlight-end | ||
|
||
server.listen(3000, () => { | ||
console.log('server running at http://localhost:3000'); | ||
}); | ||
``` | ||
</TabItem> | ||
</Tabs> | ||
Put the following in your `index.html` file: | ||
```html | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta name="viewport" content="width=device-width,initial-scale=1.0"> | ||
<title>Socket.IO chat</title> | ||
<style> | ||
body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; } | ||
|
||
#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); } | ||
#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; } | ||
#input:focus { outline: none; } | ||
#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; } | ||
|
||
#messages { list-style-type: none; margin: 0; padding: 0; } | ||
#messages > li { padding: 0.5rem 1rem; } | ||
#messages > li:nth-child(odd) { background: #efefef; } | ||
</style> | ||
</head> | ||
<body> | ||
<ul id="messages"></ul> | ||
<form id="form" action=""> | ||
<input id="input" autocomplete="off" /><button>Send</button> | ||
</form> | ||
</body> | ||
</html> | ||
``` | ||
If you restart the process (by hitting Control+C and running `node index.js` again) and refresh the page it should look like this: | ||
<img src="/images/chat-3.png" alt="A browser displaying an input and a 'Send' button" /> | ||
:::tip | ||
<Tabs groupId="lang"> | ||
<TabItem value="cjs" label="CommonJS" default attributes={{ className: 'display-none' }}> | ||
You can run this example directly in your browser on: | ||
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/cjs/step2?file=index.js) | ||
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/cjs/step2?file=index.js) | ||
</TabItem> | ||
<TabItem value="mjs" label="ES modules" attributes={{ className: 'display-none' }}> | ||
You can run this example directly in your browser on: | ||
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/socketio/chat-example/tree/esm/step2?file=index.js) | ||
- [StackBlitz](https://stackblitz.com/github/socketio/chat-example/tree/esm/step2?file=index.js) | ||
</TabItem> | ||
</Tabs> | ||
::: |
Oops, something went wrong.