Maak kennis met deze op beveiliging gerichte JS-runtime met een praktisch voorbeeldproject.
Deno is een JavaScript-runtime gebouwd op V8, dezelfde JavaScript-engine die Google Chrome aandrijft. De oorspronkelijke maker van Node.js heeft Deno gemaakt om enkele tekortkomingen en beveiligingsproblemen van Node.js aan te pakken.
Hoewel het relatief nieuw is, heeft Deno aan populariteit gewonnen als een veilige en moderne JavaScript-runtime. De focus op beveiliging, ondersteuning voor moderne taalfuncties en ontwikkelaarsvriendelijke tools maken het een aantrekkelijke keuze. U kunt het gebruiken om server-side applicaties, opdrachtregelprogramma's en andere JavaScript/TypeScript-projecten te bouwen, zoals een eenvoudige API.
Deno installeren
Voordat u Deno kunt gebruiken, moet u het eerst downloaden en installeren. De installatie van Deno varieert afhankelijk van uw besturingssysteem.
Op macOS en Linux kun je Deno installeren door deze opdracht uit te voeren:
curl -fsSL https://deno.land/x/install/install.sh | sh
Op Windows kunt u Deno met Powershell installeren met behulp van deze opdracht:
irm https://deno.land/install.ps1 | iex
U kunt bevestigen dat uw installatie is gelukt door de onderstaande opdracht uit te voeren:
deno --version
De bovenstaande opdracht zou de Deno-versie naar de console moeten afdrukken.
Als u VS Code als IDE gebruikt, kunt u downloaden Deno's VS Code-extensie om IntelliSense toe te voegen, waardoor uw productiviteit en ontwikkelingservaring worden verbeterd bij het werken met Deno-projecten.
Nadat u de extensie succesvol hebt geïnstalleerd, maakt u een .vscode map in de hoofdmap van uw project en maak een instellingen.json bestand erin.
Voeg vervolgens het onderstaande codeblok toe aan het instellingen.json bestand om IntelliSense in te schakelen:
{
"deno.enable": true,
"deno.unstable": true,
}
Verbinding maken met een database
Voor deze zelfstudie gebruikt u MongoDB als een database om gegevens uit uw API te behouden.
Om uw Deno-app te verbinden met een MongoDB-database, maakt u een db.js bestand in de hoofdmap van uw project en voeg het onderstaande codeblok eraan toe:
// db.js
import { MongoClient } from"https://deno.land/x/[email protected]/mod.ts";const client = new MongoClient();
try {
await client.connect("mongodb://localhost: 27017/todo");console.log("Connected to database");
} catch (err) {
console.log("Error connecting to database", err);
}const db = client.database("todo");
exportdefault db;
In tegenstelling tot Node.js, dat afhankelijk is van pakket beheerders net als de Node Package Manager (npm) of garen, heeft Deno een ingebouwd pakketbeheersysteem voor het rechtstreeks importeren en beheren van afhankelijkheden van URL's.
Het bovenstaande codeblok importeert bijvoorbeeld MongoClient van de url https://deno.land/x/[email protected]/mod.ts, wat naar het pakket leidt.
Gebruik vervolgens het geïmporteerde Deno MongoDB-stuurprogramma (MongoClient), brengt Deno een verbinding tot stand tussen uw applicatie en een lokale MongoDB-database.
In live scenario's is het veiliger om uw databasereferenties op te slaan in een .env bestand in plaats van ze in platte tekst op te slaan, zoals hierboven is gedaan.
Een databasemodel maken
Terwijl het mogelijk is interactie met een MongoDB-database zonder een databasemodel kan dit leiden tot ongestructureerde en minder onderhoudbare code.
Om dit te voorkomen, maakt u een TodoModel.ts bestand in de hoofdmap van uw project en structureer uw gegevens door het onderstaande codeblok aan het bestand toe te voegen:
import db from"./db.ts";
interface Todo {
title: string;
description: string;
completed?: boolean;
}const Todo = db.collection
("todos");
exportdefault Todo;
Het bovenstaande codeblok definieert een interface Te doen dat de structuur van een enkel todo-item vertegenwoordigt. Vervolgens wordt met behulp van de Todo-interface een Todo-verzameling gemaakt door de verzamelingsmethode aan te roepen die wordt weergegeven door uw eerder gemaakte MongoDB-instantie.
Een server maken met Oak
Oak is een middleware voor de native HTTP-server van Deno. Het werd geïnspireerd door Koa, dat is een alternatief voor Express.js.
Om een server met Oak te maken, maakt u een hoofd.ts bestand in de hoofdmap van uw project en voeg het onderstaande codeblok toe aan uw bestand.
// main.ts
import { Application } from"https://deno.land/x/oak/mod.ts";
import router from"./router.ts";const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
await app.listen({ port: 8000 });
console.log("Server running on port 8000");
Het bovenstaande codeblok importeert Sollicitatie van de Oak URL en maakt een toepassingsinstantie (app) die luistert naar inkomend verkeer op poort 8000.
De app.gebruik (router.routes()) line registreert de routes van de router als middleware in de Oak applicatie. Dit betekent dat de applicatie de geregistreerde routes zal matchen met inkomende verzoeken, en de bijbehorende handlers zullen worden uitgevoerd als er een match is.
De app.gebruik (router.allowedMethods()) line behandelt HTTP-methoden die niet expliciet in de router zijn gedefinieerd. Als het bijvoorbeeld een verzoek ontvangt met een niet-ondersteunde methode, bijvoorbeeld een niet-geregistreerd PUT-verzoek, zal het toegestaanMethoden() middleware zal automatisch een passend antwoord sturen (bijv. 405-methode niet toegestaan).
CRUD-functionaliteit implementeren
Deze tutorial bevat een eenvoudige todo-API met CRUD-functionaliteit.
Maak een router.ts bestand in de hoofdmap van uw project en voeg het onderstaande codeblok toe aan uw bestand:
import { Router } from"https://deno.land/x/oak/mod.ts";
import Todo from"./todoModel.ts";
import { ObjectId } from"https://deno.land/x/[email protected]/mod.ts";
const router = new Router(); // Create Router
Het bovenstaande codeblok importeert en maakt een instantie van de Oak-router. Met deze instantie kunt u routehandlers voor verschillende HTTP-methoden maken door de respectievelijke methodenamen aan te roepen (krijgen, na, neerzetten, verwijderen).
Het onderstaande codeblok is bijvoorbeeld een voorbeeld van hoe u een GET-routehandler kunt maken die alle documenten in uw Todo-verzameling retourneert.
router
.get("/api/todos", (ctx: RouterContextapi/todos">) => {
ctx.response.body = Todo.find();
})
Om een antwoordobject te verzenden met Deno, moet u het reactie.lichaam object op de RouterContex naar het antwoordobject. Hetzelfde geldt voor statuscodes.
Om andere route-handlers toe te voegen, kunt u ze koppelen aan de vorige route-handler.
Zoals zo:
.get("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
try {
const todo = await Todo.findOne({ _id: new ObjectId(ctx.params.id) });if (!todo) {
ctx.response.status = 404;ctx.response.body = {
msg: "Todo not found",
};return;
}ctx.response.body = todo;
} catch (error) {
ctx.response.status = 500;
ctx.response.body = {
msg: "Error getting todo",
error,
};
}
})
Het bovenstaande codeblok definieert een GET-routehandler die een enkel Todo-item retourneert dat overeenkomt met de id in de URL-parameters.
Definieer vervolgens een routehandler CREATE die nieuwe documenten aan uw verzameling toevoegt:
.post("/api/todo/new", async (ctx: RouterContext<"/api/todo/new">) => {
const body = ctx.request.body();
const todo = await body.value;if (!todo) {
ctx.response.status = 400;
ctx.response.body = { msg: "Invalid data. Please provide a valid todo." };
return;
}const { title, description } = todo;
if (!(title && description)) {
ctx.response.status = 400;ctx.response.body = {
msg: "Title or description missing. Please provide a valid todo.",
};return;
}try {
await Todo.insertOne({
title: todo.title,
description: todo.description,
completed: false,
});ctx.response.status = 201;
ctx.response.body = {
msg: "Todo added successfully",
};
} catch (error) {
ctx.response.status = 500;
ctx.response.body = {
msg: "Error adding todo",
error,
};
}
})
Voeg vervolgens een PUT-routehandler toe die een Todo bijwerkt op basis van de ID kaart parameter, met de gegevens die in de aanvraagtekst zijn verzonden.
.put("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
try {
const body = ctx.request.body();
const todo = await body.value;await Todo.updateOne(
{ _id: new ObjectId(ctx.params.id) },
{ $set: { title: todo.title, description: todo.description } }
);ctx.response.status = 200;
ctx.response.body = {
msg: "Todo updated successfully",
};
} catch (error) {
console.log(error);
ctx.response.status = 500;
ctx.response.body = {
msg: "Error updating todo",
error: error.message,
};
}
})
Maak ten slotte een DELETE-routehandler die een Todo uit uw MongoDB-verzameling verwijdert:
.delete("/api/todo/:id", async (ctx: RouterContext<"/api/todo/:id">) => {
await Todo.deleteOne({ _id: new ObjectId(ctx.params.id) });ctx.response.status = 200;
ctx.response.body = {
msg: "Todo deleted successfully",
};
});
U kunt uw Deno-app starten met dit commando:
deno run --allow-net --allow-read --allow-env --watch main.ts
Standaard heeft een Deno-script geen toegang tot iets buiten zijn bereik, zoals het netwerk of het bestandssysteem. Dus om uw applicatie te starten, moet u verschillende vlaggen toevoegen om Deno de vereiste machtigingen te verlenen.
--toestaan-net stelt Deno in staat om netwerkverzoeken te doen. --toestaan-lezen geeft Deno toegang tot het bestandssysteem en kan bestanden lezen. --allow-env geeft Deno toegang tot omgevingsvariabelen. De --horloge vlag start uw Deno-app in horlogemodus.
Migreren van Node.js naar Deno
Migreren van Node.js naar Deno voor het bouwen van REST API's kan aanzienlijke voordelen opleveren op het gebied van veiligheid, ontwikkelaarsproductiviteit en afhankelijkheidsbeheer. Met behulp van Deno's veilige runtime, native TypeScript-ondersteuning en vereenvoudigd afhankelijkheidsbeheer kunt u eenvoudig robuuste en efficiënte REST API's maken.
Het onvolgroeide ecosysteem van Deno kan er echter toe leiden dat u van mening verandert. Als u ervoor kiest om te migreren, weeg dan zorgvuldig de voor- en nadelen af.