Come distribuire un’applicazione Bun?
Bun è un runtime JavaScript progettato per essere veloce, leggero e facile da usare. È scritto in Zig e alimentato da JavaScriptCore, il motore JavaScript che alimenta Safari.
Bun ha un gestore di pacchetti, un test runner e un bundler integrati compatibili con Node.js. Fornisce inoltre un insieme minimo di API altamente ottimizzate per l’esecuzione di operazioni comuni, come l’avvio di un server HTTP e la scrittura di file.
In questo articolo, costruirete una semplice API web con Bun e la distribuirete su Back4app utilizzando i container di Back4app. Continuate a leggere per saperne di più su come ospitare un’applicazione Bun.
Contents
Vantaggi del bun
Dall’annuncio iniziale di Bun, anche prima del rilascio della V1 nel settembre 2023, Bun è diventato sempre più popolare nella comunità JavaScript. Ecco alcuni dei motivi.
Velocità
Bun è scritto in Zig, un linguaggio di programmazione a basso livello progettato per la programmazione di sistemi, con particolare attenzione alle prestazioni, alla sicurezza e alla leggibilità. Intende essere un’alternativa moderna a C e C++.
Inoltre, a differenza di Node.js e Deno, che utilizzano il motore JavaScript V8 di Chrome, utilizza il motore JavaScriptCore, che alimenta Safari.
Oltre a Zig e JavaScript Core, Bun utilizza anche una serie di altre tecniche, come un allocatore di memoria personalizzato ottimizzato per JavaScript e un compilatore just-in-time (JIT) per ottimizzare il codice durante l’esecuzione.
Nel complesso, la combinazione di Zig, JavaScript Core e altre ottimizzazioni rende Bun un runtime JavaScript molto veloce rispetto ad altri runtime.
Compatibilità con Node.js
Bun è stato progettato per essere un sostituto di Node.js e come tale è compatibile con tutte le API di Node.js.
Dispone anche di tutti i moduli Node.js integrati, come crypto, fs, path, ecc. È possibile verificare i moduli Node.js disponibili e non disponibili nella documentazione di Bun.js.
Inoltre, Bun è un gestore di pacchetti compatibile con npm. Ciò significa che è possibile utilizzare Bun per installare e gestire i pacchetti Node.js.
Supporto TypeScript out-of-Box
Bun dispone di un supporto nativo e continuo per TypeScript, che lo rende una scelta eccellente se si preferisce o si richiede TypeScript nei propri progetti.
TypeScript, una versione estesa e tipizzata staticamente di JavaScript, introduce caratteristiche avanzate del linguaggio e la tipizzazione statica per migliorare lo sviluppo di JavaScript.
Con Bun, non c’è bisogno di configurazioni aggiuntive, né di procedure di configurazione o di compilazione supplementari per abilitare le funzionalità di TypeScript.
Limitazioni del bun
Nonostante i suoi vantaggi, Bun presenta alcune limitazioni che è necessario considerare prima di utilizzarlo nel proprio progetto.
Risorse limitate
Bun è ancora relativamente nuovo, il che significa che la comunità è attualmente piccola. Non ci sono molte risorse che coprono lo sviluppo specifico di Bun-js, quindi potrebbe essere difficile capire come utilizzare il runtime.
Tuttavia, la documentazione di Bun è completa e funge da prezioso punto di riferimento. In caso di difficoltà, c’è anche la possibilità di chiedere assistenza tramite il loro canale Discord.
Supporto per Windows
Bun fornisce attualmente un supporto limitato per il sistema operativo Windows. Al momento in cui scriviamo, solo il runtime è supportato su Windows.
Il test runner, il gestore di pacchetti e il bundler sono ancora in fase di sviluppo e, pertanto, non funzionano su Windows. Continuate a leggere per saperne di più su come ospitare un’applicazione Bun.
Costruire un’applicazione per bun
Prima di poter utilizzare Bun, è necessario installarlo.
Per installare Bun su macOS, WSL e Linux, eseguire il comando seguente:
curl -fsSL https://bun.sh/install | bash
Impostazione dell’ambiente di sviluppo
Per creare un nuovo progetto Bun, eseguire il comando seguente:
bun init
L’esecuzione del comando precedente inizializza un progetto Bun vuoto nella directory del progetto.
Per questo tutorial, si costruirà una semplice API con Elysia, uno dei framework per server HTTP più veloci di Bun (secondo i loro benchmark).
Eseguite il comando seguente per installare Elysia e le altre dipendenze necessarie per questo progetto:
bun add elysia knex dotenv pg
Le altre dipendenze installate nel comando includono:
- Knex, un costruttore di query. Si utilizzerà questa dipendenza per semplificare l’interazione con il database.
- dotenv, questo pacchetto aiuta a gestire le variabili ambientali nel progetto.
- pg (driver per database Postgres) per interagire con il database Postgres.
Quindi, inizializzare knex nel progetto eseguendo:
knex init
Il comando precedente crea un file knexfile.js
. Questo file contiene le opzioni di configurazione per il database.
Sostituite il codice nel file con il blocco di codice sottostante:
require("dotenv").config();
export const development = {
client: "pg",
connection: process.env.DATABASE_URL,
migrations: {
directory: "./db/migrations",
}
};
Quindi, creare un file db.js
nella cartella principale del progetto e aggiungervi il blocco di codice sottostante.
const knex = require("knex");
const knexFile = require("./knexfile.js");
const environment = process.env.NODE_ENV || "development";
export default knex(knexFile[environment]);
Quindi, creare un file .env
e aggiungere i dettagli di connessione al database o l’URI al file.
Ad esempio:
DATABASE_URL = <YOUR_DATABASE_URI>
Sostituire “YOUR_DATABASE_URI” con l’URL del database.
Nota: Assicurarsi di aggiungere il file .env
al file .gitignore
, per evitare di inviare informazioni private al controllo di versione.
Creazione del modello di database
Per creare il modello di database con Knex, occorre creare un file di migrazione e scrivere un comando SQL di creazione con Knex.
Eseguire il comando seguente per creare la prima migrazione:
knex migrate:make blog
Quindi, sostituire il codice nel file di migrazione generato con il blocco di codice sottostante:
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
export function up (knex) {
return knex.schema.createTable("blog", (table) => {
table.increments("id").primary();
table.string("title").notNullable();
table.string("content").notNullable();
table.string("author").notNullable();
table.timestamp("created_at").defaultTo(knex.fn.now());
});
}
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
export function down (knex) {
return knex.schema.dropTable("blog");
}
Infine, eseguire il blocco di codice sottostante per eseguire il file di migrazione:
knex migrate:latest
Il comando precedente esegue il file di migrazione generato in precedenza, creando così una tabella Blog nel database.
Creare un server Bun-Elysia
In questa fase, si creerà un semplice server API.
Aprire il file index.ts
e aggiungere il blocco di codice sottostante:
//index.ts
const { Elysia } = require("elysia");
let db = require("./db");
db = db.default;
const app = new Elysia();
Nel blocco di codice sottostante, è stato importato Elysia e creata un’istanza del framework Elysia (app).
Creazione di gestori di percorso
Successivamente, si creeranno dei gestori di rotte per l’applicazione. I gestori creati saranno per le seguenti rotte:
- POST /posts/creare-nuovo-post
- GET /posts
- GET /posts/:id
- PATCH /posts/:id/update-post
- DELETE /posts/:id/delete-post
Aggiungere il blocco di codice sottostante al file index.ts
per creare il gestore per “/posts/create-new-post”:
app.post("/posts/create-new-post", async (context) => {
try {
//Extract the title, content and author from the request body
const { title, content, author } = context.body;
//Insert the post into the database
const post = await db("blog").insert({
title,
content,
author,
});
//Send response to the client
return new Response(JSON.stringify(post));
} catch (error: any) {
//Send error to the client
return new Response(error.message, { status: 500 });
}
});
Il blocco di codice qui sopra è un gestore di rotta per l’endpoint che aggiunge nuovi post al database.
Aggiungere il blocco di codice sottostante al file index.ts
per creare il gestore che recupera tutti i post “/posts”:
app.get("/posts", async (context) => {
try {
//Get all posts from the database
const posts = await db.select("*").from("blog");
//Send response to the client
return new Response(JSON.stringify(posts));
} catch (error: any) {
//Send error to the client
return new Response(error.message, { status: 500 });
}
});
Aggiungere il blocco di codice sottostante al file index.ts
per creare il gestore che recupera un singolo post per id “/posts/:id”:
app.get("/posts/:id", async (context) => {
//Extract the id from the request params
const { id } = context.params;
//Get the post from the database
const post = await db("blog").where({ id });
//If the post is not found, send a 404 response
if (post.length === 0) {
return new Response("Post not found", { status: 404 });
}
//Send response to the client
return new Response(JSON.stringify(post));
});
Aggiungere il blocco di codice sottostante al file index.ts
per creare il gestore che aggiorna un singolo post con i dati contenuti nel payload per id “/posts/:id/update-post”:
app.patch("/posts/:id/update-post", async (context) => {
//Extract the id from the request params
const { id } = context.params;
//Extract the title and content from the request body
const { title, content } = context.body;
//Update the post in the database
const post = await db("blog").where({ id }).update(
{
title,
content,
},
["id", "title", "content"]
);
//Send response to the client
return new Response(JSON.stringify(post));
});
Aggiungere il blocco di codice sottostante al file index.ts
per creare il gestore che cancella un singolo post per id “/posts/:id/delete-post”:
app.delete("/posts/:id/delete-post", async (context) => {
//Extract the id from the request params
const { id } = context.params;
//Delete the post from the database
const post = await db("blog").where({ id }).del();
//Send response to the client
return new Response(JSON.stringify(post));
});
Infine, aggiungere il blocco di codice sottostante per impostare il PORT della propria applicazione.
app.listen(3000, () => {
console.log("Server running on port 3000");
});
Eseguite il comando seguente per avviare l’applicazione:
bun --watch index.ts
Distribuzione di un’applicazione Bun su contenitori Back4app
La distribuzione dell’applicazione Bun richiede alcuni passaggi.
Passo 1: scrivere un file Docker
Per creare un file Docker, eseguire il comando seguente nel terminale.
touch Dockerfile
L’esecuzione del comando precedente crea un file Docker nella cartella principale del progetto.
Quindi, aprite il vostro file Docker e aggiungete il blocco di codice sottostante:
FROM oven/bun
WORKDIR /app
COPY package.json .
COPY bun.lockb .
RUN bun install
COPY . .
EXPOSE 3000
CMD ["bun", "index.ts"]
Nel file Docker qui sopra, la prima riga, FROM oven/bun
, specifica l’immagine di base da usare. Questa immagine è un’immagine precostituita che contiene il runtime Bun e tutte le sue dipendenze.
La riga successiva, WORKDIR /app
, imposta la directory di lavoro dell’immagine. È la directory in cui verrà copiato ed eseguito il codice dell’applicazione.
Le due righe seguenti, COPY package.json .
e COPY bun.lockb .
, copiano i file package.json
e bun.lockb
dalla directory corrente all’immagine. Questi file sono necessari al runtime Bun per installare le dipendenze dell’applicazione.
La riga successiva, RUN bun install
, installa le dipendenze dell’applicazione utilizzando il runtime Bun.
La riga successiva, COPY . .
, copia l’intera directory corrente nell’immagine. Questo include il codice dell’applicazione e qualsiasi altro file necessario.
La riga successiva, EXPOSE 3000
, espone la porta 3000
del contenitore al mondo esterno. Questa è la porta su cui l’applicazione si metterà in ascolto.
L’ultima riga, CMD ["bun", "index.ts"]
, specifica il comando che sarà eseguito all’avvio del contenitore. Questo comando avvierà il runtime Bun ed eseguirà il file index.ts
dell’applicazione.
Infine, inviate il codice a GitHub.
Passo 2: Creare un’applicazione Back4app
Il passo successivo per ospitare un’applicazione Bun è creare una nuova applicazione su Back4App. Per prima cosa, accedete al vostro account Back4App o iscrivetevi se non ne avete ancora uno. Una volta effettuato l’accesso, vi troverete nella dashboard di Back4App.
Fare clic sul pulsante “NUOVA APP” e selezionare l’opzione“Container come servizio“.
Come passo successivo per ospitare un’applicazione Bun, collegare il proprio account GitHub al proprio account Back4app. La connessione dell’account consente a Back4app di accedere ai repository del vostro account.
Si può decidere di concedere l’accesso a tutti i repository del proprio account o a repository specifici. Scegliete l’applicazione che volete distribuire, in questo caso l’applicazione costruita in questa esercitazione, e fate clic su Seleziona.
Dopo aver fatto clic sul pulsante Seleziona, si verrà indirizzati a una pagina di configurazione, dove si dovranno inserire i dettagli della propria applicazione, come la PORTA e le variabili d’ambiente.
Dopo aver compilato i dettagli, fare clic sul pulsante Crea app. Questo avvia il processo di distribuzione. La distribuzione dovrebbe andare a buon fine e si otterrà un URL per accedere all’applicazione, ma se non dovesse andare a buon fine, si può sfruttare l’integrazione ChatGPT di Back4app per risolvere i problemi con il file Docker.
In alternativa, è possibile risolvere manualmente gli errori di distribuzione utilizzando i registri dettagliati e la guida alla risoluzione dei problemi di Back4app.
Conclusione
In questo articolo abbiamo esplorato il runtime JavaScript Bun, i suoi vantaggi e le sue apparenti limitazioni. Si è anche visto come costruire un’applicazione Bun utilizzando Elysia, Knex e PostgreSQL.
Infine, avete esplorato i container Back4app e come distribuire le vostre applicazioni Bun sulla piattaforma.
Quando si utilizza Bun, è importante notare che è ancora nelle sue fasi iniziali e potrebbe introdurre alcuni cambiamenti importanti in futuro.
FAQ
Cos’è Bun?
Bun è un runtime JavaScript progettato per essere veloce ed efficiente. È costruito sul motore JavaScriptCore e utilizza una serie di ottimizzazioni (vantaggi dell’utilizzo del linguaggio di basso livello, Zig) per renderlo più veloce.
Come distribuire un’app Bun?
– Crea un’app Bun.
– Scrivi un Dockerfile.
– Invia la tua applicazione Bun a GitHub.
– Apri un account Back4app o accedi al tuo account esistente.
– Crea una nuova app “CaaS” su Back4app.
– Concedi a Back4app l’accesso all’applicazione che vuoi distribuire.
– Seleziona l’app e compila i dettagli di configurazione.
– Fai clic su Distribuisci.