Utiliser des outils de regroupement de modules avec Firebase

Les outils de regroupement de modules JavaScript peuvent effectuer de nombreuses tâches, mais l'une de leurs fonctionnalités les plus utiles est la possibilité d'ajouter et d'utiliser des bibliothèques externes dans votre base de code. Les outils de regroupement de modules lisent les chemins d'importation dans votre code et combinent (regroupent) votre code spécifique à l'application avec le code de la bibliothèque importée.

À partir de la version 9, l'API modulaire JavaScript Firebase est optimisée pour fonctionner avec les fonctionnalités d'optimisation des outils de regroupement de modules afin de réduire la quantité de code Firebase incluse dans votre build final.

import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged, getRedirectResult } from 'firebase/auth';

const firebaseApp = initializeApp({ /* config */ });
const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => { /* check status */ });

/**
 * getRedirectResult is unused and should not be included in the code base.
 * In addition, there are many other functions within firebase/auth that are
 * not imported and therefore should not be included as well.
 */

Ce processus d'élimination du code inutilisé d'une bibliothèque est appelé "tree shaking". Supprimer manuellement ce code serait extrêmement chronophage et source d'erreurs, mais les outils de regroupement de modules peuvent automatiser cette suppression.

L'écosystème JavaScript compte de nombreux outils de regroupement de modules de haute qualité. Ce guide explique comment utiliser Firebase avec webpack, Rollup et esbuild.

Premiers pas

Pour suivre ce guide, vous devez avoir installé npm dans votre environnement de développement. npm permet d'installer et de gérer les dépendances (bibliothèques). Pour installer npm, installez Node.js, qui inclut npm automatiquement.

La plupart des développeurs sont correctement configurés une fois qu'ils ont installé Node.js. Toutefois, de nombreux développeurs rencontrent des problèmes courants lorsqu'ils configurent leur environnement. Si vous rencontrez des erreurs, assurez-vous que votre environnement dispose de la CLI npm et que vous avez configuré les autorisations appropriées pour que vous n'ayez pas à installer des paquets en tant qu'administrateur avec la commande sudo.

package.json et installation de Firebase

Une fois npm installé, vous devez créer un fichier package.json à la racine de votre projet local. Générez ce fichier à l'aide de la commande npm suivante:

npm init

Vous serez alors guidé par un assistant pour fournir les informations requises. Une fois le fichier créé, il se présente comme suit:

{
  "name": "your-package-name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {

  }
}

Ce fichier est responsable de nombreuses tâches différentes. Il s'agit d'un fichier important à connaître si vous souhaitez en savoir plus sur le regroupement de modules et la création de code JavaScript en général. L'élément important de ce guide est l'objet "dependencies". Cet objet contiendra une paire clé-valeur de la bibliothèque que vous avez installée et de la version qu'elle utilise.

Pour ajouter des dépendances, utilisez la commande npm install ou npm i.

npm i firebase

Lorsque vous exécutez npm i firebase, le processus d'installation met à jour package.json pour lister Firebase comme dépendance:

  "dependencies": {
    "firebase": "^9.0.0"
  },

La clé correspond au nom de la bibliothèque, et la valeur à la version à utiliser. La valeur de la version est flexible et peut accepter une plage de valeurs. Cette pratique est appelée gestion de versions sémantique ou semver. Pour en savoir plus sur le semver, consultez le guide de npm sur la gestion des versions sémantiques.

Dossiers source et de compilation

Le code que vous écrivez est lu et traité par un outil de regroupement de modules, puis généré en tant que nouveau fichier ou ensemble de fichiers. Il est important de séparer ces deux types de fichiers. Le code que les outils de regroupement de modules lisent et traitent est appelé code "source". Les fichiers qu'ils génèrent sont appelés code compilé ou "dist" (distribution).

Une configuration courante dans les bases de code consiste à stocker le code source dans un dossier appelé src et le code compilé dans un dossier appelé dist.

- src
 |_ index.js
 |_ animations.js
 |_ datalist.js


- dist
 |_ bundle.js

Dans l'exemple de structure de fichier ci-dessus, supposons que index.js importe à la fois animations.js et datalist.js. Lorsqu'un outil de regroupement de modules traite le code source, il génère le fichier bundle.js dans le dossier dist. bundle.js est une combinaison des fichiers du dossier src et de toutes les bibliothèques importées.

Si vous utilisez des systèmes de contrôle des versions tels que Git, il est courant d'ignorer le dossier dist lorsque vous stockez ce code dans le dépôt principal.

Points d'entrée

Les outils de regroupement de modules ont tous un concept de point d'entrée. Vous pouvez considérer votre application comme une arborescence de fichiers. Un fichier importe le code d'un autre, et ainsi de suite. Cela signifie qu'un fichier sera la racine de l'arborescence. Ce fichier est appelé point d'entrée.

Reprenons l'exemple de structure de fichiers précédent.

- src
 |_ index.js
 |_ animations.js
 |_ datalist.js


- dist
 |_ bundle.js
// src/index.js
import { animate } from './animations';
import { createList } from './datalist';

// This is not real code, but for example purposes only
const theList = createList('users/123/tasks');
theList.addEventListener('loaded', event => {
  animate(theList);
});

Le fichier src/index.js est considéré comme le point d'entrée, car il commence les importations de tout le code nécessaire à l'application. Ce fichier de point d'entrée est utilisé par les outils de regroupement de modules pour lancer le processus de regroupement.

Utiliser Firebase avec webpack

Aucune configuration spécifique n'est requise pour les applications Firebase et webpack. Cette section décrit une configuration webpack générale.

La première étape consiste à installer webpack à partir de npm en tant que dépendance de développement.

npm i webpack webpack-cli -D

Créez un fichier nommé webpack.config.js à la racine de votre projet local et ajoutez le code suivant.

const path = require('path');

module.exports = {
  // The entry point file described above
  entry: './src/index.js',
  // The location of the build folder described above
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  // Optional and for development only. This provides the ability to
  // map the built code back to the original source format when debugging.
  devtool: 'eval-source-map',
};

Assurez-vous ensuite que Firebase est installé en tant que dépendance.

npm i firebase

Ensuite, initialisez Firebase dans votre base de code. Le code suivant importe et initialise Firebase dans un fichier de point d'entrée, et utilise Firestore Lite pour charger un document "ville".

// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';

const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);

async function loadCity(name) {
  const cityDoc = doc(db, `cities/${name}`);
  const snapshot = await getDoc(cityDoc);
  return {
    id: snapshot.id,
    ...snapshot.data(),
  };
}

L'étape suivante consiste à ajouter un script npm pour exécuter la compilation webpack. Ouvrez le fichier package.json et ajoutez la paire clé-valeur suivante à l'objet "scripts".

  "scripts": {
    "build": "webpack --mode=development"
  },

Pour exécuter webpack et générer le dossier de compilation, exécutez la commande suivante.

npm run build

Enfin, vérifiez le dossier de compilation dist. Il doit contenir un fichier nommé bundle.js qui contient votre application groupée et le code de dépendance.

Pour en savoir plus sur l'optimisation de votre build webpack pour la production, consultez la documentation officielle sur le paramètre de configuration "mode".

Utiliser Firebase avec Rollup

Aucune configuration spécifique n'est requise pour les applications Firebase et le rattachement. Cette section présente une configuration générale de la récapitulation.

La première étape consiste à installer Rollup et un plug-in permettant de mapper les importations aux dépendances installées avec npm.

npm i rollup @rollup/plugin-node-resolve -D

Créez un fichier nommé rollup.config.js à la racine de votre projet local et ajoutez le code suivant.

import { nodeResolve } from '@rollup/plugin-node-resolve';

export default {
  // the entry point file described above
  input: 'src/index.js',
  // the output for the build folder described above
  output: {
    file: 'dist/bundle.js',
    // Optional and for development only. This provides the ability to
    // map the built code back to the original source format when debugging.
    sourcemap: 'inline',
    // Configure Rollup to convert your module code to a scoped function
    // that "immediate invokes". See the Rollup documentation for more
    // information: https://rollupjs.org/guide/en/#outputformat
    format: 'iife'
  },
  // Add the plugin to map import paths to dependencies
  // installed with npm
  plugins: [nodeResolve()]
};

Ensuite, initialisez Firebase dans votre base de code. Le code suivant importe et initialise Firebase dans un fichier de point d'entrée, et utilise Firestore Lite pour charger un document "ville".

// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';

const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);

async function loadCity(name) {
  const cityDoc = doc(db, `cities/${name}`);
  const snapshot = await getDoc(cityDoc);
  return {
    id: snapshot.id,
    ...snapshot.data(),
  };
}

L'étape suivante consiste à ajouter un script npm pour exécuter le build de compilation. Ouvrez le fichier package.json et ajoutez la paire clé-valeur suivante à l'objet "scripts".

  "scripts": {
    "build": "rollup -c rollup.config.js"
  },

Pour exécuter le rattachement et générer le dossier de compilation, exécutez la commande suivante.

npm run build

Enfin, vérifiez le dossier de compilation dist. Il doit contenir un fichier nommé bundle.js qui contient votre application groupée et le code de dépendance.

Pour en savoir plus sur l'optimisation de votre build Rollup pour la production, consultez la documentation officielle sur les plug-ins pour les builds de production.

Utiliser Firebase avec esbuild

Aucune configuration spécifique n'est requise pour les applications Firebase et esbuild. Cette section couvre une configuration générale d'esbuild.

La première étape consiste à installer esbuild en tant que dépendance de développement.

npm i esbuild -D

Créez un fichier nommé esbuild.config.js à la racine de votre projet local et ajoutez le code suivant.

require('esbuild').build({
  // the entry point file described above
  entryPoints: ['src/index.js'],
  // the build folder location described above
  outfile: 'dist/bundle.js',
  bundle: true,
  // Replace with the browser versions you need to target
  target: ['chrome60', 'firefox60', 'safari11', 'edge20'],
  // Optional and for development only. This provides the ability to
  // map the built code back to the original source format when debugging.
  sourcemap: 'inline',
}).catch(() => process.exit(1))

Ensuite, initialisez Firebase dans votre base de code. Le code suivant importe et initialise Firebase dans un fichier de point d'entrée, et utilise Firestore Lite pour charger un document "ville".

// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';

const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);

async function loadCity(name) {
  const cityDoc = doc(db, `cities/${name}`);
  const snapshot = await getDoc(cityDoc);
  return {
    id: snapshot.id,
    ...snapshot.data(),
  };
}

L'étape suivante consiste à ajouter un script npm pour exécuter esbuild. Ouvrez le fichier package.json et ajoutez la paire clé-valeur suivante à l'objet "scripts".

  "scripts": {
    "build": "node ./esbuild.config.js"
  },

Enfin, vérifiez le dossier de compilation dist. Il doit contenir un fichier nommé bundle.js qui contient votre application groupée et le code de dépendance.

Pour en savoir plus sur l'optimisation d'esbuild pour la production, consultez la documentation officielle sur la minification et d'autres optimisations.