Utilizzo di bundler di moduli con Firebase

I bundler dei moduli JavaScript possono fare molte cose, ma una delle loro funzionalità più utili è la possibilità di aggiungere e utilizzare librerie esterne nella base di codice. I pacchetti di moduli leggono i percorsi di importazione nel codice e combinano (bundle) il codice specifico dell'applicazione con il codice della libreria importata.

A partire dalla versione 9 e versioni successive, l'API modulare JavaScript di Firebase è ottimizzata per funzionare con le funzionalità di ottimizzazione dei bundler dei moduli al fine di ridurre la quantità di codice Firebase incluso nella build finale.

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.
 */

Questa procedura di eliminazione del codice inutilizzato da una libreria è nota come tree shaking. La rimozione manuale di questo codice sarebbe estremamente dispendiosa in termini di tempo e soggetta a errori, ma i bundler dei moduli possono automatizzare questa rimozione.

Nell'ecosistema JavaScript sono disponibili molti aggregatori di moduli di alta qualità. Questa guida è incentrata sull'utilizzo di Firebase con webpack, Rollup e esbuild.

Inizia

Per utilizzare questa guida, devi avere installato npm nel tuo ambiente di sviluppo. NPM viene utilizzato per installare e gestire le dipendenze (librerie). Per installare npm, installa Node.js, che include automaticamente npm.

La maggior parte degli sviluppatori ha configurato correttamente il proprio ambiente dopo aver installato Node.js. Tuttavia, esistono problemi comuni che molti sviluppatori riscontrano durante la configurazione del proprio ambiente. Se riscontri errori, assicurati che il tuo ambiente disponga dell'interfaccia a riga di comando npm e che siano configurate le autorizzazioni appropriate in modo da non dover installare i pacchetti come amministratore con il comando sudo.

package.json e installazione di Firebase

Una volta installato npm, dovrai creare un file package.json nella directory principale del tuo progetto locale. Genera questo file con il seguente comando npm:

npm init

Verrà visualizzata una procedura guidata per fornirti le informazioni necessarie. Una volta creato, il file sarà simile al seguente:

{
  "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": {

  }
}

Questo file è responsabile di molte cose diverse. Si tratta di un file importante con cui familiarizzare se vuoi saperne di più sul bundling dei moduli e sulla creazione di codice JavaScript in generale. L'elemento importante per questa guida è l'oggetto"dependencies". Questo oggetto conterrà una coppia chiave-valore della libreria che hai installato e la versione in uso.

L'aggiunta delle dipendenze viene eseguita tramite il comando npm install o npm i.

npm i firebase

Quando esegui npm i firebase, la procedura di installazione si aggiorna package.json per elencare Firebase come dipendenza:

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

La chiave è il nome della libreria e il valore è la versione da utilizzare. Il valore della versione è flessibile e può accettare una serie di valori. Questo è noto come versionamento semantico o semver. Per scoprire di più su semver, consulta la guida di npm sul controllo delle versioni semantiche.

Cartelle di origine e di compilazione

Il codice che scrivi viene letto ed elaborato da un bundler di moduli e poi viene visualizzato come un nuovo file o un insieme di file. È importante separare questi due tipi di file. Il codice letto ed elaborato dai pacchetti di moduli è noto come codice "sorgente". I file generati sono noti come codice compilato o "dist" (distribuzione).

Una configurazione comune nelle basi di codice è memorizzare il codice sorgente in una cartella denominata src e il codice compilato in una cartella denominata dist.

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


- dist
 |_ bundle.js

Nella struttura del file di esempio riportata sopra, tieni presente che index.js importa sia animations.js sia datalist.js. Quando un aggregatore di moduli elabora il codice sorgente, genera il file bundle.js nella cartella dist. bundle.js è una combinazione dei file nella cartella src e di eventuali librerie importate.

Se utilizzi sistemi di controllo del codice sorgente come Git, è comune ignorare la dist cartella quando memorizzi questo codice nel repository principale.

Punti di contatto

I pacchetti di moduli hanno tutti un concetto di punto di contatto. Puoi pensare alla tua applicazione come a un albero di file. Un file importa il codice da un altro e così via. Ciò significa che un file sarà la radice dell'albero. Questo file è conosciuto come punto di ingresso.

Esaminiamo di nuovo l'esempio di struttura dei file precedente.

- 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);
});

Il file src/index.js è considerato il punto di ingresso perché avvia le importazioni di tutto il codice necessario per l'applicazione. Questo file di punto di contatto viene utilizzato dai pacchetti di moduli per avviare il processo di aggregazione.

Utilizzo di Firebase con webpack

Non è necessaria alcuna configurazione specifica per le app Firebase e webpack. Questa sezione tratta una configurazione generale di webpack.

Il primo passaggio consiste nell'installare webpack da npm come dipendenza di sviluppo.

npm i webpack webpack-cli -D

Crea un file nella directory principale del progetto locale denominato webpack.config.js e aggiungi il seguente codice.

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',
};

Assicurati inoltre di aver installato Firebase come dipendenza.

npm i firebase

Quindi, inizializza Firebase nella base di codice. Il seguente codice importa e inizializza Firebase in un file di punto di contatto e utilizza Firestore Lite per caricare un documento "città".

// 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(),
  };
}

Il passaggio successivo consiste nell'aggiungere uno script npm per eseguire la compilazione di webpack. Apri il file package.json e aggiungi la seguente coppia chiave-valore all'oggetto "scripts".

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

Per eseguire webpack e generare la cartella di compilazione, esegui il seguente comando.

npm run build

Infine, controlla la cartella di compilazione dist. Deve contenere un file denominato bundle.js che contiene il codice dell'applicazione e delle dipendenze in bundle.

Per ulteriori informazioni sull'ottimizzazione della compilazione webpack per la produzione, consulta la documentazione ufficiale sull'impostazione di configurazione "mode".

Utilizzo di Firebase con Rollup

Non è necessaria alcuna configurazione specifica per le app Firebase e Rollup. Questa sezione illustra una configurazione generale di aggregazione.

Il primo passaggio consiste nell'installare Rollup e un plug-in utilizzato per mappare le importazioni alle dipendenze installate con npm.

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

Crea un file nella directory principale del progetto locale denominato rollup.config.js e aggiungi il seguente codice.

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()]
};

Quindi, inizializza Firebase nella base di codice. Il seguente codice importa e inizializza Firebase in un file di punto di contatto e utilizza Firestore Lite per caricare un documento "città".

// 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(),
  };
}

Il passaggio successivo consiste nell'aggiungere uno script npm per eseguire la compilazione del rollup. Apri il file package.json e aggiungi la seguente coppia chiave-valore all'oggetto "scripts".

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

Per eseguire il raggruppamento e generare la cartella di compilazione, esegui il seguente comando.

npm run build

Infine, controlla la cartella di compilazione dist. Deve contenere un file denominato bundle.js che contiene il codice dell'applicazione e delle dipendenze in bundle.

Per saperne di più sull'ottimizzazione della compilazione di aggregazione per la produzione, consulta la documentazione ufficiale sui plug-in per le build di produzione.

Utilizzare Firebase con esbuild

Non è necessaria alcuna configurazione specifica per le app Firebase ed esbuild. Questa sezione illustra una configurazione generale di esbuild.

Il primo passaggio consiste nell'installare esbuild come dipendenza di sviluppo.

npm i esbuild -D

Crea un file nella directory principale del progetto locale denominato esbuild.config.js e aggiungi il seguente codice.

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))

Quindi, inizializza Firebase nella base di codice. Il seguente codice importa e inizializza Firebase in un file di punto di contatto e utilizza Firestore Lite per caricare un documento "città".

// 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(),
  };
}

Il passaggio successivo consiste nell'aggiungere uno script npm per eseguire esbuild. Apri il file package.json e aggiungi la seguente coppia chiave/valore all'oggetto "scripts".

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

Infine, controlla la cartella di compilazione dist. Deve contenere un file denominato bundle.js che contiene il codice dell'applicazione e delle dipendenze in bundle.

Per ulteriori informazioni sull'ottimizzazione di esbuild per la produzione, consulta la documentazione ufficiale sulla minificazione e su altre ottimizzazioni.