Comment déployer une application Deno ?

How to Deploy a Deno Application_
How to Deploy a Deno Application_

Il existe différentes options de déploiement pour les applications web construites avec Deno. Cependant, la conteneurisation en tant que plateforme de service est devenue un choix populaire ces derniers temps en raison des nombreux avantages qu’elle offre par rapport aux autres options de déploiement.

Dans cet article, vous explorerez Deno, ses avantages et ses limites. De plus, vous allez construire une application Deno simple et la déployer sur des conteneurs Back4app.

Qu’est-ce que Deno ?

Deno est un moteur d’exécution sécurisé et moderne pour JavaScript et TypeScript, créé pour répondre aux limitations et aux défauts de conception de Node.js.

Contrairement à Node.js, il met l’accent sur la sécurité par défaut, en imposant des permissions granulaires pour le système de fichiers et l’accès au réseau.

De plus, Deno supporte nativement TypeScript, éliminant ainsi le besoin d’étapes supplémentaires de configuration ou de transpilation, entre autres.

Depuis sa sortie en 2018, Deno a suscité l’attention et l’intérêt des développeurs en raison de ses améliorations par rapport à Node.js.

Cependant, bien que Deno apporte des améliorations, Node.js reste un écosystème mature avec un soutien important de la communauté et un vaste dépôt de paquets.

Néanmoins, Deno a attiré une communauté croissante de développeurs qui apprécient son approche et explorent son potentiel.

Avantages de Deno

La popularité croissante de Deno s’explique par plusieurs raisons sous-jacentes. En voici quelques-unes.

Sécurité améliorée par rapport à Node.js

Deno offre une sécurité améliorée comme avantage clé, en mettant en œuvre un modèle de sécurité basé sur les permissions et en exécutant les applications dans un environnement sandboxé.

Il met en œuvre un modèle de sécurité basé sur les autorisations, dans lequel une autorisation explicite est requise pour accéder à des ressources telles que le système de fichiers et le réseau.

Par défaut, Deno fonctionne en mode restreint et exécute les applications dans un environnement sandboxé, limitant les actions potentiellement risquées, les isolant du système sous-jacent et empêchant l’accès direct aux ressources sensibles.

Des audits de sécurité complets et des revues de code méticuleuses renforcent encore la sécurité robuste de Deno. Ces mesures vous offrent une plateforme fiable et sécurisée pour créer des applications, inspirer confiance dans leur sécurité et les protéger contre les vulnérabilités potentielles.

Gestion de la dépendance

Deno offre une approche distincte de la gestion des dépendances par rapport aux environnements d’exécution JavaScript traditionnels tels que Node.js.

Au lieu de s’appuyer sur un registre de paquets centralisé, Deno utilise des URL pour importer des modules directement depuis le web.

Cette approche simplifie le processus en éliminant le besoin d’un gestionnaire de paquets séparé comme npm et en atténuant les problèmes liés aux conflits de versions et à la complexité de la gestion du dossier “node_modules”.

Vous pouvez spécifier les dépendances en indiquant les URL des modules à importer, ce qui facilite le partage et la distribution du code. Cette approche décentralisée de la gestion des dépendances dans Deno favorise la simplicité, réduit les frictions et contribue à une expérience de développement plus rationalisée.

Prise en charge de TypeScript dès le départ

Deno offre un support natif et transparent pour TypeScript, ce qui en fait un excellent choix si vous préférez ou avez besoin de TypeScript dans vos projets.

TypeScript est un surensemble typé de JavaScript qui apporte le typage statique et d’autres fonctionnalités avancées au développement JavaScript. Avec Deno, il n’y a pas besoin de configuration ou d’étapes de construction supplémentaires pour utiliser TypeScript.

Deno est livré avec le compilateur TypeScript, ce qui vous permet d’écrire et d’exécuter directement du code TypeScript.

Cette prise en charge native élimine la complexité de la mise en place d’une chaîne d’outils TypeScript distincte et simplifie le processus de développement.

Il vous permet de tirer parti de la vérification des types TypeScript, de l’amélioration des outils et de l’amélioration de l’expérience des développeurs lors de la création d’applications avec Deno.

Limites de Deno

Cependant, Deno présente certaines limites qui freinent son adoption. En voici quelques-unes.

Écosystème immature

L’une des limites de Deno est la maturité de son écosystème. Comparé à Node.js, qui existe depuis plus longtemps, l’écosystème de Deno est encore relativement nouveau et en pleine évolution.

Cela signifie qu’il peut y avoir moins de bibliothèques, de frameworks et d’outils tiers spécifiquement conçus pour Deno. Il se peut que vous deviez créer certaines fonctionnalités à partir de zéro ou adapter des paquets Node.js existants pour les utiliser dans Deno.

La taille réduite de la communauté signifie également qu’il peut y avoir moins de ressources, de tutoriels et de support communautaire disponibles par rapport à l’écosystème Node.js bien établi.

Cependant, à mesure que Deno gagne en popularité et en adoption, son écosystème devrait se développer et mûrir, offrant à l’avenir une gamme plus large de bibliothèques et d’outils.

Une courbe d’apprentissage abrupte

Une autre limite de Deno est la courbe d’apprentissage associée à la transition depuis d’autres environnements d’exécution JavaScript, tels que Node.js.

Deno introduit de nouveaux concepts, API et modèles avec lesquels vous devrez peut-être vous familiariser. Il s’agit notamment de comprendre le système de modules de Deno, le modèle de sécurité basé sur les permissions, et les différences dans la façon dont certaines fonctionnalités sont implémentées par rapport à d’autres runtimes.

Les développeurs qui maîtrisent déjà Node.js devront peut-être consacrer du temps et des efforts à l’apprentissage et à l’adaptation aux caractéristiques et conventions spécifiques de Deno.

Cependant, la courbe d’apprentissage peut être gérée en se référant à la documentation officielle de Deno, en s’engageant avec la communauté Deno et en explorant les ressources d’apprentissage disponibles.

Compatibilité avec les bibliothèques Node.js

La compatibilité avec les bibliothèques Node.js est une autre limitation de Deno. En raison des différences entre les systèmes de modules et les environnements d’exécution, toutes les bibliothèques et modules Node.js ne peuvent pas être utilisés directement dans Deno sans modifications.

Deno utilise des modules ES (modules ECMAScript) comme système de modules, alors que Node.js utilise traditionnellement des modules CommonJS. Cette différence dans les formats de modules peut entraîner des incompatibilités lors de l’importation et de l’utilisation de modules spécifiques à Node.js dans Deno.

Les développeurs devront peut-être procéder à des ajustements ou trouver des bibliothèques alternatives spécifiquement conçues pour fonctionner avec le système de modules de Deno.

Bien que Deno fournisse une couche de compatibilité permettant d’exécuter certains modules Node.js, elle ne couvre pas tous les cas, et des modifications ou adaptations manuelles peuvent être nécessaires.

Options de déploiement de Deno

Il existe plusieurs options de déploiement pour les applications Deno, dont les suivantes.

Infrastructure en tant que service (IaaS)

L’infrastructure en tant que service (IaaS) est un modèle d’informatique en nuage qui offre des ressources informatiques virtualisées. Avec l’IaaS, vous pouvez louer des machines virtuelles, du stockage et des réseaux auprès de fournisseurs d’informatique en nuage sur la base d’un paiement à l’utilisation. Cela vous permet de mettre en place et de gérer votre propre infrastructure virtualisée sans investir dans du matériel physique.

Les options IaaS vous permettent d’exécuter des applications Deno sur des machines virtuelles. Les plateformes IaaS populaires comme AWS, Google Cloud et Microsoft Azure offrent des solutions flexibles et évolutives, vous permettant de configurer l’infrastructure en fonction des besoins spécifiques de votre application.

Cependant, si l’IaaS vous permet de mieux contrôler et d’isoler les ressources, il exige également une configuration et une gestion plus manuelles, impliquant des tâches telles que le provisionnement des serveurs, les mises à jour de sécurité et la surveillance.

Par conséquent, l’IaaS est un choix viable lorsque vous avez besoin d’un contrôle étendu sur votre infrastructure et que vous disposez de l’expertise nécessaire pour gérer efficacement ses complexités.

Conteneurs en tant que service (CaaS)

Container-as-a-Service (CaaS) est un modèle d’informatique en nuage qui simplifie le déploiement et la gestion d’applications conteneurisées.

Avec CaaS, vous pouvez vous concentrer sur la création et le déploiement d’applications sans vous soucier de l’infrastructure sous-jacente.

Les applications Deno peuvent être déployées dans des conteneurs, ce qui garantit la cohérence et l’isolation. Back4app containers est une option CaaS populaire pour le déploiement de Deno.

Les plateformes CaaS offrent une évolutivité et une isolation des ressources, chaque application fonctionnant dans son propre conteneur, ce qui renforce la sécurité et la stabilité.

La cohérence des conteneurs garantit que les applications Deno peuvent être facilement déployées sur n’importe quelle plateforme supportant les conteneurs.

Bien que les solutions CaaS aient une courbe d’apprentissage, elles offrent des avantages significatifs pour les applications nécessitant une mise à l’échelle et un déploiement dynamiques sur plusieurs nœuds ou grappes.

Processus d’installation de Deno

Avant de pouvoir utiliser Deno, vous devez le télécharger et l’installer. L’installation de Deno varie en fonction de votre système d’exploitation.

Sur macOS et Linux, vous pouvez installer Deno en exécutant la commande ci-dessous :

curl -fsSL <https://deno.land/x/install/install.sh> | sh

Sous Windows, vous pouvez installer Deno à l’aide de Powershell en exécutant la commande ci-dessous :

irm <https://deno.land/install.ps1> | iex

Pour confirmer que votre installation a réussi, vous pouvez exécuter la commande ci-dessous, qui devrait afficher un numéro de version dans votre terminal.

deno --version

Si vous ne voyez pas le numéro de version, essayez d’installer Deno à nouveau.

Mise en place d’un projet Deno

Pour créer une API simple avec Deno, vous aurez besoin d’un routeur, d’un serveur et d’une base de données.

Avant de suivre les étapes ci-dessous, créez un dossier src dans le répertoire racine de votre projet. Ce dossier contiendra tous les fichiers sources de votre projet.

Étape 1 : Création d’un fichier de dépendance

Contrairement à Node.js, Deno n’utilise pas de gestionnaires de paquets comme NPM ou Yarn. Les paquets sont importés directement à partir de leur URL.

Pour imiter les fonctions d’un fichier package.json, créez un fichier deps.ts dans le répertoire racine de votre projet et ajoutez-y le bloc de code ci-dessous.

export { Application, Router } from "https://deno.land/x/[email protected]/mod.ts";
export type { RouterContext} from "https://deno.land/x/[email protected]/mod.ts";
export { config as dotenvConfig } from "https://deno.land/x/[email protected]/mod.ts";
export { Client } from "https://deno.land/x/[email protected]/mod.ts";

Le bloc de code ci-dessus importe (installe) et exporte Application, Router et RouterContex de Oak. config de dotenv et Client de deno-postgres.

Étape 2 : Création d’un serveur

Pour cette étape, vous allez créer un simple serveur HTTP avec Oak. Oak est un middleware pour le serveur HTTP de Deno basé sur Koa.js, un framework pour Node.js similaire à Express mais plus léger.

Pour créer un serveur HTTP avec Oak, créez un fichier server.ts dans votre src et ajoutez-y le bloc de code ci-dessous.

import { Application } from "../deps.ts";
import config from "../config/default.ts";

import router from "./router.ts";

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: config.port });

Le bloc de code ci-dessus crée un serveur HTTP avec Oak et enregistre un routeur pour gérer tout le trafic entrant.

La ligne app.use(router.routes()) enregistre les routes du routeur en tant qu’intergiciel dans l’application Oak. Toutes les requêtes entrantes seront comparées aux routes enregistrées et les gestionnaires correspondants seront exécutés si une correspondance est trouvée.

Si une correspondance n’est pas trouvée, la ligne app.use(router.allowedMethods()) les traite en envoyant des réponses appropriées telles que 404 not found ou 405 not allowed.

Étape 3 : Gestion des variables environnementales

Le stockage de données sensibles, telles que les clés d’API, les identifiants de base de données, etc., en texte clair présente un risque pour la sécurité. Toute personne qui s’empare de vos clés ou de vos identifiants peut avoir un accès illimité à votre application. Il peut en résulter une perte ou un vol de données, entre autres exploits possibles.

Pour éviter ce genre de situation, il est recommandé de stocker les données sensibles dans des variables d’environnement.

Créez un fichier .env dans le dossier racine de votre projet et stockez-y vos identifiants de base de données et d’autres informations sensibles.

Comme cela :

#.env
DB_URI = <YOUR_POSTGRES_DB_URI>
PORT = 8000

Remplacez par vos identifiants de base de données.

Ensuite, créez un dossier config dans le dossier racine de votre projet, et dans le dossier config, créez un fichier default.ts et ajoutez-y le bloc de code ci-dessous.

//default.ts
import { dotenvConfig } from "../deps.ts";

dotenvConfig({
  export: true,
  path: "../.env",
});

const config = {
  db: {
    dbUri: Deno.env.get("DB_URI"),
  },
  port: 3000
};

export default config;

Le bloc de code ci-dessus récupère en toute sécurité les valeurs stockées dans votre fichier .env et les expose au reste de votre application.

Étape 3 : Connexion à une base de données

Pour cette étape, vous allez connecter votre application à une base de données Postgres. Vous aurez besoin de la base de données pour stocker et récupérer des données pour votre application.

Créez un fichier db.ts dans votre dossier src et ajoutez-y le bloc de code ci-dessous.

//db.ts
import { Client } from "../deps.ts";
import config from "../config/default.ts";

let postgresConfiguration = config.db.dbUri;

const client = new Client(postgresConfiguration);

await client.connect();

export default client;

Le bloc de code ci-dessus tente de connecter votre application à une base de données Postgres en utilisant l’URI que vous avez fourni dans votre fichier .env.

Étape 4 : Création d’un référentiel de base de données

Créez un fichier blogRepository dans votre dossier src et ajoutez-y le code ci-dessous.

//blogRepository.ts
import client from "./db.ts";

class BlogRepository {
  async createBlogTable() {
    const blog = await client.queryArray(
      `CREATE TABLE IF NOT EXISTS blogs (id SERIAL PRIMARY KEY, title VARCHAR(255), body VARCHAR(255), author VARCHAR(255))`
    );

    return blog;
  }

  async getAllBlogs() {
    const allBlogs = await client.queryArray("SELECT * FROM blogs");

    return allBlogs;
  }

  async getBlogById(id: string) {
    const blog = await client.queryArray(
      `SELECT * FROM blogs WHERE id = ${id}`
    );

    return blog;
  }

  async createBlog(title: string, body: string, author: string) {
    const blog = await client.queryArray(
      `INSERT INTO blogs (title, body, author) VALUES ('${title}', '${body}', '${author}')`
    );

    return blog;
  }

  async updateBlog(id: string, title: string, body: string, author: string) {
    const blog = await client.queryArray(
      `UPDATE blogs SET title = '${title}', body = '${body}', author = '${author}' WHERE id = ${id}`
    );

    return blog;
  }

  async deleteBlog(id: string) {
    const blog = await client.queryArray(`DELETE FROM blogs WHERE id = ${id}`);

    return blog;
  }
}

export default new BlogRepository();

Le bloc de code ci-dessus gère toutes les opérations de base de données en abstrayant les requêtes SQL brutes et en exposant des méthodes simples que vous pouvez utiliser pour interagir avec votre base de données Postgres.

Étape 5 : Création de gestionnaires d’itinéraires

Pour cette étape, vous allez créer des gestionnaires de routes pour gérer des fonctions CRUD simples pour votre application. Les routes prises en charge sont les suivantes :

  • GET /api/blogs : Retourne tous les blogs de votre base de données
  • GET /api/blog/:id : Renvoie un seul blog avec l’identifiant correspondant fourni dans les paramètres de l’URL.
  • POST /api/blog/new : crée un nouveau blog dans votre base de données.
  • PUT /api/blog/:id : Met à jour un blog avec l’identifiant correspondant fourni dans les paramètres de l’URL.
  • DELETE /api/blog/:id : Supprime un blog dont l’identifiant correspond à celui fourni dans les paramètres de l’URL.

Créez un fichier router.ts dans votre dossier src et ajoutez-y les importations suivantes.

import { Router, RouterContext } from "../deps.ts";
import blogRepository from "./blogRepository.ts";

Ensuite, créez une instance de routeur en y ajoutant le bloc de code ci-dessous :

const router = new Router();

Pour enregistrer vos gestionnaires de routeur, vous devez les associer à l’instance de routeur.

Par exemple (GET /api/blogs) :

router
  .get("/api/blogs", async (ctx: RouterContext<"/api/blogs">) => {
    const data = await blogRepository.getAllBlogs();
    console.log(data);

    //format data
    const allBlogs = data.rows.map((blog) => {
      return {
        id: blog[0],
        title: blog[1],
        body: blog[2],
        author: blog[3]
      };
    });

    ctx.response.body = allBlogs;
  })

Le bloc de code ci-dessus crée un gestionnaire de route pour GET /api/blogs en enchaînant la logique du gestionnaire à l’instance de routeur.

Enchaînez-les à la méthode précédemment enchaînée pour enregistrer le reste des itinéraires. Par exemple :

GET /api/blog/:id :

.get("/api/blog/:id", async (ctx: RouterContext<"/api/blog/:id">) => {
    try {
      const data = await blogRepository.getBlogById(ctx.params.id);
      console.log(data);

      //format data
      const blog = data.rows.map((blog) => {
        return {
          id: blog[0],
          title: blog[1],
          body: blog[2],
          author: blog[3]
        };
      });

      ctx.response.body = blog;
    } catch (error) {
      ctx.response.status = 500;
      ctx.response.body = {
        msg: "Error getting blog",
        error,
      };
    }
  })

POST /api/blog/new

.post("/api/blog/new", async (ctx: RouterContext<"/api/blog/new">) => {
    const resBody = ctx.request.body();
    const blog = await resBody.value;

    if (!blog) {
      ctx.response.status = 400;
      ctx.response.body = { msg: "Invalid data. Please provide a valid blog." };
      return;
    }

    const { title, body, author } = blog;

    if (!(title && body && author)) {
      ctx.response.status = 400;
      ctx.response.body = {
        msg: "Title or description missing. Please provide a valid blog.",
      };
      return;
    }

    try {
      await blogRepository.createBlog(title, body, author);

      ctx.response.status = 201;
      ctx.response.body = {
        msg: "blog added successfully",
      };
    } catch (error) {
      ctx.response.status = 500;
      ctx.response.body = {
        msg: "Error adding blog",
        error,
      };
    }
  })

PUT /api/blog/:id :

.put("/api/blog/:id", async (ctx: RouterContext<"/api/blog/:id">) => {
    try {
      const resBody = ctx.request.body();
      const blog = await resBody.value;

      if (!blog) {
        ctx.response.status = 400;
        ctx.response.body = {
          msg: "Invalid data. Please provide a valid blog.",
        };
        return;
      }

      const { title, body, author } = blog;

      if (!(title && body && author)) {
        ctx.response.status = 400;
        ctx.response.body = {
          msg: "Title or description missing. Please provide a valid blog.",
        };

        return;
      }

      await blogRepository.updateBlog(ctx.params.id, title, body, author);

      ctx.response.status = 200;
      ctx.response.body = {
        msg: "blog updated successfully",
      };
    } catch (error) {
      console.log(error);
      ctx.response.status = 500;
      ctx.response.body = {
        msg: "Error updating blog",
        error: error.message,
      };
    }
  })

DELETE /api/blog/:id :

.delete("/api/blog/:id", async (ctx: RouterContext<"/api/blog/:id">) => {
    await blogRepository.deleteBlog(ctx.params.id);

    ctx.response.status = 200;
    ctx.response.body = {
      msg: "blog deleted successfully",
    };
  });

Ensuite, exportez votre instance de routeur. Comme suit :

export default router;

Enfin, modifiez votre fichier server.ts pour créer une base de données de blogs au premier démarrage de votre application.

Comme cela :

import { Application } from "../deps.ts";
import config from "../config/default.ts";
import blogRepository from "./blogRepository.ts";

import router from "./router.ts";

const app = new Application();

(async () => {
  await blogRepository.createBlogTable();
})();

app.use(router.routes());
app.use(router.allowedMethods());

await app.listen({ port: config.port });

Le code modifié ajoute au fichier server.ts un IIFE qui crée une nouvelle table de blog dans votre base de données.

Déployer votre application Deno sur des conteneurs Back4app

Pour déployer votre application Deno sur des conteneurs Back4app, vous devez suivre les étapes ci-dessous :

Étape 1 : Créer un fichier Docker

Un Dockerfile fournit des instructions spécifiques pour la construction d’une image Docker. Ces instructions guident le processus de construction de l’image.

Exécutez la commande ci-dessous pour créer un fichier Docker :

touch Dockerfile

La commande ci-dessus crée un fichier Docker dans le répertoire racine de votre projet.

Ensuite, ajoutez le bloc de code ci-dessous à votre fichier Docker :

FROM denoland/deno:latest

EXPOSE 8000

WORKDIR /app

COPY deps.ts .
RUN deno cache deps.ts

COPY . .

RUN deno cache src/server.ts

CMD ["run", "--allow-net", "--allow-env", "--allow-read", "src/server.ts"]

Le fichier Docker ci-dessus met en place un environnement conteneurisé pour l’exécution d’une application Deno. Il met en cache les dépendances de l’application et le point d’entrée, puis exécute l’application Deno avec les autorisations spécifiées lorsque le conteneur est démarré.

L’application est censée écouter sur le port 8000, mais le mappage du port doit être effectué lors de l’exécution du conteneur.

Enfin, publiez votre code sur GitHub.

Étape 2 : Créer une nouvelle application Back4app

Pour créer une application Back4app, visitez le site officiel de Back4app. Une fois sur le site, repérez le bouton S’inscrire dans le coin supérieur droit de la page d’accueil de Back4app. Vous serez dirigé vers un formulaire d’inscription après avoir cliqué sur le bouton S’inscrire. Remplissez ce formulaire avec les informations requises, telles que votre adresse e-mail, votre nom d’utilisateur et votre mot de passe. Veillez à fournir des informations exactes. Une fois le formulaire rempli, envoyez-le.

Si vous avez déjà un compte, cliquez plutôt sur Connexion.

Une fois que vous avez créé votre compte Back4app, connectez-vous pour accéder au tableau de bord de votre compte. De là, localisez le bouton “NEW APP” et cliquez dessus.

Cette action vous dirigera vers une page où différentes options vous seront présentées pour créer votre nouvelle application. Puisque votre intention est de déployer en utilisant la conteneurisation, optez pour l’option“Containers as a Service“.

Ensuite, connectez votre compte GitHub à votre compte Back4app. Vous pouvez donner à Back4app l’accès à tous les dépôts de votre compte ou à des dépôts spécifiques.

Choisissez l’application que vous souhaitez déployer, dans ce cas, l’application que vous avez créée dans ce tutoriel, et cliquez sur Sélectionner.

Choisir le référentiel à déployer

En cliquant sur le bouton de sélection, vous accéderez à une page où vous devrez fournir des informations sur votre application, telles que le nom, la branche, le répertoire racine, les options de déploiement automatique, le port, la santé et les variables d’environnement.

Veillez à fournir toutes les variables environnementales nécessaires au bon fonctionnement de votre application. Une fois que vous avez rempli les informations requises, cliquez sur le bouton “Créer une application”.

Remplissez les détails de votre application

Cela lancera le processus de déploiement, et après un certain temps, votre déploiement devrait être prêt. Si le processus de déploiement prend beaucoup de temps, vous pouvez vérifier les journaux pour voir si une erreur s’est produite lors du déploiement ou consulter le guide de dépannage de Back4app.

Conclusion

Dans cet article, vous avez exploré Deno, ses avantages, ses limitations, ses options de déploiement populaires, comment construire une application avec Deno, et déployer votre application en utilisant les conteneurs Back4app.

Malgré ses limites, grâce à son modèle de sécurité, Deno peut être idéal pour construire des applications très sécurisées et sensibles. De plus, son support natif de TypeScript élimine les problèmes liés à la mise en place de TypeScript dans votre projet.

En suivant les étapes décrites dans cet article, vous pouvez facilement créer et déployer votre application Deno sur des conteneurs Back4app.

FAQ

Qu’est-ce que Deno ?

Deno est un environnement d’exécution JavaScript/TypeScript sécurisé et moderne qui permet aux développeurs de créer des applications côté serveur et côté client.

Comment déployer une application Deno ?

1. Créez une application Deno
2. Créez un Dockerfile
3. Déployez votre application Deno sur GitHub et connectez votre compte GitHub à votre compte Back4app.
4. Créez une application CaaS sur Back4app
5. Sélectionnez votre application Deno dans votre liste de dépôts
6. Déployez votre application Deno


Leave a reply

Your email address will not be published.