mirror of
https://github.com/feathersjs/feathers.git
synced 2025-12-08 19:46:22 +00:00
453 lines
14 KiB
Markdown
453 lines
14 KiB
Markdown
---
|
|
outline: deep
|
|
---
|
|
|
|
# Quick start
|
|
|
|
Alright then! Let's learn Feathers. In this quick start guide we'll create our first Feathers app, an API server and a simple website to use it. You'll see how easy it is to get started with Feathers in just a single file without additional boilerplate or tooling. If you want to jump right into creating a complete application you can go to the [Creating An App](./generator.md) chapter.
|
|
|
|
<img style="margin: 2em;" src="/img/main-character-bench.svg" alt="Getting started">
|
|
|
|
Feathers works with all [currently active NodeJS releases](https://github.com/nodejs/Release#release-schedule). All guides are assuming the languages features from the most current stable NodeJS release which you can get from the [NodeJS website](https://nodejs.org/en/).
|
|
|
|
<BlockQuote type="tip">
|
|
|
|
You can follow this guide on your own computer in the terminal or try the steps out live without installing anything in the [Feathers Quick Start on Stackblitz](https://stackblitz.com/@daffl/collections/feathers-quick-start).
|
|
|
|
</BlockQuote>
|
|
|
|
After successful installation, the `node` and `npm` commands should be available on the terminal:
|
|
|
|
```
|
|
node --version
|
|
```
|
|
|
|
```
|
|
npm --version
|
|
```
|
|
|
|
<BlockQuote type="warning" label="Important">
|
|
|
|
Running NodeJS and npm should not require admin or root privileges.
|
|
|
|
</BlockQuote>
|
|
|
|
Let's create a new folder for our application:
|
|
|
|
```sh
|
|
mkdir feathers-basics
|
|
cd feathers-basics
|
|
```
|
|
|
|
Since any Feathers application is a Node application, we can create a default [package.json](https://docs.npmjs.com/files/package.json) using `npm`:
|
|
|
|
<LanguageBlock global-id="ts">
|
|
|
|
```sh
|
|
npm init --yes
|
|
# Install TypeScript and its NodeJS wrapper
|
|
npm i typescript ts-node @types/node --save-dev
|
|
# Also initialize a TS configuration file that uses modern JavaScript
|
|
npx tsc --init --target es2020
|
|
```
|
|
|
|
</LanguageBlock>
|
|
|
|
<LanguageBlock global-id="js">
|
|
|
|
```sh
|
|
npm init --yes
|
|
```
|
|
|
|
</LanguageBlock>
|
|
|
|
## Installing Feathers
|
|
|
|
Feathers can be installed like any other Node module by installing the [@feathersjs/feathers](https://www.npmjs.com/package/@feathersjs/feathers) package through [npm](https://www.npmjs.com). The same package can also be used with module loaders like Vite, Webpack, and in React Native.
|
|
|
|
```sh
|
|
npm install @feathersjs/feathers --save
|
|
```
|
|
|
|
<BlockQuote label="note">
|
|
|
|
All Feathers core modules are in the `@feathersjs` namespace.
|
|
|
|
</BlockQuote>
|
|
|
|
## Our first app
|
|
|
|
Now we can create a Feathers application with a simple `messages` service that allows us to create new messages and find all existing ones.
|
|
|
|
<LanguageBlock global-id="ts">
|
|
|
|
Create a file called `app.ts` with the following content:
|
|
|
|
</LanguageBlock>
|
|
<LanguageBlock global-id="js">
|
|
|
|
Create a file called `app.mjs` with the following content:
|
|
|
|
</LanguageBlock>
|
|
|
|
```ts
|
|
import { feathers } from '@feathersjs/feathers'
|
|
|
|
// This is the interface for the message data
|
|
interface Message {
|
|
id?: number
|
|
text: string
|
|
}
|
|
|
|
// A messages service that allows us to create new
|
|
// and return all existing messages
|
|
class MessageService {
|
|
messages: Message[] = []
|
|
|
|
async find() {
|
|
// Just return all our messages
|
|
return this.messages
|
|
}
|
|
|
|
async create(data: Pick<Message, 'text'>) {
|
|
// The new message is the data text with a unique identifier added
|
|
// using the messages length since it changes whenever we add one
|
|
const message: Message = {
|
|
id: this.messages.length,
|
|
text: data.text
|
|
}
|
|
|
|
// Add new message to the list
|
|
this.messages.push(message)
|
|
|
|
return message
|
|
}
|
|
}
|
|
|
|
// This tells TypeScript what services we are registering
|
|
type ServiceTypes = {
|
|
messages: MessageService
|
|
}
|
|
|
|
const app = feathers<ServiceTypes>()
|
|
|
|
// Register the message service on the Feathers application
|
|
app.use('messages', new MessageService())
|
|
|
|
// Log every time a new message has been created
|
|
app.service('messages').on('created', (message: Message) => {
|
|
console.log('A new message has been created', message)
|
|
})
|
|
|
|
// A function that creates messages and then logs
|
|
// all existing messages on the service
|
|
const main = async () => {
|
|
// Create a new message on our message service
|
|
await app.service('messages').create({
|
|
text: 'Hello Feathers'
|
|
})
|
|
|
|
// And another one
|
|
await app.service('messages').create({
|
|
text: 'Hello again'
|
|
})
|
|
|
|
// Find all existing messages
|
|
const messages = await app.service('messages').find()
|
|
|
|
console.log('All messages', messages)
|
|
}
|
|
|
|
main()
|
|
```
|
|
|
|
<LanguageBlock global-id="ts">
|
|
|
|
We can run it with
|
|
|
|
```sh
|
|
npx ts-node app.ts
|
|
```
|
|
|
|
</LanguageBlock>
|
|
<LanguageBlock global-id="js">
|
|
|
|
We can run it with
|
|
|
|
```sh
|
|
node app.mjs
|
|
```
|
|
|
|
</LanguageBlock>
|
|
|
|
[Try it out live >](https://stackblitz.com/edit/node-mupbmh?embed=1&file=app.ts&view=editor)
|
|
|
|
We will see something like this in the terminal:
|
|
|
|
```sh
|
|
A new message has been created { id: 0, text: 'Hello Feathers' }
|
|
A new message has been created { id: 1, text: 'Hello again' }
|
|
All messages [ { id: 0, text: 'Hello Feathers' },
|
|
{ id: 1, text: 'Hello again' } ]
|
|
```
|
|
|
|
Here we implemented only `find` and `create`, but a service can also have a few other methods, specifically `get`, `update`, `patch` and `remove`. We will learn more about service methods and events throughout this guide, but this sums up some of the most important concepts upon which Feathers is built.
|
|
|
|
## An API Server
|
|
|
|
So far we've created a Feathers application, a message service, and are listening to events. However, this is only a simple NodeJS script that prints some output and then exits. What we really want is to host it as an API server. This is where Feathers transports come in.
|
|
|
|
A transport takes a service like the one we created above and turns it into a server that other clients can talk to, like a website or mobile application.
|
|
|
|
In the following example we will take our existing service and use:
|
|
|
|
- `@feathersjs/koa` which uses [KoaJS](https://koajs.com/) to automatically turn our services into a REST API
|
|
- `@feathersjs/socketio` which uses Socket.io to do the same as a WebSocket, real-time API (as we will see in a bit this is where the `created` event we saw above comes in handy).
|
|
|
|
Run:
|
|
|
|
<LanguageBlock global-id="ts">
|
|
|
|
```sh
|
|
npm install @feathersjs/socketio @feathersjs/koa --save
|
|
```
|
|
|
|
Then update `app.ts` with the following content:
|
|
|
|
</LanguageBlock>
|
|
<LanguageBlock global-id="js">
|
|
|
|
```sh
|
|
npm install @feathersjs/socketio @feathersjs/koa koa-static --save
|
|
```
|
|
|
|
Then update `app.mjs` with the following content:
|
|
|
|
</LanguageBlock>
|
|
|
|
```ts{2-4,42-55,58-65}
|
|
import { feathers } from '@feathersjs/feathers'
|
|
import { koa, rest, bodyParser, errorHandler, serveStatic } from '@feathersjs/koa'
|
|
import socketio from '@feathersjs/socketio'
|
|
|
|
// This is the interface for the message data
|
|
interface Message {
|
|
id?: number
|
|
text: string
|
|
}
|
|
|
|
// A messages service that allows us to create new
|
|
// and return all existing messages
|
|
class MessageService {
|
|
messages: Message[] = []
|
|
|
|
async find() {
|
|
// Just return all our messages
|
|
return this.messages
|
|
}
|
|
|
|
async create(data: Pick<Message, 'text'>) {
|
|
// The new message is the data text with a unique identifier added
|
|
// using the messages length since it changes whenever we add one
|
|
const message: Message = {
|
|
id: this.messages.length,
|
|
text: data.text
|
|
}
|
|
|
|
// Add new message to the list
|
|
this.messages.push(message)
|
|
|
|
return message
|
|
}
|
|
}
|
|
|
|
// This tells TypeScript what services we are registering
|
|
type ServiceTypes = {
|
|
messages: MessageService
|
|
}
|
|
|
|
// Creates an KoaJS compatible Feathers application
|
|
const app = koa<ServiceTypes>(feathers())
|
|
|
|
// Use the current folder for static file hosting
|
|
app.use(serveStatic('.'))
|
|
// Register the error handle
|
|
app.use(errorHandler())
|
|
// Parse JSON request bodies
|
|
app.use(bodyParser())
|
|
|
|
// Register REST service handler
|
|
app.configure(rest())
|
|
// Configure Socket.io real-time APIs
|
|
app.configure(socketio())
|
|
// Register our messages service
|
|
app.use('messages', new MessageService())
|
|
|
|
// Add any new real-time connection to the `everybody` channel
|
|
app.on('connection', (connection) => app.channel('everybody').join(connection))
|
|
// Publish all events to the `everybody` channel
|
|
app.publish((_data) => app.channel('everybody'))
|
|
|
|
// Start the server
|
|
app
|
|
.listen(3030)
|
|
.then(() => console.log('Feathers server listening on localhost:3030'))
|
|
|
|
// For good measure let's create a message
|
|
// So our API doesn't look so empty
|
|
app.service('messages').create({
|
|
text: 'Hello world from the server'
|
|
})
|
|
```
|
|
|
|
[Try it out live >](https://stackblitz.com/edit/node-zfinli?embed=1&file=app.ts)
|
|
|
|
<LanguageBlock global-id="ts">
|
|
|
|
We can start the server with
|
|
|
|
```sh
|
|
npx ts-node app.ts
|
|
```
|
|
|
|
</LanguageBlock>
|
|
<LanguageBlock global-id="js">
|
|
|
|
We can start the server with
|
|
|
|
```sh
|
|
node app.mjs
|
|
```
|
|
|
|
</LanguageBlock>
|
|
|
|
<BlockQuote type="info">
|
|
|
|
The server will stay running until you stop it by pressing **Control + C** in the terminal.
|
|
|
|
</BlockQuote>
|
|
|
|
And in the browser visit
|
|
|
|
```
|
|
http://localhost:3030/messages
|
|
```
|
|
|
|
to see an array with the one message we created on the server.
|
|
|
|
<BlockQuote>
|
|
|
|
The built-in [JSON viewer in Firefox](https://developer.mozilla.org/en-US/docs/Tools/JSON_viewer) or a browser plugin like [JSON viewer for Chrome](https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh) makes it nicer to view JSON responses in the browser.
|
|
|
|
</BlockQuote>
|
|
|
|
This is the basic setup of a Feathers API server.
|
|
|
|
- The `app.use` calls probably look familiar if you have used something like Koa or Express before.
|
|
- `app.configure` calls set up the Feathers transport to host the API.
|
|
- `app.on('connection')` and `app.publish` are used to set up event channels, which send real-time events to the proper clients (everybody that is connected to our server in this case). You can learn [more about the channels API](../../api/channels.md) after finishing this guide.
|
|
|
|
## In the browser
|
|
|
|
Now we can look at one of the really cool features of Feathers: **It works the same in a web browser!** This means that we could take [our first app example](#our-first-app) from above and run it just the same in a website. Since we already have a server running, however, let's go a step further and create a Feathers app that talks to our `messages` service on the server using a real-time Socket.io connection.
|
|
|
|
In the same folder, add the following `index.html` page:
|
|
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<title>Feathers Example</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/daisyui@2.46.1/dist/full.css" rel="stylesheet" type="text/css" />
|
|
<link
|
|
href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2/dist/tailwind.min.css"
|
|
rel="stylesheet"
|
|
type="text/css"
|
|
/>
|
|
<link rel="stylesheet" href="https://feathersjs.com/feathers-chat.css" />
|
|
</head>
|
|
<body data-theme="dracula">
|
|
<main id="main" class="p-8">
|
|
<h1 class="font-medium leading-tight text-5xl mt-0 mb-2">Welcome to Feathers</h1>
|
|
|
|
<div class="form-control w-full py-2">
|
|
<form class="input-group overflow-hidden" onsubmit="sendMessage(event)">
|
|
<input name="message" id="message-text" type="text" class="input input-bordered w-full" />
|
|
<button type="submit" class="btn">Send</button>
|
|
</form>
|
|
</div>
|
|
<h2 class="pt-1 pb-2 text-lg">Messages</h2>
|
|
</main>
|
|
|
|
<script src="//unpkg.com/@feathersjs/client@^5.0.0/dist/feathers.js"></script>
|
|
<script src="/socket.io/socket.io.js"></script>
|
|
<script type="text/javascript">
|
|
// Set up socket.io
|
|
const socket = io('http://localhost:3030')
|
|
// Initialize a Feathers app
|
|
const app = feathers()
|
|
|
|
// Register socket.io to talk to our server
|
|
app.configure(feathers.socketio(socket))
|
|
|
|
// Form submission handler that sends a new message
|
|
async function sendMessage(event) {
|
|
const messageInput = document.getElementById('message-text')
|
|
|
|
event.preventDefault()
|
|
|
|
// Create a new message with the input field value
|
|
await app.service('messages').create({
|
|
text: messageInput.value
|
|
})
|
|
|
|
messageInput.value = ''
|
|
}
|
|
|
|
// Renders a single message on the page
|
|
function addMessage(message) {
|
|
document.getElementById('main').innerHTML += `<div class="chat chat-start">
|
|
<div class="chat-bubble">${message.text}</div>
|
|
</div>`
|
|
}
|
|
|
|
const main = async () => {
|
|
// Find all existing messages
|
|
const messages = await app.service('messages').find()
|
|
|
|
// Add existing messages to the list
|
|
messages.forEach(addMessage)
|
|
|
|
// Add any newly created message to the list in real-time
|
|
app.service('messages').on('created', addMessage)
|
|
}
|
|
|
|
main()
|
|
</script>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
[Try it out live >](https://stackblitz.com/edit/node-m7cjfd?embed=1&file=index.html)
|
|
|
|
Now in the browser if you go to
|
|
|
|
```
|
|
http://localhost:3030
|
|
```
|
|
|
|
you will see a simple website that allows creating new messages. It is possible to open the page in two tabs and see new messages show up on either side in real-time. You can verify that the messages got created by visiting
|
|
|
|
```
|
|
http://localhost:3030/messages
|
|
```
|
|
|
|
You'll see the JSON response including all current messages.
|
|
|
|
## What's next?
|
|
|
|
In this chapter we created our first Feathers application and a service that allows creating new messages, storing them in memory, and retrieving them. We then hosted that service as a REST and real-time API server and used Feathers in the browser to connect to that server and create a website that can send new messages and show all existing messages in real-time.
|
|
|
|
Even though we are using just NodeJS and Feathers from scratch without any additional tools, we didn't write a lot of code. In the [next chapter](./generator.md) we will look at the Feathers CLI which can create a similar Feathers application with a recommended file structure, models, database connections, authentication and more.
|