Mantenha o controle: um guia para Webpack e React, Pt. 2
Publicados: 2022-03-11Na primeira parte deste tutorial do React-Webpack, discutimos como configurar carregadores e realizar a otimização. Agora, entraremos em técnicas mais avançadas relacionadas a casos de uso específicos de configuração do React/Webpack.
TypeScript e React com Webpack: Digite Babel
Existem várias maneiras de usar o TypeScript em seu projeto React. Embora ts-loader
seja uma boa opção, gostaria de me concentrar em como transpilar o TypeScript usando @babel/preset-typescript
porque muitas bibliotecas estão publicando plugins Babel para otimizar o tempo de compilação. Além de processar arquivos TypeScript, ele nos permitirá usar plugins Babel fornecidos por várias bibliotecas, como styled-components ou react-intl.
A primeira coisa que precisamos fazer é instalar as dependências do TypeScript e do Babel:
npm install -D typescript @babel/preset-typescript @types/react @types/react-dom
Em seguida, geraremos um arquivo de configuração TypeScript usando o programa de linha de comando tsc
:
./node_modules/.bin/tsc -init --lib dom --jsx react --isolatedModules
O comando acima irá gerar um tsconfig.json
adequado para escrever código para um ambiente de navegador. A opção --isolatedModules
impõe algumas restrições que garantem que o código que você escreve seja compatível com @babel/plugin-transform-typescript
. Esta opção é útil para que seu IDE avise quando você estiver escrevendo código de uma forma que o Babel não poderá transformar.
Em seguida, vamos atualizar o babel.config.js
introduzindo uma nova predefinição:
@@ -6,7 +6,8 @@ module.exports = { modules: false } ], - "@babel/preset-react" + "@babel/preset-react", + "@babel/preset-typescript" ], plugins: [ "@babel/plugin-transform-runtime",
E habilite a extensão de arquivo .ts
em 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({
A configuração acima é suficiente para poder transpilar nosso código, mas na verdade não o valida. Precisaremos realizar a verificação de tipo em um processo paralelo separado usando fork-ts-checker-webpack-plugin
.
Primeiro, precisamos instalá-lo:
npm install -D fork-ts-checker-webpack-plugin
Em seguida, vamos adicioná-lo à seção de plugins
em 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: {
Especificar async: false
impedirá que o Webpack emita código inválido e mostre erros de compilação em uma sobreposição ao executar um servidor de desenvolvimento.
Nota: Você também pode estar interessado em macros Babel, que estão ganhando força.
CSS, Aprimorado via Webpack
No artigo anterior, abordamos o estilo básico usando css-loader
. Existem várias maneiras de melhorar essa configuração.
A configuração proposta aproveitará as tecnologias CSS Modules, Sass e PostCSS. Embora eles se complementem de algumas maneiras, você não precisa usar todos eles ao mesmo tempo. A configuração final terá todos os plugins acima ativados, e deixaremos para você deixar algo de fora se tiver certeza de que “não vai precisar”.
Módulos CSS
Os módulos CSS abordam o problema de escopo global em arquivos CSS gerando um nome único e aleatório para cada classe CSS. Do ponto de vista de um arquivo JavaScript consumindo um Módulo CSS, uma associação entre o nome da classe original e a aleatória é representada por um objeto exportado pelo loader. Ele permite que você encontre e use classes especificadas em um arquivo CSS de uma forma que torna a colisão acidental quase impossível.
O suporte a Módulos CSS já está incluído no css-loader
. Agora vamos precisar adicionar uma nova regra para deixar explícito quando os módulos CSS estão em 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: {
Com isso, qualquer arquivo que termine em .module.css
será processado com os Módulos CSS habilitados.
Pós CSS
PostCSS é uma estrutura de processamento CSS extensível com uma enorme biblioteca de plugins que você pode usar para estender a sintaxe CSS, realizar otimização ou fornecer fallbacks para navegadores mais antigos.
Primeiro, vamos instalar as dependências necessárias:
npm install -D postcss-loader postcss-import postcss-preset-env
E atualize nossa configuração CSS:
@@ -47,9 +47,11 @@ module.exports = function(_env, argv) { { loader: "css-loader", options: { - modules: true + modules: true, + importLoaders: 1 } - } + }, + "postcss-loader" ] }, {
Vamos configurar o PostCSS usando os seguintes plugins:
-
postcss-import
: permite que PostCSS processe instruções@import
-
postcss-preset-env
: Aplica polyfills para oferecer suporte a recursos CSS modernos na maioria dos navegadores
Crie um arquivo chamado postcss.config.js
e preencha-o com o seguinte:
module.exports = { plugins: { "postcss-import": {}, "postcss-preset-env": {} } };
Você pode verificar o diretório de plugins PostCSS para outras extensões que podem ser úteis e adicioná-las ao seu config.

Sass/SCSS
Sass é outro framework de processamento CSS popular. Ao contrário do PostCSS, o Sass vem com “baterias incluídas”. Pronto para uso, o Sass oferece suporte para regras aninhadas, mixins e regras de reescrita para compatibilidade com versões anteriores. Enquanto o PostCSS visa preservar a sintaxe CSS padrão, a sintaxe Sass pode divergir da especificação CSS. Apesar disso, o Sass é uma solução tão onipresente que usá-lo para criar CSS pode ser uma opção mais fácil, mas que depende de seus requisitos.
Primeiro, vamos instalar as dependências necessárias:
npm install -D sass-loader node-sass resolve-url-loader
Em seguida, adicione um novo carregador à nossa configuração do 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: {
Abordamos preventivamente alguns problemas com o snippet acima:
Introduzimos
resolve-url-loader
apóssass-loader
para fazer as importações relativas funcionarem dos arquivos@import
ed Sass.Especificamos a opção
importLoaders
paracss-loader
para processar arquivos@import
-ed usando os carregadores que o seguem.
Com a configuração acima, podemos começar a criar nossos estilos usando Sass/SCSS além dos módulos PostCSS e CSS que descrevemos anteriormente. Embora todas essas opções possam ser habilitadas simultaneamente, você não precisa usar todas elas dentro do mesmo projeto, então você pode escolher a ferramenta que melhor se adapta às suas necessidades.
Trabalhadores da Web
Web workers é um conceito poderoso da web moderna. Ele permite que você descarregue cálculos caros do thread principal. Os web workers devem ser usados com moderação e reservados para coisas que não podem ser otimizadas por agendamento inteligente dentro de um loop de eventos. O uso de web workers é um bom candidato para otimizar operações longas e síncronas.
O Webpack facilita o uso de web workers com worker-loader
, que agrupa arquivos de trabalho no diretório de saída e fornece uma classe de trabalho para o arquivo do consumidor.
Primeiro, precisamos instalar worker-loader
:
npm install -D worker-loader
Em seguida, adicione-o ao nosso arquivo de configuração:
@@ -31,6 +31,10 @@ module.exports = function(_env, argv) { } } }, + { + test: /\.worker\.js$/, + loader: "worker-loader" + }, { test: /\.css$/, use: [
Agora, tudo o que você precisa fazer para começar a usar web workers é instanciar uma classe importada de um arquivo que termina em .worker.js
que implementa a API Worker comum.
Trabalhadores de serviço
Os service workers habilitam técnicas avançadas de otimização e melhorias na experiência do usuário. Eles permitem que seu aplicativo funcione offline quando um usuário perde a conexão de rede. Eles também permitem que seu aplicativo seja carregado instantaneamente, mesmo depois de enviar uma atualização.
O Webpack facilita a configuração de service workers para seu aplicativo usando o módulo workbox-webpack-plugin. Primeiro, precisamos instalá-lo:
npm install -D workbox-webpack-plugin
Em seguida, adicionaremos o plug-in à seção de plug- plugins
da configuração do nosso 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: {
A configuração acima usa as seguintes opções:
-
swDest
especifica o nome do arquivo de saída para o arquivo de trabalho gerado. -
clientsClaim
instrui o service worker a assumir o controle da página imediatamente após o registro e começar a servir recursos em cache em vez de esperar pelo recarregamento da próxima página. -
skipWaiting
faz com que as atualizações no service worker entrem em vigor imediatamente, em vez de esperar que todas as instâncias ativas sejam destruídas.
Há uma boa razão pela qual as duas últimas opções não são o padrão. Quando ativado simultaneamente, existe a possibilidade de ocorrerem falhas em situações sensíveis ao tempo, portanto, cabe a você tomar uma decisão consciente sobre manter essas opções ativadas em sua configuração.
Por fim, precisamos registrar o service worker quando um usuário abre nosso aplicativo:
@@ -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"); + }); +}
Os service workers são capazes de muito mais do que adicionar recursos offline ao nosso aplicativo. Se você precisar de um maior grau de controle sobre o comportamento do service worker, poderá usar o plug-in InjectManifest
. Ao escrever seu próprio arquivo de service worker, você também pode habilitar o armazenamento em cache para solicitações de API e usar outros recursos habilitados por service workers, como notificações por push. Você pode descobrir mais sobre os recursos do Workbox na seção Receitas Avançadas de sua documentação oficial.
Configuração avançada do React Webpack: dando uma vantagem ao seu projeto
Esta segunda parte de nossa série de tutoriais do Webpack deve tê-lo armado com o conhecimento necessário para estender sua configuração do Webpack além dos casos de uso mais gerais do React. Espero que você tenha achado essas informações úteis e que possa estender com confiança sua configuração personalizada para atingir as metas específicas do seu projeto.
Como sempre, você pode encontrar os arquivos de configuração completos no GitHub e consultar a documentação do Webpack e sua seção de plugins para encontrar mais receitas aplicáveis aos seus objetivos. Obrigado por ler!