Mantenere il controllo: una guida a Webpack e reagire, pt. 2
Pubblicato: 2022-03-11Nella prima parte di questo tutorial React-Webpack, abbiamo discusso come configurare i caricatori ed eseguire l'ottimizzazione. Ora entreremo in tecniche più avanzate relative a specifici casi d'uso della configurazione di React/Webpack.
TypeScript e Reagisci con Webpack: Inserisci Babel
Esistono diversi modi in cui puoi utilizzare TypeScript nel tuo progetto React. Sebbene ts-loader
sia una buona opzione, mi piacerebbe concentrarmi su come transpilare TypeScript usando @babel/preset-typescript
perché molte librerie stanno pubblicando plug-in Babel per eseguire l'ottimizzazione del tempo di compilazione. Oltre a elaborare i file TypeScript, ci consentirà di utilizzare i plug-in Babel forniti da varie librerie come styled-components o react-intl.
La prima cosa che dovremo fare è installare le dipendenze TypeScript e Babel:
npm install -D typescript @babel/preset-typescript @types/react @types/react-dom
Genereremo quindi un file di configurazione TypeScript utilizzando il programma da riga di comando tsc
:
./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules
Il comando sopra genererà un tsconfig.json
adatto per scrivere codice per un ambiente browser. L'opzione --isolatedModules
impone alcuni vincoli che assicurano che il codice che scrivi sia compatibile con @babel/plugin-transform-typescript
. Questa opzione è utile affinché il tuo IDE ti avverta quando stai scrivendo codice in un modo che Babel non sarà in grado di trasformare.
Successivamente, aggiorneremo babel.config.js
introducendo un nuovo preset:
@@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",
E abilita l'estensione del file .ts
in webpack.config.js
:
@@ -11,7 +11,7 @@ module.exports = function(_env, argv) { return { devtool: isDevelopment && "cheap-module-source-map", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "dist"), filename: "assets/js/[name].[contenthash:8].js", @@ -20,7 +20,7 @@ module.exports = function(_env, argv) { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", @@ -61,6 +61,9 @@ module.exports = function(_env, argv) { } ] }, + resolve: { + extensions: [".js", ".jsx", ".ts", ".tsx"] + }, plugins: [ isProduction && new MiniCssExtractPlugin({
La configurazione di cui sopra è sufficiente per poter transpilare il nostro codice ma in realtà non lo convalida. Dovremo eseguire il controllo del tipo in un processo parallelo separato utilizzando fork-ts-checker-webpack-plugin
.
Per prima cosa, dobbiamo installarlo:
npm install -D fork-ts-checker-webpack-plugin
Quindi, lo aggiungeremo alla sezione dei plugins
in webpack.config.js
:
@@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -78,6 +79,9 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new ForkTsCheckerWebpackPlugin({ + async: false }) ].filter(Boolean), optimization: {
Specificando async: false
impedirà a Webpack di emettere codice non valido e mostrerà errori di compilazione in una sovrapposizione durante l'esecuzione di un server di sviluppo.
Nota: potresti anche essere interessato alle macro di Babel, che stanno guadagnando terreno.
CSS, migliorato tramite Webpack
Nell'articolo precedente, abbiamo trattato lo stile di base usando css-loader
. Ci sono diversi modi in cui possiamo migliorare questa configurazione.
La configurazione proposta sfrutterà le tecnologie CSS Modules, Sass e PostCSS. Sebbene in qualche modo si completino a vicenda, non è necessario utilizzarli tutti contemporaneamente. La configurazione finale avrà tutti i plug-in di cui sopra abilitati e lasceremo a te il compito di tralasciare qualcosa se sei certo che "non ne avrai bisogno".
Moduli CSS
I moduli CSS affrontano il problema dell'ambito globale nei file CSS generando un nome univoco randomizzato per ciascuna classe CSS. Dal punto di vista di un file JavaScript che consuma un Modulo CSS, un'associazione tra il nome della classe originale e quella randomizzata è rappresentata da un oggetto esportato dal caricatore. Ti consente di trovare e utilizzare le classi specificate in un file CSS in un modo che rende quasi impossibile la collisione accidentale.
Il supporto per i moduli CSS è già incluso in css-loader
. Ora dovremo aggiungere una nuova regola per rendere esplicito quando i moduli CSS sono in uso:
@@ -33,11 +33,25 @@ module.exports = function(_env, argv) { }, { test: /\.css$/, use: [ isProduction ? MiniCssExtractPlugin.loader : "style-loader", "css-loader" ] }, + { + test: /\.module.css$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + modules: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {
Con ciò, qualsiasi file che termina con .module.css
verrà elaborato con i moduli CSS abilitati.
PostCSS
PostCSS è un framework di elaborazione CSS estensibile con una vasta libreria di plugin che puoi utilizzare per estendere la sintassi CSS, eseguire l'ottimizzazione o fornire fallback per i browser meno recenti.
Innanzitutto, installeremo le dipendenze necessarie:
npm install -D postcss-loader postcss-import postcss-preset-env
E aggiorna la nostra configurazione CSS:
@@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {
Configureremo PostCSS utilizzando i seguenti plugin:
-
postcss-import
: consente a PostCSS di elaborare istruzioni@import
-
postcss-preset-env
: applica i polyfill per supportare le moderne funzionalità CSS nella maggior parte dei browser
Crea un file chiamato postcss.config.js
e popolalo con quanto segue:
module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };
Puoi controllare la directory dei plug-in PostCSS per altre estensioni che potresti trovare utili e aggiungerle alla tua configurazione.
Sass/SCSS
Sass è un altro popolare framework di elaborazione CSS. A differenza di PostCSS, Sass viene fornito con "batterie incluse". Immediatamente, Sass offre supporto per regole nidificate, mixin e regole di riscrittura per la compatibilità con le versioni precedenti. Mentre PostCSS mira a preservare la sintassi CSS standard, la sintassi Sass potrebbe divergere dalle specifiche CSS. Nonostante ciò, Sass è una soluzione così onnipresente che utilizzarlo per la creazione di CSS potrebbe essere solo un'opzione più semplice, ma dipende dalle tue esigenze.

Innanzitutto, installeremo le dipendenze necessarie:
npm install -D sass-loader node-sass resolve-url-loader
Quindi, aggiungi un nuovo caricatore alla nostra configurazione di Webpack:
@@ -38,6 +38,25 @@ module.exports = function(_env, argv) { "css-loader" ] }, + { + test: /\.s[ac]ss$/, + use: [ + isProduction ? MiniCssExtractPlugin.loader : "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 2 + } + }, + "resolve-url-loader", + { + loader: "sass-loader", + options: { + sourceMap: true + } + } + ] + }, { test: /\.(png|jpg|gif)$/i, use: {
Abbiamo affrontato preventivamente un paio di problemi con lo snippet di cui sopra:
Abbiamo introdotto
resolve-url-loader
doposass-loader
per far funzionare le importazioni relative dai file@import
ed Sass.Abbiamo specificato l'opzione
importLoaders
percss-loader
per elaborare i file@import
-ed usando i caricatori che la seguono.
Con la configurazione sopra, possiamo iniziare a creare i nostri stili usando Sass/SCSS oltre ai moduli PostCSS e CSS che abbiamo descritto prima. Sebbene tutte queste opzioni possano essere abilitate contemporaneamente, non è necessario utilizzarle tutte all'interno dello stesso progetto, quindi puoi scegliere lo strumento che meglio si adatta alle tue esigenze.
Lavoratori Web
I web worker sono un concetto potente del web moderno. Ti consente di scaricare calcoli costosi lontano dal thread principale. I web worker dovrebbero essere usati con parsimonia e riservati per cose che non possono essere altrimenti ottimizzate da una pianificazione intelligente all'interno di un ciclo di eventi. L'utilizzo di web worker è un buon candidato per l'ottimizzazione di operazioni lunghe e sincrone.
Webpack semplifica l'utilizzo dei web worker con worker-loader
, che raggruppa i file di lavoro nella directory di output e fornisce una classe di lavoro al file del consumatore.
Innanzitutto, dobbiamo installare worker-loader
:
npm install -D worker-loader
Quindi aggiungilo al nostro file di configurazione:
@@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [
Ora, tutto ciò che devi fare per iniziare a utilizzare i web worker è creare un'istanza di una classe importata da un file che termina con .worker.js
che implementa la normale API Worker.
Operatori di servizio
Gli addetti all'assistenza abilitano tecniche di ottimizzazione avanzate e miglioramenti all'esperienza utente. Consentono alla tua app di funzionare offline quando un utente perde la connessione di rete. Inoltre, consentono alla tua app di caricarsi istantaneamente anche dopo aver eseguito il push di un aggiornamento.
Webpack semplifica la configurazione dei service worker per la tua app utilizzando il modulo workbox-webpack-plugin. Per prima cosa, dobbiamo installarlo:
npm install -D workbox-webpack-plugin
Quindi, aggiungeremo il plug-in alla sezione plugins
-in della nostra configurazione del Webpack:
@@ -4,6 +4,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin"); const webpack = require("webpack"); const TerserWebpackPlugin = require("terser-webpack-plugin"); const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const WorkboxPlugin = require("workbox-webpack-plugin"); module.exports = function(_env, argv) { const isProduction = argv.mode === "production"; @@ -75,6 +76,11 @@ module.exports = function(_env, argv) { "process.env.NODE_ENV": JSON.stringify( isProduction ? "production" : "development" ) + }), + new WorkboxPlugin.GenerateSW({ + swDest: "service-worker.js", + clientsClaim: true, + skipWaiting: true }) ].filter(Boolean), optimization: {
La configurazione precedente utilizza le seguenti opzioni:
-
swDest
specifica il nome del file di output per il file di lavoro generato. -
clientsClaim
indica all'operatore del servizio di assumere il controllo della pagina subito dopo la registrazione e di iniziare a servire le risorse memorizzate nella cache invece di attendere il ricaricamento della pagina successiva. -
skipWaiting
rende immediatamente effettivi gli aggiornamenti per il lavoratore del servizio invece di attendere che tutte le istanze attive vengano distrutte.
C'è una buona ragione per cui le due ultime opzioni non sono l'impostazione predefinita. Se abilitato contemporaneamente, è possibile che si verifichino problemi tecnici in situazioni sensibili al tempo, quindi spetta a te prendere una decisione consapevole se mantenere tali opzioni abilitate nella tua configurazione.
Infine, dobbiamo registrare il lavoratore del servizio quando un utente apre la nostra app:
@@ -2,3 +2,9 @@ import React from "react"; import ReactDOM from "react-dom"; ReactDOM.render(<h3>React App</h3>, document.getElementById("root")); + +if ("serviceWorker" in navigator) { + window.addEventListener("load", () => { + navigator.serviceWorker.register("/service-worker.js"); + }); +}
Gli addetti ai servizi sono in grado di fare molto di più che aggiungere funzionalità offline alla nostra app. Se hai bisogno di un maggiore livello di controllo sul comportamento degli operatori di servizio, puoi invece utilizzare il plug-in InjectManifest
. Scrivendo il tuo file di lavoro del servizio, puoi anche abilitare la memorizzazione nella cache per le richieste API e utilizzare altre funzionalità abilitate dai lavoratori del servizio come le notifiche push. Puoi scoprire di più sulle funzionalità di Workbox nella sezione Advanced Recipes della sua documentazione ufficiale.
Advanced React Webpack Config: dare un vantaggio al tuo progetto
Questa seconda parte della nostra serie di tutorial sul Webpack dovrebbe averti fornito le conoscenze necessarie per estendere la configurazione del tuo Webpack oltre i casi d'uso di React più generali. Spero che tu abbia trovato queste informazioni utili e che tu possa estendere con sicurezza la tua configurazione personalizzata per raggiungere gli obiettivi specifici del tuo progetto.
Come sempre, puoi trovare i file di configurazione completi su GitHub e fare riferimento alla documentazione Webpack e alla sezione relativa ai plugin per trovare altre ricette applicabili ai tuoi obiettivi. Grazie per aver letto!