Configurações versáteis do Webpack para seu aplicativo React

Adewale Abati ? Blocked Unblock Seguir Seguindo 4 de janeiro

Se você é como eu, então você se esforçou para configurar o Webpack para o seu aplicativo React. O Create- react -app (CRA) já vem com Webpack , mas normalmente precisaríamos adicionar mais configurações à medida que nosso aplicativo cresce. Felizmente para nós, podemos criar um arquivo webpack.config.js e colocar nossas configurações de Webpack lá.

Neste artigo, abordaremos:

  • Configurações genéricas para nosso aplicativo
  • Configurações específicas para produção e desenvolvimento apenas
  • Agrupamento e Minificação de Scripts e Folhas de Estilo
  • Otimizações como code-splitting e lazy-loading

Pré-requisitos

Para configurar esta configuração, precisamos:

  • Conhecimento básico de Javascript e sintaxe ES6 para ES8
  • Conhecimento básico de React

?O código a ser executado no terminal será escrito como $ npm install

Por que precisamos do Webpack?

O Webpack é um bundler amplamente utilizado para aplicativos de javascript, com grande suporte e excelente equipe para mantê-lo. Além disso, é muito fácil de configurar.

O Webpack vem com alguns pacotes para nós:

  • webpack-cli : A ferramenta de linha de comando que nos dá acesso a alguns comandos do Webpack
  • webpack-dev-server : Um servidor do lado do cliente com a capacidade de recarregar apenas para fins de desenvolvimento
  • html-webpack-plugin : Isso irá gerar e atualizar os templates HTML para nosso aplicativo
  • HMR-plugin : Um plugin para habilitar o recarregamento do hot module de nosso aplicativo

E muito mais. O Webpack possui muitos plugins para simplificar o processo de desenvolvimento o máximo possível. Usaremos mais desses plug-ins do Webpack à medida que progredirmos.

Por que precisamos de Babel?

A versão atual do React usa a sintaxe ES6 para ES8. Precisamos que o Babel compile o código escrito nessas sintaxes de volta ao código que o navegador pode entender. Babel está lá para garantir compatibilidade retroativa, certo? Podemos escrever nosso código nas novas sintaxes de limpeza e fazer com que Babel se preocupe com o resto.

Primeiro, temos que configurar nosso aplicativo e instalar algumas dependências de desenvolvimento.

Configuração

Para começar, execute o seguinte comando no seu terminal:

 $ create-react-app webpack-configs 
 $ cd webpack-configs 

Se você não tiver o create-react-app (CRA) instalado, não se preocupe! Ele vem com o nó agora, então vá em frente e execute o seguinte comando para configurar o aplicativo:

 $ npx create-react-app webpack-configs 
 $ cd webpack-configs 

Agora, inicie o aplicativo:

 $ npm run start 

Agora abra o diretório do seu aplicativo no seu editor de texto favorito e exclua os arquivos CSS e SVG no diretório src . Da mesma forma, abra src/App.js e exclua tudo nele, queremos que esteja vazio por enquanto. Vá para o src/index.js e exclua as importações de arquivos CSS e SVG.

 // src/App.js 
 // Empty file 

devDependencies são dependências para desenvolvimento SOMENTE! Então tudo o que vamos instalar em seguida será como devDependency .

Instalando o Webpack e o Babel

Para configurar o Webpack e o Babel, primeiro precisamos instalá-los e alguns dos plugins necessários para a configuração inicial. Execute o seguinte comando no seu terminal:

 $ npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin @babel/core @babel/preset-env babel-loader @babel/preset-react babel-plugin-transform-class-properties babel-plugin-transform-es2015-modules-commonjs 

Feito isso, abra o arquivo package.json e adicione o seguinte aos seus scripts:

 // package.json 
 ... 
  "scripts": { 
  ... 
  "webpack": "webpack", 
  "webpack-dev-server": "webpack-dev-server", 
  "dev": "npm run webpack-dev-server -- --env.mode development", 
  "prod": "npm run webpack -- --env.mode production" 
 } 

Agora salve-o, volte ao seu terminal e tentaremos testar o código recém-adicionado.

Corre:

 $ npm run dev 

Nosso aplicativo quebra, mas não é uma mensagem de erro ruim porque está nos dizendo o que fizemos de errado.

O script que adicionamos ao nosso package.json está tentando executar a configuração do Webpack. Mas nenhum modo de ambiente foi definido, então ele quebra.

Configurando arquivos webpack.config.js e .babelrc

Vamos escrever as configurações para o arquivo webpack.config.js e nosso arquivo .babelrc .

Configurando o Babel

Na pasta raiz, crie um arquivo .babelrc para conter todas as configurações. Execute o seguinte comando no seu terminal:

 $ touch .babelrc 

Abra o arquivo e adicione o código mostrado abaixo:

Se você se lembra, nós instalamos duas predefinições de Babel. Estas pré-configurações são o que adicionamos no arquivo para que o Babel possa lê-las.

O que os presets fazem:

  • “babel-preset-env” diz ao Webpack para compilar toda a sintaxe do ES5 (que os navegadores entendem)
  • “babel-preset-react” react “babel-preset-react” adiciona suporte para a sintaxe jsx
  • “transform-es2015-modules-commonjs” e “transform-class-properties” estão lá para compatibilidade com versões anteriores

Também precisamos de um arquivo para armazenar nossas configurações genéricas de Webpack para nosso aplicativo. No seu terminal, execute:

 $ touch webpack.config.js 

Adicione esta configuração ao arquivo:

Vamos dividir o código no arquivo webpack.config.js acima. O Webpack usa um objeto ou uma função que retorna um objeto em sua configuração. Nós vamos usar a função, então podemos passar nossas variáveis de ambiente para o nosso arquivo de configuração. Isso informará ao Webpack qual configuração do ambiente deve ser executada.

Um exemplo da função seria algo como isto:

 module.exports = ({ mode } = { mode: "production" }) => {} 

E se falharmos em passar um env para deixar o Webpack saber com qual mode trabalhar, o padrão é a production .

Então a função retorna um objeto de propriedades. Propriedades retornadas incluem:

  • mode : Diz ao Webpack em que modo estamos atualmente.
  • entry : Também definimos um arquivo de entrada que será o index.js porque esse é o arquivo principal em seu aplicativo reagente. Ele renderiza o aplicativo para o DOM, então você quer ir a partir daqui para que o Webpack possa viajar por todos os outros componentes.
  • saída : Diz Webpack o que chamar a pasta eo javascript em pacote. Isso está acontecendo nos bastidores sem adicionar essa configuração. Mas, com a configuração, podemos sobrescrevê-lo.
  • plugins : Usados com o Webpack para conseguir o que os carregadores não podem. Alguns plugins são externos e alguns estão dentro do Webpack como o plugin HMR.

Configurando o Webpack para carregar arquivos jsx e estáticos

Após nossa compilação inicial, tivemos alguns erros lançados pelo Webpack. Vamos adicionar as configurações para dizer ao Webpack como lidar com esses erros. Para fazer isso, temos que instalar algumas devDependencies.

Para instalar os carregadores, execute:

 $ npm i -D babel-loader file-loader url-loader 

Vamos escrever uma configuração para o Webpack com os carregadores que instalamos. Atualize seu arquivo webpack.config.js com o código abaixo:

Agora, salve e execute isso no terminal:

 $ npm run prod 

Ele cria e cria uma pasta de build em nossa pasta raiz. Abra a pasta e você verá o arquivo bundle.js e index.html .

Agora vamos colocar o aplicativo em execução:

 $ npm run dev 

Como você pode ver, nosso aplicativo é executado. Agora, vá para .babelrc e comente todos os códigos no arquivo. Então corra:

 $ npm run dev 

Agora, temos erros de compilação:

Aqui está porque está quebrando:

  • webpack é executado e encontra a sintaxe App.js em App.js
  • em seguida, vai para o arquivo webpack.config.js para um carregador que pode dizer o que fazer com jsx
  • então ele encontra o babel-loader e então vai em frente para carregar nosso arquivo .babelrc

Descomente o código e tudo fica verde novamente!

Agora, entre no App.js e adicione o código mostrado abaixo:

Adicione o código abaixo para webpack.config.js também:

 // webpack.config.js 
 ... 
 devServer: { 
  open: true 
 } 

O que a propriedade faz:

  • open : se for verdade, abre nosso aplicativo no navegador.

Agora, toda vez que executarmos $ npm run dev nosso aplicativo abrirá em um servidor do lado do cliente e ouvirá as alterações.

Salve e execute:

 $ npm run dev 

Ele compila e abre nosso aplicativo em http://localhost:8080/

Configurando Hot-Module-Replacement (HMR)

Há um problema que temos, porém, toda vez que fazemos uma mudança, o servidor é recarregado e perdemos nosso estado. Podemos adicionar um plugin Hot Module Replacement que vem com o Webpack em nossa configuração para corrigir isso. Atualize o arquivo webpack.config.js , para que fique parecido com isto:

O que nós adicionamos ao arquivo:

  • Nós ajustamos “ hot ” para true na propriedade devServer . Se for verdade, diz ao webpack que precisamos ativar o HMR
  • Plugin HMR para a nossa gama de plugins, para habilitar o hot-module-reloading do nosso aplicativo

Toda vez que você editar seu arquivo webpack.config.js , você DEVE reiniciar o servidor.

Incremente seu contador e altere o texto do cabeçalho no nosso componente App . Nosso aplicativo renderiza novamente, mas ainda estamos perdendo o estado de nossos aplicativos.

Bem, o HMR do Webpack não pode preservar o estado das nossas aplicações. Para preservar esse estado, precisaremos de outra biblioteca chamada react-hot-loader (RHL). A biblioteca trabalha em conjunto com o Webpack para entregar o HMR à nossa aplicação.

Então, vamos instalá-lo e adicioná-lo às nossas configurações. Vamos travar o servidor e instalar a biblioteca.

Para instalar, primeiro execute o comando abaixo para travar o servidor:

 ctrl + C 

e então corra:

 $ npm i -D react-hot-loader 

Agora atualize o arquivo .babelrc:

 // .babelrc 
 { 
  "presets": [ 
  "@babel/preset-react", 
  [ 
  "@babel/preset-env", 
  { 
  "targets": { 
  "browsers": "last 2 versions" 
  }, 
  "modules": false, 
  "loose": false 
  } 
  ] 
  ], 
  "plugins": [ 
  "transform-class-properties" , "react-hot-loader/babel" 
  ], 
  "env": { 
  "test": { 
  "plugins": [ 
  "transform-es2015-modules-commonjs" 
  ] 
  } 
  } 
 } 

Entre no nosso App.js e atualize o código também:

 // App.js 
 import React, { Component } from "react"; 
 import { hot } from "react-hot-loader"; 
 class App extends Component { 
  state = { 
  counter: 0 
  }; 
  handleClick = () => { 
  this.setState(prevState => { 
  return { counter: prevState.counter + 1 }; 
  }); 
  }; 
  render() { 
  return ( 
  <div className="App"> 
  <h1>I'm configuring setting up Webpack!!!</h1> 
  <p>{`The count now is: ${this.state.counter}`}</p> 
  <button onClick={this.handleClick}>Click me</button> 
  </div> 
  ); 
  } 
 } 
 export default hot(module)(App); 

Adicionamos o código acima ao nosso App.js porque ele será nosso componente pai. Então, envolver o aplicativo com hot (módulo) habilitaria o HMR em todos os outros componentes na árvore. Temos que atualizar nosso index.js para trabalhar com o HMR também.

Entre em nosso src/index.js e atualize o código também:

Em nosso index.js , temos uma instrução condicional que faz o seguinte:

  • module.hot : verifica se há uma alteração no aplicativo e aciona o método de renderização se for verdade
  • process.env.NODE_ENV : verifica se estamos no modo de desenvolvimento
  • module.hot.accept : especifica como lidar com as mudanças

Agora, reinicie seu servidor:

 $ npm run dev 

Agora incremente nosso contador e volte ao App.js e edite o texto. Viola! O estado não está perdido.

Manipulando estilos com o Webpack

Precisamos modelar nosso aplicativo para que possamos personalizar o Webpack para lidar com ele:

  • criar pasta sass na sua pasta src
  • criar um arquivo app.scss na sua pasta sass
  • Copie o código abaixo no app.scss

Observe que nada acontece? Bem, isso é porque o src/app.scss não é usado em nenhum componente, então o Webpack não tentará empacotá-lo. Este é o Tree-Shaking fora da caixa com o Webpack graças à sintaxe do módulo ES5 (ie import and export) . O Webpack não agruparia arquivos não utilizados, portanto, faríamos pacotes mais leves. (Mais sobre a agitação da árvore ).

Vá em frente e importe app.scss para o nosso arquivo App.js :

 // src/App.js 
 import React, { Component } from "react"; 
 import { hot } from "react-hot-loader"; 
 import './sass/app.scss'; 

Ele quebra porque o Webpack não sabe o que fazer com arquivos .sass / .scss / .css. Nós temos que adicionar um carregador para dizer ao Webpack como lidar com as folhas de estilo que estamos usando.

Vamos rodar isso:

 $ npm i -D sass-loader css-loader style-loader 

Vamos implementar esses carregadores de maneiras diferentes com base no ambiente.

Configurando configurações Webpack específicas do ambiente

Antes de configurar os carregadores, temos que dividir nossas configurações. Ao enviar para a produção, queremos pacotes tão leves quanto possível. Mas não estamos tão preocupados com isso para o desenvolvimento. Então, trataríamos as folhas de estilo de maneira diferente para os dois modos. Vamos criar as configurações específicas do ambiente.

Corre:

 $ mkdir build-utils 

Crie webpack.development.js e webpack.production.js na pasta build-utils . Eles vão manter configurações específicas para o seu modo.

webpack.config.js contém nossa configuração genérica.

Para passar configurações específicas do ambiente, precisamos de um pacote de utilitários chamado webpack-merge . Se você estiver familiarizado com o método ES6 Object.assign () , o webpack-merge funciona da mesma maneira. Se você não o fizer, não se preocupe, eu vou entrar no conceito daqui a pouco.

Definimos configurações genéricas para evitar a repetição de códigos, o que é uma boa prática. Agora, precisamos adicionar as configurações específicas à configuração genérica, dependendo do script que executamos. Para conseguir isso, precisamos de uma maneira de concatenar as duas configurações. O Webpack-merge faz exatamente isso. Se houver um conflito de propriedades em nosso webpack.config.js , ele será sobrescrito pela propriedade de entrada.

Precisamos instalar esse utilitário para adicioná-lo às nossas configurações.

Corre:

 $ npm i -D webpack-merge 

Vá para o webpack.config.js e sobrescreva-o com o código abaixo:

Aqui, webpack-merge o pacote webpack-merge , então criamos uma função modeConfiguration que carrega a configuração que corresponde ao modo em que estamos. Vamos passar modeConfiguration como o segundo argumento para webpackMerge . webpackMerge adiciona configurações a partir da configuração genérica.

Agora que temos essa configuração de fluxo, vamos definir nossas configurações específicas do ambiente.

Configurando configurações específicas de desenvolvimento

Quando no modo de desenvolvimento, vamos definir um carregador para nossos arquivos SASS / SCSS.

Adicione o código abaixo ao arquivo webpack.development.js :

 // build_utils/webpack.development.js 
 module.exports = () => ({ 
  module: { 
  rules: [ 
  { 
  test: /.sa?css$/, 
  use: ["style-loader", "css-loader", "sass-loader"] 
  } 
  ] 
  } 
 }); 

Configurando configurações específicas de produção

No modo de produção, vamos fazer algumas coisas:

  • definir um carregador para extrair nossos estilos
  • desativar mapas de origem para nossos arquivos javascript incluídos
  • otimizar nossos estilos

Para instalar o plugin para extrair nossos estilos, execute:

 $ npm i -D mini-css-extract-plugin 

Em seguida, inclua o seguinte código em build_utils/webpack.production.js :

No arquivo acima, definimos um carregador para nossos estilos e o Webpack lê isso da direita para a esquerda.

sass-loader – -> css-loader – -> MiniCssExtractPlugin.

O plug-in extrai nosso CSS dos arquivos JS para um arquivo separado ao entrar em produção.

Eu nomeei o script incluído para o production production.js .

Para construir para produção, execute:

 $ npm run prod 

Com isso, podemos ver nosso arquivo CSS na pasta de saída, embora não otimizado. Podemos otimizá-lo usando plugins como otimizar-css-assets-webpack-plugin e uglifyjs-webpack-plugin para diminuir o CSS.

Para instalar os plugins para otimizar o nosso CSS, execute:

 $ npm i -D optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin 

Atualize o arquivo webpack.production.js com o código abaixo:

Na configuração, desativamos os mapas de origem para ferramentas de desenvolvimento. Ele adiciona meta-informações para o navegador em nossas ferramentas de desenvolvimento para depuração, mas a desvantagem é a velocidade de construção mais lenta. Então, podemos ter isso em desenvolvimento, mas definitivamente não em produção.

Exclua a pasta de build . Em seguida, execute o comando build para reconstruir com um arquivo CSS reduzido:

 $ npm run prod 

Ele constrói com um arquivo CSS otimizado agora. Bom trabalho!

Lazying carregando nosso aplicativo

Para aplicação lenta de React, usamos uma biblioteca chamada react-loadable . Tem um componente de ordem superior (HOC) chamado Loadable . Carregável dinamicamente carrega qualquer módulo antes de renderizá-lo em seu aplicativo.

Para instalar a biblioteca como uma dependência, execute:

 $ npm i -D react-loadable 

Após a instalação, crie um novo arquivo em src chamado LoadableApp.js

Copie o código abaixo para ele:

 // src/LoadableApp.js 
 import React, { Component } from "react"; 
 import Loadable from "react-loadable"; 
 const LoadApp = Loadable({ 
  loader: () => import("./App"), 
  loading() { 
  return <div>Loading...</div>; 
  }, 
  timeout: 10000 // 10 seconds 
 }); 
 export default class LoadableApp extends Component { 
  render() { 
  return <LoadApp/> 
  } 
 } 

Deixe-me explicar o código acima:

  • nós importamos o HOC Loadable de carregável por reação
  • nós passamos em um objeto para dizer ao Loadable o que fazer
  • loader : isto diz ao Loadable para importar nosso componente especificado
  • loading : uma mensagem para exibir aos usuários enquanto o Loadable está importando nosso componente
  • tempo limite : isso diria ao Loadable por quanto tempo tentar carregar o componente antes que ele falhe. Lida com problemas com conexão lenta à internet
  • nós atribuímos o componente retornado por Loadable to LoadApp
  • nós renderizamos o componente retornado

Agora, temos que atualizar nosso index.js para renderizar o componente pregueado e de divisão de código. Precisamos mudar cada menção ao App.js com o LoadableApp.js .

Sobrescreva-o com o código abaixo:

Corre:

 npm run dev 

Ainda não estamos lá. Nosso aplicativo lança um erro no console:

Nós precisamos adicionar um plugin ao nosso .babelrc para dizer ao Babel para analisar importações dinâmicas.

Para instalar o plugin, execute:

 $ npm i -D babel-plugin-syntax-dynamic-import 

Atualize o array de plugins em .babelrc para:

 // .babelrc 
 "plugins": [ 
  "transform-class-properties", 
  "react-hot-loader/babel", 
  "syntax-dynamic-import" 
 ] 

Nosso aplicativo recompila sem erros lançados. Também do Webpack 2+, sempre que você usar a sintaxe import() , o Webpack automaticamente divide o código para você. Portanto, não só estamos carregando os nossos componentes de forma preguiçosa agora, mas também dividindo-os por código.

Conclusão

É isso para configurar o Webpack com o React para necessidades de configuração genéricas e específicas. Se você quiser personalizar isso ainda mais, você pode descobrir mais sobre os documentos Webpack para obter insights sobre como fazê-lo. Você pode encontrar uma versão funcional deste projeto no GitHub .

Plug: LogRocket , um DVR para aplicativos da web

https://logrocket.com/signup/

LogRocket é uma ferramenta de registro de front-end que permite que você repita problemas como se eles tivessem ocorrido em seu próprio navegador. Em vez de adivinhar por que os erros ocorrem ou solicitar aos usuários capturas de tela e log dumps, o LogRocket permite que você repita a sessão para entender rapidamente o que deu errado. Ele funciona perfeitamente com qualquer aplicativo, independentemente do framework, e possui plugins para registrar o contexto adicional do Redux, Vuex e @ ngrx / store.

Além de registrar as ações e o estado do Redux, o LogRocket registra logs do console, erros de JavaScript, rastreamentos de pilha, solicitações / respostas de rede com cabeçalhos + corpos, metadados do navegador e logs personalizados. Ele também instrumenta o DOM para gravar o HTML e CSS na página, recriando vídeos com pixels perfeitos até mesmo dos aplicativos de página única mais complexos.

Experimente Grátis.