Site icon Blog ARC Optimizer

Comment optimiser la gestion des fichiers dans Next.js

Comment optimiser la gestion des fichiers dans Next.js


Voyons comment optimiser la gestion des fichiers dans une application moderne utilisant Edge Store. Nous verrons certains des avantages qu’il offre, les processus de configuration et comment implémenter certaines de ses fonctionnalités dans une application Next.js.

Lors de la création d’applications Web modernes, il est presque inévitable de gérer les fichiers d’une manière ou d’une autre. Cela peut impliquer de collecter des images d’utilisateurs, de gérer des vidéos, de générer ou d’héberger des PDF, entre autres tâches liées aux fichiers. Cependant, la gestion manuelle de ces fichiers dans les applications Next.js peut s’avérer difficile. Non seulement cela prend du temps et est sujet aux erreurs, mais il manque également de fonctionnalités d’optimisation et d’évolutivité.

Bien que de nombreuses options de gestion de fichiers soient disponibles, cet article se concentrera sur Magasin Edge. Edge Store a été présenté comme une solution de type sécurisé qui simplifie la gestion des fichiers dans les applications Web en éliminant les complexités liées à l’utilisation de fichiers. Il élimine le besoin de se soucier de facteurs tels que l’intégration, les performances, la vitesse, la prise en charge des fichiers volumineux et la validation, entre autres.

Dans cet article, nous explorerons certains des avantages offerts par Edge Store, les processus de configuration et comment implémenter ses fonctionnalités dans un Suivant.js application.

Qu’est-ce qu’Edge Store ?

En termes simples, Edge Store est un package convivial pour les développeurs qui simplifie la gestion des fichiers dans les applications Web. Basé sur la sécurité des types, il permet le téléchargement et la récupération de fichiers à partir d’un stockage cloud distant avec une installation et une configuration minimales.

En outre, il offre également un large éventail d’avantages qui contribuent à rendre le traitement des fichiers efficace, plus sécurisé et plus convivial.

Voici quelques-uns de ses avantages :

  • Type de sécurité: TRPC a été une énorme source de référence lors de la création du package Edge Store ; par conséquent, il partage de nombreux modèles avec TRPC et offre une sécurité de type stricte lors de la mise en œuvre.

  • Intégration simple: Edge Store permet une intégration sans effort avec les applications Web modernes. Il fournit deux adaptateurs pour Next.js, chacun pour le routeur d’applications et le routeur de pages. Ces adaptateurs rationalisent le processus d’intégration d’Edge Store dans les applications Next.js. Edge Store fournit également un adaptateur Express dans les cas où nous avons un backend Express.js et une interface create-react-app ou Vite React. Bien qu’Edge Store héberge des fichiers, il permet également une intégration directe avec des fournisseurs de stockage cloud externes tels que le compartiment AWS S3, Azure Blob Storage et d’autres fournisseurs personnalisés.

  • CDN rapide: Edge Store intègre un réseau de diffusion de contenu pour une diffusion optimale des fichiers depuis n’importe où dans le monde. Son réseau de serveurs distribués améliore les performances et permet également la livraison des fichiers à la meilleure vitesse.

  • Prise en charge des fichiers volumineux: Lorsque vous travaillez avec des fichiers volumineux, Edge Store divise automatiquement le téléchargement de ces fichiers en téléchargements en plusieurs parties, ce qui rend le téléchargement plus rapide et plus stable. Il implémente également une logique de nouvelle tentative en cas de problème de réseau ou de toute autre erreur.

  • Protection des fichiers: Edge Store offre une meilleure sécurité des fichiers avec des validations Edge personnalisées. Il aide à protéger les téléchargements de fichiers et peut également mettre en œuvre des mécanismes de contrôle d’accès appropriés.

  • Génération automatique de vignettes: Le redimensionnement et l’optimisation manuels des images pour différentes tailles d’écran peuvent être fastidieux. Edge Store simplifie votre flux de travail en générant automatiquement des vignettes pour les images. Il fournit une vignette pour une image si elle est plus grande qu’une taille spécifique.

Configuration du projet

Exécutez la commande ci-dessous pour créer une application Next.js :

npx create-next-app

Pour les invites résultantes, ajoutez un nom préféré et préconfigurez le reste de l’application comme indiqué ci-dessous.

Accédez au répertoire créé et exécutez la commande ci-dessous pour installer les dépendances nécessaires :

npm install @edgestore/server @edgestore/react zod

Le edgestore/server est le package de base pour Edge Store. Il fournit la fonctionnalité côté serveur pour gérer les fichiers. Le edgestore/react Le package offre les composants et hooks React nécessaires pour interagir avec la fonctionnalité du serveur Edge Store à partir de votre application côté client. Zod est une bibliothèque de validation de données et de définition de schémas. Edge Store utilise Zod pour améliorer la sécurité des types.

Ensuite, exécutez la commande ci-dessous pour démarrer votre serveur de développement :

npm run dev

Premiers pas avec Edge Store

L’intégration d’Edge Store dans les applications Next.js nécessite des configurations côté serveur et côté client. Cependant, avant de pouvoir continuer, nous devons créer un nouveau projet sur la plateforme Web Edge Store pour accéder au secret et à la clé d’accès requis.

Visitez ce lien pour créer un compte ou connectez-vous si vous possédez déjà un compte Edge Store. Après avoir terminé avec succès le processus d’intégration, cliquez sur « Créez votre premier projet » sur la page résultante pour ajouter un nouveau projet.

Ajoutez un nom de projet pour l’application et cliquez sur le bouton « Créer ».

Ensuite, vous devriez voir une nouvelle page avec un secret et une clé d’accès distincts.

A la racine de votre projet, créez un fichier nommé .envet définissez les clés en tant que variables d’environnement comme indiqué ci-dessous :

EDGE_STORE_ACCESS_KEY=<<Your access key>>
EDGE_STORE_SECRET_KEY=<<Your secret key>>

Maintenant, configurons Edge Store côté serveur de l’application.

Configuration côté serveur

Créé un api/edgestore/[…edgestore]/route.ts fichier dans le src/app dossier et ajoutez-y ce qui suit :

import { initEdgeStore } from "@edgestore/server";
import { createEdgeStoreNextHandler } from "@edgestore/server/adapters/next/app";

const es = initEdgeStore.create();

const edgeStoreRouter = es.router({
  myPublicImages: es.imageBucket(),
});

const handler = createEdgeStoreNextHandler({
  router: edgeStoreRouter,
});

export { handler as GET, handler as POST };
export type EdgeStoreRouter = typeof edgeStoreRouter;

Le fichier contient toutes les configurations côté serveur pour Edge Store. Il crée une route API qui récupère toutes les requêtes sous l’API Edge Store.

En haut du fichier, nous avons importé deux composants essentiels, initEdgeStore et createEdgeStoreNextHandlerà partir de leurs packages respectifs.

initEdgeStore importe à partir du package principal pour Edge Store et sert d’objet principal pour lancer le générateur Edge Store.

createEdgeStoreNextHandler, d’autre part, est une fonction qui importe depuis l’adaptateur Edge Store pour les applications Next.js App Router. Il peut être utilisé pour créer le gestionnaire de route principal de l’API Edge Store.

Ensuite, nous avons lancé le générateur Edge Store et créé le routeur principal pour le compartiment Edge Store.

Vous pouvez considérer les compartiments Edge Store comme une collection de fichiers distincte. Il existe deux types de compartiments de fichiers : imageBucket et fileBucket. Les deux compartiments fonctionnent presque de la même manière, sauf que si fileBucket permet de travailler avec des fichiers de tous types, imageBucket n’accepte que les fichiers avec certains types MIME.

Ensuite, nous avons créé le gestionnaire de route de l’API Edge Store et lui avons transmis le routeur défini. Ensuite, il a été exporté pour les requêtes GET et POST.

Enfin, nous avons généré et exporté le type de routeur qui sera utilisé pour créer le client de type sécurisé pour le frontend.

Avec cela, nous disposons désormais d’une configuration de base côté serveur pour commencer à télécharger des images.

Côté client

Créez un fichier nommé lib/edgestore.ts dans le src/ dossier et ajoutez-y ce qui suit :

'use client';

import { type EdgeStoreRouter } from '../app/api/edgestore/[...edgestore]/route';
import { createEdgeStoreProvider } from '@edgestore/react';

const { EdgeStoreProvider, useEdgeStore } =
  createEdgeStoreProvider<EdgeStoreRouter>();

export { EdgeStoreProvider, useEdgeStore };

Ici, nous avons importé et initié notre fournisseur de contexte.

Enveloppons maintenant notre application avec le fournisseur dans le src/app/layout.tsx fichier comme indiqué ci-dessous :

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { EdgeStoreProvider } from "@/lib/edgestore";

const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
  title: "Create Next App", 
  description: "Generated by create next app",
};
export default function RootLayout({ 
  children,
}: Readonly<{
  children: React.ReactNode,
}>) {
  return (
    <html lang="en">
    <body className={inter.className}>
      <EdgeStoreProvider>{children}</EdgeStoreProvider>
    </body>
  </html>
  );
}

Nous pouvons utiliser le useEdgeStore hook renvoyé par l’initiation du contexte pour accéder au client frontal de type sécurisé et l’utiliser pour télécharger des fichiers. Implémentons cela dans la section suivante.

Téléchargement de fichiers

Ouvrez votre src/app/page.tsx fichier et remplacez le code qu’il contient par ce qui suit :

"use client";
import { ChangeEvent, FormEvent, useState } from "react";
import Image from "next/image";
import { useEdgeStore } from "../lib/edgestore";

export default function Home() {
  const [file, setFile] = useState<File>();
  const [fileRemoteUrl, setFileRemoteUrl] = useState<string>("");
  const { edgestore } = useEdgeStore();
  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    setFile(e.target.files?.[0]);
  };

  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (!file) return;
    try {
      const res = await edgestore.myPublicImages.upload({ file });
      setFileRemoteUrl(res.url);
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <main className="p-24 flex flex-col items-center gap-6">
      <h1 className="text-2xl font-semibold">Edge Store File Upload Demo</h1>
      <form
        onSubmit={handleSubmit}
        className="flex flex-col gap-4 items-center"
      >
        <input type="file" onChange={handleFileChange} />
        <button className="px-4 py-2 bg-blue-800 text-white font-medium rounded-sm">
          Upload File
        </button>
      </form>
      {fileRemoteUrl && (
        <Image
          src={fileRemoteUrl}
          width={250}
          height={250}
          alt="uploaded-file"
        />
      )}
    </main>
  );
}

Dans le code ci-dessus, nous avons défini un formulaire avec un input élément du file taper. Le input l’élément contient un onChange attribut qui déclenche un handleChange fonctionner chaque fois que l’entrée change ; il assigne le fichier sélectionné à une variable d’état appelée file.

Ensuite, nous avons initialisé le useEdgeStore crochet et j’ai attrapé le edgestore client.

Lorsque le bouton de téléchargement de fichier est cliqué et que le onSubmit la fonction est déclenchée, et nous appelons la upload méthode du publicImages seau.

L’appel au handleSubmit La méthode renvoie une réponse qui contient l’URL de l’image générée ainsi que d’autres données, comme indiqué ci-dessous.

Nous enregistrons l’URL dans un fileRemoteUrl état, qui est ensuite rendu à la page. En raison de la façon dont Next.js moderne fonctionne avec des images distantes, nous devons ajouter le domaine de nos images au nextConfig installation.

Ouvrez votre next.config.js fichier au niveau racine de l’application et mettez-le à jour comme indiqué ci-dessous :


const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "files.edgestore.dev",
        port: "",
        pathname: "/**",
      },
    ],
  },
};
export default nextConfig;

Vous pouvez maintenant enregistrer les modifications et tester l’application de démonstration dans le navigateur.

Vous devriez également voir l’image téléchargée dans le tableau de bord de votre projet.

Ajouter une fonctionnalité de progression du téléchargement

Edge Store simplifie également le processus de mise en œuvre d’une indication de la progression d’un téléchargement de fichier. Sur le upload méthode, nous pouvons enregistrer un onProgressChange fonction qui donne accès à une variable qui peut être utilisée à cet effet.

Ouvrez le src/app/pages.tsx fichier et mettez à jour le code comme indiqué ci-dessous :

"use client";

import { ChangeEvent, FormEvent, useState } from "react";
import Image from "next/image";
import { useEdgeStore } from "../lib/edgestore";

export default function Home() {
  const [file, setFile] = useState<File>();
  const [fileRemoteUrl, setFileRemoteUrl] = useState<string>("");
  const [progressVal, setProgressVal] = useState<number>(0);
  const { edgestore } = useEdgeStore();
  
  const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    setFile(e.target.files?.[0]);
  };

  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (!file) return;
    try {
      const res = await edgestore.myPublicImages.upload({
        file,
        onProgressChange: (progress) => {
          setProgressVal(progress);
        },
      });
      setFileRemoteUrl(res.url);
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <main className="p-24 flex flex-col items-center gap-6">
      <h1 className="text-2xl font-semibold">Edge Store File Upload Demo</h1>
      <form
        onSubmit={handleSubmit}
        className="flex flex-col gap-4 items-center"
      >
        <input type="file" onChange={handleFileChange} />

        <div className="h-2 my-4 w-40 overflow-hidden rounded border">
          <div
            className="h-full bg-white transition-all duration-150"
            style={{ width: `${progressVal}%` }}
          ></div>
        </div>
        <button className="px-4 py-2 bg-blue-800 text-white font-medium rounded-sm">
          Upload File
        </button>
      </form>
      {fileRemoteUrl && (
        <Image
          src={fileRemoteUrl}
          width={250}
          height={250}
          alt="uploaded-file"
        />
      )}
    </main>
  );
}

Ici, nous avons défini un onProgressChange fonction pour accéder à la valeur de progression. La valeur est enregistrée dans le progressVal état et utilisé pour afficher un indicateur de progression dynamique.

Vous pouvez maintenant prévisualiser les modifications dans le navigateur.

Composants intégrés d’Edge Store

Au lieu d’implémenter manuellement la logique de sélection de fichiers, Edge Store fournit plusieurs composants personnalisés prédéfinis pour gérer les fichiers, notamment les composants à image unique, multi-images et multi-fichiers.

Le composant Single-image permet la sélection de fichiers et introduit des fonctionnalités supplémentaires telles que la fonctionnalité glisser-déposer, l’aperçu de l’image et la gestion appropriée de l’état. Le composant Multi-image fait la même chose que le composant Single-image mais prend également en charge plusieurs images. Le composant Multi-fichiers permet la sélection de plusieurs fichiers de toutes sortes.

Voyons comment l’un de ces composants peut être utilisé dans notre application de démonstration.

Pour ajouter le composant Multi-fichier à notre application, créez un src/components/MultiFileDropzone.tsx fichier et copiez le code de ce lien à lui, comme indiqué ci-dessous.

Le code repose sur des dépendances supplémentaires, alors exécutez la commande ci-dessous dans votre terminal pour installer les dépendances requises :

npm install react-dropzone lucide-react tailwind-merge

Créons une nouvelle page de démonstration qui utilise le composant Multi-file. Créer un src/app/new/page.tsx fichier et ajoutez-y ce qui suit :

'use client';
import {
  MultiFileDropzone,
  type FileState,
} from '@/components/MultiFileDropzone';
import { useEdgeStore } from '@/lib/edgestore';
import { useState } from 'react';

export default function MultiFileDropzoneUsage() {
  const [fileStates, setFileStates] = useState<FileState[]>([]);
  const { edgestore } = useEdgeStore();
  function updateFileProgress(key: string, progress: FileState['progress']) {
    setFileStates((fileStates) => {
      const newFileStates = structuredClone(fileStates);
      const fileState = newFileStates.find(
        (fileState) => fileState.key === key,
      );
      if (fileState) {
        fileState.progress = progress;
      }
      return newFileStates;
    });
  }
  return (
    <div className='p-10'>
      <MultiFileDropzone
        value={fileStates}
        onChange={(files) => {
          setFileStates(files);
        }}
        onFilesAdded={async (addedFiles) => {
          setFileStates([...fileStates, ...addedFiles]);
          await Promise.all(
            addedFiles.map(async (addedFileState) => {
              try {
                const res = await edgestore.myPublicImages.upload({
                  file: addedFileState.file,
                  onProgressChange: async (progress) => {
                    updateFileProgress(addedFileState.key, progress);
                    if (progress === 100) {
                      
                      
                      await new Promise((resolve) => setTimeout(resolve, 1000));
                      updateFileProgress(addedFileState.key, 'COMPLETE');
                    }
                  },
                });
                console.log(res);
              } catch (err) {
                updateFileProgress(addedFileState.key, 'ERROR');
              }
            }),
          );
        }}
      />
    </div>
  );
}

Enregistrez les modifications et accédez à votre navigateur.

Ajout d’une validation de fichier

Avec Edge Store, nous pouvons définir une validation de base des fichiers sans recourir à des services externes. Nous pouvons définir la taille maximale du fichier et les types MIME acceptés pour chaque compartiment de fichiers, comme indiqué ci-dessous :

const edgeStoreRouter = es.router({
  myPublicIiles: es.fileBucket({
    maxSize: 1024 * 1024 * 10, 
    accept: ["image/jpeg", "image/png"],
  }),
});

Nous pouvons également définir des limites sur les composants personnalisés Edge Store. Un exemple d’extrait de code est présenté ci-dessous :

<SingleImageDropzone
  width={120}
  height={120}
  value={file}
  onChange={(file) => {
    setFile(file);
  }}
  dropzoneOptions={{
    maxSize: 1024 * 1024 * 10,
  }}
/>

Ici, une limite de taille de 10 Mo a été définie sur un seul composant d’image.

Protection des fichiers

Edge Store a introduit le concept de contexte, qui peut être utilisé pour ajouter des métadonnées et définir une logique de contrôle d’accès aux fichiers.

Pour ajouter une protection de fichier, ouvrez le api/edgestore/[…edgestore]/route.ts fichier et mettez à jour le code comme indiqué ci-dessous :

import { initEdgeStore } from "@edgestore/server";
import {
  CreateContextOptions,
  createEdgeStoreNextHandler,
} from "@edgestore/server/adapters/next/app";

type Context = {
  userId: string;
  userRole: "admin" | "user";
};

function createContext({ req }: CreateContextOptions): Context {
  
  return {
    userId: "1234",
    userRole: "admin",
  };
}

const es = initEdgeStore.context<Context>().create();
const edgeStoreRouter = es.router({
  myPublicImages: es.imageBucket(),
  myProtectedFiles: es
    .fileBucket()
    .path(({ ctx }) => [{ owner: ctx.userId }])
    .accessControl({
      OR: [
        {
          userId: { path: "owner" },
        },
        {
          userRole: { eq: "admin" },
        },
      ],
    }),
});

const handler = createEdgeStoreNextHandler({
  router: edgeStoreRouter,
  createContext,
});

export { handler as GET, handler as POST };
export type EdgeStoreRouter = typeof edgeStoreRouter;

Dans l’extrait de code ci-dessus, nous avons créé le Context tapez pour autoriser uniquement l’administrateur et le propriétaire d’un fichier particulier à accéder au fichier. Ensuite, nous avons défini un createContext fonction qui obtient et renvoie les données de session d’authentification d’un utilisateur.

À des fins de démonstration, nous travaillerons avec des données statiques. Il est nécessaire d’ajouter le contexte au générateur Edge Store comme indiqué ci-dessous :

const es = initEdgeStore.context<Context>().create();

Ensuite, nous avons créé un nouveau myProtectedFiles bucket et mis à jour le routeur principal pour ajouter le userId en tant que section propriétaire du chemin d’accès aux fichiers protégés. En savoir plus sur Métadonnées et chemins de fichiers dans la configuration Edge Store.

Nous avons également défini la logique de contrôle d’accès des fichiers protégés pour autoriser l’accès uniquement à l’administrateur et au propriétaire d’un fichier particulier.

Enfin, nous avons ajouté le createContext fonction dans le gestionnaire d’itinéraire.

const handler = createEdgeStoreNextHandler({
  router: edgeStoreRouter,
  createContext,
});

Pour afficher les modifications apportées à la protection des fichiers, ouvrez le src/app/new/page.tsx fichier et remplacez le compartiment défini par le myProtectedFiles nous venons de créer :

<MultiFileDropzone
  value={fileStates}
  onChange={(files) => {
    setFileStates(files);
  }}
  onFilesAdded={async (addedFiles) => {
    setFileStates([...fileStates, ...addedFiles]);
    await Promise.all(
      addedFiles.map(async (addedFileState) => {
        try {
          
          const res = await edgestore.myProtectedFiles.upload({
            file: addedFileState.file,
            onProgressChange: async (progress) => {
              updateFileProgress(addedFileState.key, progress);
              if (progress === 100) {
                
                
                await new Promise((resolve) => setTimeout(resolve, 1000));
                updateFileProgress(addedFileState.key, "COMPLETE");
              }
            },
          });
          console.log(res);
        } catch (err) {
          updateFileProgress(addedFileState.key, "ERROR");
        }
      })
    );
  }}
/>

Enregistrez les modifications et téléchargez un exemple de fichier. Vous devriez voir qu’un nouveau compartiment a également été créé pour les fichiers protégés.

Caractéristiques supplémentaires

Edge Store offre de nombreuses fonctionnalités utiles pour travailler et gérer des fichiers. Par exemple, il utilise une approche conviviale pour télécharger des fichiers volumineux. Il divise automatiquement le téléchargement de fichiers volumineux en téléchargements en plusieurs parties, augmentant ainsi la vitesse et la stabilité du processus.

Si un problème survient pendant le téléchargement (tel qu’un problème de réseau), Edge Store implémente automatiquement une logique de nouvelle tentative qui récupère la partie ayant échoué sans redémarrer l’intégralité du téléchargement.

Conclusion

Edge Store aborde directement les problèmes de gestion et de gestion des fichiers dans les applications Web modernes. Il y parvient en intégrant la sécurité des types, l’abstraction des composants et un ensemble complet de fonctionnalités. Dans cet article, nous avons examiné Edge Store et certains des avantages qu’il offre. Nous avons également créé une application de démonstration Next.js et intégré Edge Store pour le téléchargement de fichiers dans l’application.




Source link
Quitter la version mobile