Nouveau : Datasets open source gratuits disponibles !Decouvrir →
Intermediaire 20 min Next.js

Deployer Next.js sur Fly.io

Pourquoi Deployer Next.js sur Fly.io ?

Deployer un application Next.js sur Fly.io permet une mise en production rapide et élastique, avec des coûts optimisés. Cela est particulièrement utile pour les développeurs qui cherchent à rendre leurs applications accessibles et scalables sans avoir besoin d'infrastructure physique. Un cas concret serait de créer un service de gestionnaire de tâches en ligne où les utilisateurs peuvent ajouter, modifier et supprimer des tâches.

Prerequis

  • Connaissance avancée du langage JavaScript
  • Familiarité avec le framework Next.js
  • Installation de Node.js v14.0 ou plus tard
  • Installation de Docker

Concepts fondamentaux

1. Fly.io

Fly.io est une plateforme d'hébergement pour des applications web et microservices. Il permet de déployer, évoluer et mettre à l'échelle des applications en quelques minutes.

## Installation de Fly CLI
curl -L https://fly.io/install.sh | sh

2. Next.js App Router

Next.js 13 introduit le nouveau App Router qui permet une structure de routing plus modulaire et efficace, basée sur les fichiers du système de fichiers.

// pages/dashboard/index.js
import Link from 'next/link';

export default function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Link href="/tasks">
        <a>Gestion des tâches</a>
      </Link>
    </div>
  );
}

3. Variables d'environnement

Fly.io permet de définir des variables d'environnement pour votre application, ce qui est utile pour stocker des secrets ou des configurations spécifiques à l'environnement.

## Définir une variable d'environnement dans Fly.io
flyctl config set DATABASE_URL=postgres://user:password@host:port/dbname

Mise en pratique : projet fil rouge

Nous allons créer un simple gestionnaire de tâches en ligne. Le projet comprendra les fonctionnalités suivantes :

  • Ajouter une nouvelle tâche
  • Modifier une tâche existante
  • Supprimer une tâche

Étape 1 : Initialisation du projet

Commencez par initialiser un nouveau projet Next.js.

## Créer un nouveau projet Next.js
npx create-next-app@latest task-manager
cd task-manager

Étape 2 : Configuration de la base de données

Nous utiliserons PostgreSQL pour stocker les tâches. Créez une base de données et configurez les variables d'environnement.

## Créer une base de données PostgreSQL
createdb task_manager

## Définir les variables d'environnement dans fly.toml
[env]
DATABASE_URL = "postgres://user:password@host:port/task_manager"

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

Créez un fichier db.js pour gérer la connexion à la base de données.

// db.js
import { Pool } from 'pg';

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

export default pool;

Étape 4 : Création des modèles

Créez un fichier taskModel.js pour définir les opérations CRUD sur la tâche.

// taskModel.js
import db from './db';

export const getTasks = async () => {
  const result = await db.query('SELECT * FROM tasks');
  return result.rows;
};

export const createTask = async (task) => {
  const { title, description } = task;
  const result = await db.query(
    'INSERT INTO tasks (title, description) VALUES ($1, $2) RETURNING *',
    [title, description]
  );
  return result.rows[0];
};

export const updateTask = async (id, task) => {
  const { title, description } = task;
  const result = await db.query(
    'UPDATE tasks SET title=$1, description=$2 WHERE id=$3 RETURNING *',
    [title, description, id]
  );
  return result.rows[0];
};

export const deleteTask = async (id) => {
  const result = await db.query('DELETE FROM tasks WHERE id=$1', [id]);
  return result.rowCount > 0;
};

Étape 5 : Création des routes API

Créez des fichiers pour les routes API dans pages/api.

// pages/api/tasks.js
import { getTasks, createTask, updateTask, deleteTask } from '../../taskModel';

export default async function handler(req, res) {
  const { method, body } = req;

  switch (method) {
    case 'GET':
      try {
        const tasks = await getTasks();
        res.status(200).json(tasks);
      } catch (error) {
        res.status(500).json({ message: error.message });
      }
      break;
    case 'POST':
      try {
        const newTask = await createTask(body);
        res.status(201).json(newTask);
      } catch (error) {
        res.status(400).json({ message: error.message });
      }
      break;
    default:
      res.setHeader('Allow', ['GET', 'POST']);
      res.status(405).end(`Method ${method} Not Allowed`);
  }
}
nextjs
// pages/api/tasks/[id].js
import { getTasks, updateTask, deleteTask } from '../../taskModel';

export default async function handler(req, res) {
  const { method, body, query: { id } } = req;

  switch (method) {
    case 'GET':
      try {
        const task = await getTasks();
        res.status(200).json(task);
      } catch (error) {
        res.status(500).json({ message: error.message });
      }
      break;
    case 'PUT':
      try {
        const updatedTask = await updateTask(id, body);
        res.status(200).json(updatedTask);
      } catch (error) {
        res.status(400).json({ message: error.message });
      }
      break;
    case 'DELETE':
      try {
        const deleted = await deleteTask(id);
        if (deleted) {
          res.status(204).end();
        } else {
          res.status(404).json({ message: 'Tâche non trouvée' });
        }
      } catch (error) {
        res.status(500).json({ message: error.message });
      }
      break;
    default:
      res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
      res.status(405).end(`Method ${method} Not Allowed`);
  }
}

Étape 6 : Création des composants UI

Créez les composants React pour afficher et modifier les tâches.

// pages/index.js
import { useState, useEffect } from 'react';
import axios from 'axios';

const Home = () => {
  const [tasks, setTasks] = useState([]);
  const [newTask, setNewTask] = useState({ title: '', description: '' });
  const [editingTask, setEditingTask] = useState(null);

  useEffect(() => {
    fetchTasks();
  }, []);

  const fetchTasks = async () => {
    try {
      const response = await axios.get('/api/tasks');
      setTasks(response.data);
    } catch (error) {
      console.error('Erreur lors de la récupération des tâches', error);
    }
  };

  const handleAddTask = async () => {
    try {
      await axios.post('/api/tasks', newTask);
      fetchTasks();
      setNewTask({ title: '', description: '' });
    } catch (error) {
      console.error('Erreur lors de l\'ajout d\'une tâche', error);
    }
  };

  const handleEditTask = async () => {
    try {
      await axios.put(`/api/tasks/${editingTask.id}`, editingTask);
      fetchTasks();
      setEditingTask(null);
    } catch (error) {
      console.error('Erreur lors de la mise à jour d\'une tâche', error);
    }
  };

  const handleDeleteTask = async (id) => {
    try {
      await axios.delete(`/api/tasks/${id}`);
      fetchTasks();
    } catch (error) {
      console.error('Erreur lors de la suppression d\'une tâche', error);
    }
  };

  return (
    <div>
      <h1>Gestionnaire de Tâches</h1>
      {editingTask ? (
        <form onSubmit={handleEditTask}>
          <input
            type="text"
            value={editingTask.title}
            onChange={(e) => setEditingTask({ ...editingTask, title: e.target.value })}
            required
          />
          <textarea
            value={editingTask.description}
            onChange={(e) => setEditingTask({ ...editingTask, description: e.target.value })}
            required
          ></textarea>
          <button type="submit">Enregistrer</button>
        </form>
      ) : (
        <form onSubmit={handleAddTask}>
          <input
            type="text"
            value={newTask.title}
            onChange={(e) => setNewTask({ ...newTask, title: e.target.value })}
            required
          />
          <textarea
            value={newTask.description}
            onChange={(e) => setNewTask({ ...newTask, description: e.target.value })}
            required
          ></textarea>
          <button type="submit">Ajouter</button>
        </form>
      )}
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            {task.title} - {task.description}
            <button onClick={() => setEditingTask(task)}>Modifier</button>
            <button onClick={() => handleDeleteTask(task.id)}>Supprimer</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default Home;

Erreurs frequentes et debugging

1. Error: connect ECONNREFUSED 127.0.0.1:5432

Cause : La base de données PostgreSQL n'est pas démarrée.

## Démarrer la base de données PostgreSQL
pg_ctl -D /usr/local/var/postgres start

2. Error: listen EADDRINUSE :::3000

Cause : Le port 3000 est déjà utilisé par une autre application.

## Trouver l'application utilisant le port 3000 et la terminer
lsof -i :3000
kill -9 <PID>

3. Error: connect ECONNREFUSED <DATABASE_URL>

Cause : La chaîne de connexion à la base de données est incorrecte.

## Vérifier la chaîne de connexion dans fly.toml
flyctl config get DATABASE_URL

Pour aller plus loin

  1. Déploiement sur un domaine personnalisé : Apprenez comment déployer votre application Next.js sur un domaine personnalisé avec Fly.io.
  2. Intégration avec des services externes : Intégrez des services externes comme Google Maps ou OpenAI pour enrichir votre application.
  3. Tests automatisés : Ajoutez des tests automatisés à votre projet en utilisant Jest et React Testing Library.

Défi pratique

Déployez votre gestionnaire de tâches sur Fly.io en suivant les étapes ci-dessus. Assurez-vous que la base de données fonctionne correctement, que l'API est accessible via les routes /api/tasks et /api/tasks/[id], et que l'interface utilisateur permet d'ajouter, modifier et supprimer des tâches.

Besoin d'aide sur Next.js ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que Fly.io?
Fly.io est une plateforme pour le déploiement d'applications web et microservices sur un réseau mondial de points de terminaison.
Comment installer Next.js sur mon ordinateur local?
Pour installer Next.js localement, vous devez avoir Node.js installé. Ensuite, vous pouvez créer un nouveau projet Next.js en utilisant la commande `npx create-next-app@latest my-next-app`.
Comment déployer mon application Next.js sur Fly.io?
Pour déployer votre application Next.js sur Fly.io, vous devez d'abord créer une image Docker de votre application. Ensuite, utilisez la commande `flyctl deploy` pour déployer votre application sur le réseau Fly.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.