Menține controlul: un ghid pentru Webpack și React, Pt. 2
Publicat: 2022-03-11În prima parte a acestui tutorial React-Webpack, am discutat despre cum să configurați încărcătoarele și să realizați optimizarea. Acum, vom intra în tehnici mai avansate legate de cazuri specifice de utilizare a configurației React/Webpack.
TypeScript și React with Webpack: Introduceți Babel
Există mai multe moduri în care puteți utiliza TypeScript în proiectul dvs. React. Deși ts-loader
este o opțiune bună, aș dori să mă concentrez asupra modului de transpilare TypeScript folosind @babel/preset-typescript
deoarece multe biblioteci publică pluginuri Babel pentru a realiza optimizarea timpului de compilare. Pe lângă procesarea fișierelor TypeScript, ne va permite să folosim pluginuri Babel furnizate de diverse biblioteci, cum ar fi styled-components sau react-intl.
Primul lucru pe care trebuie să-l facem este să instalăm dependențele TypeScript și Babel:
npm install -D typescript @babel/preset-typescript @types/react @types/react-dom
Vom genera apoi un fișier de configurare TypeScript folosind programul de linie de comandă tsc
:
./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules
Comanda de mai sus va genera un tsconfig.json
potrivit pentru scrierea codului pentru un mediu de browser. Opțiunea --isolatedModules
impune anumite constrângeri care se asigură că codul pe care îl scrieți va fi compatibil cu @babel/plugin-transform-typescript
. Este util să aveți această opțiune pentru ca IDE-ul dvs. să vă avertizeze atunci când scrieți cod într-un mod pe care Babel nu îl va putea transforma.
În continuare, vom actualiza babel.config.js
introducând o nouă presetare:
@@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",
Și activați extensia de fișier .ts
în 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({
Configurația de mai sus este suficientă pentru a putea transpila codul nostru, dar nu îl validează de fapt. Va trebui să efectuăm verificarea tipului într-un proces separat, paralel, folosind fork-ts-checker-webpack-plugin
.
În primul rând, trebuie să-l instalăm:
npm install -D fork-ts-checker-webpack-plugin
Apoi, îl vom adăuga la secțiunea de plugins
din 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: {
Specificarea async: false
va împiedica Webpack să emită cod invalid și va afișa erori de compilare într-o suprapunere atunci când rulează un server de dezvoltare.
Notă: s-ar putea să fiți interesat și de macrocomenzile Babel, care câștigă teren.
CSS, îmbunătățit prin Webpack
În articolul anterior, am acoperit stilul de bază folosind css-loader
. Există mai multe moduri în care putem îmbunătăți această configurație.
Configurația propusă va profita de tehnologiile CSS Modules, Sass și PostCSS. Deși se completează unul pe celălalt în anumite moduri, nu trebuie să le folosiți pe toate în același timp. Configurarea finală va avea activate toate pluginurile de mai sus și vă vom lăsa la latitudinea dvs. să omiteți ceva dacă sunteți sigur că „nu veți avea nevoie de el”.
Module CSS
Modulele CSS abordează problema delimitării globale a fișierelor CSS prin generarea unui nume unic, randomizat pentru fiecare clasă CSS. Din punctul de vedere al unui fișier JavaScript care consumă un Modul CSS, o asociere între numele clasei originale și cel randomizat este reprezentată de un obiect exportat de încărcător. Vă permite să găsiți și să utilizați clasele specificate într-un fișier CSS într-un mod care face aproape imposibilă coliziunea accidentală.
Suportul pentru module CSS este deja inclus în css-loader
. Acum va trebui să adăugăm o nouă regulă pentru a face explicit când sunt utilizate modulele CSS:
@@ -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: {
Cu aceasta, orice fișier care se termină în .module.css
va fi procesat cu modulele CSS activate.
PostCSS
PostCSS este un cadru de procesare CSS extensibil, cu o bibliotecă uriașă de plugin-uri pe care le puteți utiliza pentru a extinde sintaxa CSS, pentru a efectua optimizare sau pentru a oferi alternative pentru browsere mai vechi.
Mai întâi, vom instala dependențele necesare:
npm install -D postcss-loader postcss-import postcss-preset-env
Și actualizați configurația noastră CSS:
@@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {
Vom configura PostCSS folosind următoarele plugin-uri:
-
postcss-import
: Permite PostCSS să proceseze declarațiile@import
-
postcss-preset-env
: aplică polyfills pentru a suporta funcțiile CSS moderne în majoritatea browserelor
Creați un fișier numit postcss.config.js
și populați-l cu următoarele:
module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };
Puteți verifica directorul de pluginuri PostCSS pentru alte extensii pe care le puteți găsi utile și să le adăugați la configurația dvs.

Sass/SCSS
Sass este un alt cadru de procesare CSS popular. Spre deosebire de PostCSS, Sass vine cu „baterii incluse”. Ieșit din cutie, Sass oferă suport pentru reguli imbricate, mixuri și reguli de rescriere pentru compatibilitate inversă. În timp ce PostCSS urmărește să păstreze sintaxa CSS standard, sintaxa Sass poate diverge de specificațiile CSS. În ciuda acestui fapt, Sass este o soluție atât de omniprezentă încât utilizarea acesteia pentru crearea CSS poate fi doar o opțiune mai ușoară, dar una care depinde de cerințele dvs.
Mai întâi, vom instala dependențele necesare:
npm install -D sass-loader node-sass resolve-url-loader
Apoi, adăugați un nou încărcător la configurația 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: {
Am abordat preventiv câteva probleme cu fragmentul de mai sus:
Am introdus
resolve-url-loader
dupăsass-loader
pentru a face ca importurile relative să funcționeze din fișierele@import
ed Sass.Am specificat opțiunea
importLoaders
pentrucss-loader
pentru a procesa fișierele@import
-ed folosind încărcătorul care îl urmează.
Cu configurația de mai sus, putem începe să ne cream stilurile folosind Sass/SCSS în plus față de modulele PostCSS și CSS pe care le-am descris anterior. Deși toate aceste opțiuni pot fi activate simultan, nu trebuie să le utilizați pe toate în cadrul aceluiași proiect, așa că puteți alege instrumentul care se potrivește cel mai bine cerințelor dvs.
Lucrători web
Lucrătorii web este un concept puternic al web-ului modern. Vă permite să descărcați calcule costisitoare departe de firul principal. Lucrătorii web ar trebui să fie utilizați cu moderație și rezervați pentru lucruri care nu pot fi optimizate altfel prin programarea inteligentă în cadrul unei bucle de evenimente. Utilizarea lucrătorilor web este un bun candidat pentru optimizarea operațiunilor lungi și sincrone.
Webpack facilitează utilizarea lucrătorilor web cu worker-loader
, care grupează fișierele de lucru în directorul de ieșire și oferă o clasă de lucru pentru fișierul de consum.
Mai întâi, trebuie să instalăm worker-loader
:
npm install -D worker-loader
Apoi adăugați-l în fișierul nostru de configurare:
@@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [
Acum, tot ce trebuie să faceți pentru a începe să utilizați lucrătorii web este să instanțiați o clasă importată dintr-un fișier care se termină în .worker.js
care implementează API-ul Worker obișnuit.
Lucrători de servicii
Lucrătorii de servicii permit tehnici avansate de optimizare și îmbunătățiri ale experienței utilizatorului. Ei vă permit aplicației să funcționeze offline atunci când un utilizator își pierde conexiunea la rețea. De asemenea, vă permit aplicației să se încarce instantaneu chiar și după ce ați apăsat o actualizare.
Webpack facilitează configurarea lucrătorilor de service pentru aplicația dvs. folosind modulul workbox-webpack-plugin. În primul rând, trebuie să-l instalăm:
npm install -D workbox-webpack-plugin
Apoi, vom adăuga pluginul la secțiunea de plugins
a configurației noastre 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: {
Configurația de mai sus folosește următoarele opțiuni:
-
swDest
specifică numele fișierului de ieșire pentru fișierul de lucru generat. -
clientsClaim
îi cere lucrătorului de servicii să preia controlul asupra paginii imediat după înregistrare și să înceapă să servească resursele din cache în loc să aștepte reîncărcarea paginii următoare. -
skipWaiting
face ca actualizările pentru lucrătorul de serviciu să intre în vigoare imediat, în loc să aștepte ca toate instanțele active să fie distruse.
Există un motiv bun pentru care ultimele două opțiuni nu sunt implicite. Când este activat simultan, există posibilitatea ca erorile să apară în situații sensibile la timp, așa că depinde de dvs. să luați o decizie conștientă dacă să păstrați aceste opțiuni activate în configurația dvs.
În cele din urmă, trebuie să înregistrăm lucrătorul de service atunci când un utilizator deschide aplicația noastră:
@@ -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"); + }); +}
Lucrătorii de servicii sunt capabili de mult mai mult decât să adauge capabilități offline la aplicația noastră. Dacă aveți nevoie de un grad mai mare de control asupra comportamentului lucrătorilor de servicii, atunci puteți utiliza pluginul InjectManifest
în schimb. Prin scrierea propriului fișier de serviciu, puteți, de asemenea, să activați memorarea în cache pentru solicitările API și să utilizați alte funcții activate de lucrătorii de servicii, cum ar fi notificările push. Puteți afla mai multe despre capabilitățile Workbox în secțiunea Rețete avansate din documentația sa oficială.
Advanced React Webpack Config: oferiți-vă proiectului un avantaj
Această a doua parte a seriei noastre de tutoriale Webpack ar trebui să vă ofere cunoștințele necesare pentru a vă extinde configurația Webpack peste cele mai generale cazuri de utilizare React. Sper că ați găsit aceste informații utile și că vă puteți extinde cu încredere configurația personalizată pentru a atinge obiectivele specifice proiectului dumneavoastră.
Ca întotdeauna, puteți găsi fișierele complete de configurare pe GitHub și puteți consulta documentația Webpack și secțiunea de pluginuri pentru a găsi mai multe rețete aplicabile obiectivelor dvs. Multumesc pentru lectura!