Webpack – Tornando o trabalho com nosso boilerplate front-end mais produtivo.

Compartilhe nas redes sociais

No primeiro artigo desta série criamos uma estrutura básica de um projeto front-end usando Webpack e Babel.

Hoje iremos evoluir um pouco mais nosso boilerplate fazendo com que seu uso no ambiente de desenvolvimento torne nosso trabalho mais produtivo.

Por exemplo, talvez você não tenha reparado, mas, os arquivos que são gerados pelo Webpack, já compilados pelo Babel, são muito difíceis de fazer debug e isso dificulta bastante nosso trabalho…

Então nós iremos adicionar algumas configurações extras no Webpack que nos possibilitarão:

  • Limpar a pasta dist automaticamente, evitando código antigo no diretório.
  • Adicionar source maps que facilitarão o processo de debug.
  • Usar um modo de rebuild automático quando acontecerem alterações.

Ao fim, com certeza nosso boilerplate nos ajudará a ter uma produtividade melhor durante o desenvolvimento de uma aplicação.

Todo o código fonte deste artigo e do anterior você encontra neste repositório.

Bora la?

Limpando o diretório dist

Sempre que você remover ou adicionar ‘páginas’ no seu arquivo de configuração do Webpack e fizer um novo buildnpm run build, ele irá gerar os arquivos e colocá-los na pasta dist para você, mas não controlará quais arquivos estão realmente em uso pelo seu projeto.

Sendo assim, uma boa prática é sempre limpar o diretório antes de cada build, eliminando qualquer arquivo referente a builds antigos.

clean-webpack-plugin

Este plugin limpa a pasta dist automaticamente antes de cada build para nós.

Para usá-lo basta instalá-lo:

npm install --save-dev clean-webpack-plugin

E então adicioná-lo ao arquivo de configuração, webpack.config.js:

const path = require('path');
// ... 
// adicione a importação do plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// ...
// ...
// inicialize uma nova instancia do plugin na chave 'plugins' da configuração.

module.exports = {
// ...,
    plugins: [
        //... instancias do plugin HtmlWebpackPlugin
        // ...
        new CleanWebpackPlugin(),
    ]
};

Feito! Agora, toda vez antes que o build for feito a pasta dist terá todo seu conteúdo apagado.

mode=development

O Webpack espera que nós o informemos quando estivermos trabalhando no ambiente de desenvolvimento. Isso porque ele verifica qual mode está configurado e ativa ou desativa features específicas pra cada modo.

Essas features são detalhes importantes para cada caso, seja se você estiver trabalhando em desenvolvimento ou se já estiver fazendo o build para produção. Por exemplo: Habilitar o cache interno do Webpack, exibir ou não mensagens de erro, etc…

Informar o Webpack sobre qual ambiente estamos trabalhando pode ser feito através da chave mode no arquivo de configuração ou pelo próprio cli, usando a flag --mode=development.

No nosso caso usamos a opção segunda opção (cli).

Onde definimos isso? No nosso package.json.

"scripts": {
  "build": "./node_modules/.bin/webpack --colors --progress --mode=development",
  "build:production": "./node_modules/.bin/webpack --colors --progress --mode=production",
  "watch": "npm run build -- --watch"
},

Viu alí? Nos scripts build e build:production, definimos respectivamente --mode=development e --mode=production.

Então: 
npm run build (development mode)

npm run build:production (production mode)

Se na hora de executar o Webpack não informarmos nenhum mode ele sempre assumirá o default que é production.

Para saber mais leia a parte da documentação que fala a respeito disso.

Debugando com source maps

Em nosso processo de build o Webpack transpila o código moderno para JavaScript “antigo” usando o Babel e depois junta os arquivos que são importados com os arquivos importadores, formando pacotes únicos.

Por exemplo: em nosso caso, src/home/index.js importa o src/tools/message.js.
O Webpack vai gerar o dist/index.js que conterá o código compilado de ambos citados anteriormente.

Isso tudo torna o debugging absurdamente difícil, pois as mensagens de erro e os números das linhas não apontarão para o arquivo e código original, mas sim para o já compilado.

A fim de facilitar a localização de erros e avisos, o próprio JavaScript oferece um recurso chamado mapas de origem (source maps), que mapeiam seu código compilado de volta ao seu código-fonte original. Se um erro se originar do message.js, o source map informará exatamente isso.

Para habilitar isso no Webpack basta adicionar a seguinte linha no nosso webpack.config.js:

module.exports = {
   // ...,
    devtool: 'inline-soure-map',
   // ...
};

Vamos fazer um teste?

Altere o seguinte arquivo.
src/tools/message.js:

export const showMessage = (message = '') => {
    alerttt(message); // nome da função alert escrito errado.
};

Faça o build, abra o arquivo index.html no browser e olhe o console do JavaScript. Vai ter um erro, e o erro apontará para o arquivo original! =D

Sucesso!

Existem várias opções disponíveis quando se trata de source maps. Verifique-as para que você possa configurá-las de acordo com suas necessidades.

Neste artigo usamos a opção inline-source-map, que é boa para fins ilustrativos (embora não seja para produção).

Rebuild automático

Executar npm run build manualmente toda vez que você alterar seu código se torna rapidamente um aborrecimento.

Por isso existem algumas opções diferentes disponíveis no Webpack que ajudam a compilar automaticamente seu código sempre que ele é alterado.

Aqui iremos abordar duas delas, o Watch mode e o webpack-dev-server.

Usando o Watch Mode

Você pode instruir o Webpack a “observar” todos os arquivos em seu gráfico de dependências quanto a alterações. Se um desses arquivos for atualizado, o código será recompilado para que você não precise executar a compilação completa manualmente.

Na verdade nós já criamos essa instrução no nosso primeiro artigo quando configuramos nossos scripts no arquivo package.json:

"scripts": {
  // ... outros scripts,
  "watch": "npm run build -- --watch"
},

Isso mesmo, informamos a flag --watch ao executar o webpack.

Em nosso caso criamos o script watch, então, basta rodar o comando npm run watch para que o Webpack comece a ‘observar’ os arquivos e a recompilar automaticamente depois de cada alteração.

Usando webpack-dev-server

O webpack-dev-server nos fornece um servidor web simples junto com a capacidade de usar live reloading.

Isso faz com que ele seja muito mais usado do que o watch mode.

Sua configuração é facil:

npm install --save-dev webpack-dev-server

Alteramos o webpack.config.js:

module.exports = {
   // ...,
    devServer: {
        contentBase: './dist'
    },
   // ...
};

Isso informa ao webpack-dev-server para servir os arquivos do diretório dist no localhost: 8080.

Vamos então adicionar mais um script para executar facilmente nosso web server.

package.json:

"scripts": {
  // ... outros scripts,
  "start": "webpack-dev-server --open"
},

Agora podemos executar o npm start a partir da linha de comando e veremos nosso navegador carregando automaticamente nossa página.

Toda vez que você alterar um arquivo de origem e salvá-lo o servidor web será recarregado automaticamente após a compilação do código e você verá instantaneamente as alterações no browser.  Teste você mesmo!

webpack-dev-server é muito útil e vem com uma série de outras configurações que valem a pena você se aprofundar. Veja em sua documentação.

Conclusão

Conforme o prometido no inicio do artigo, nosso boilerplate agora limpa a pasta dist toda vez antes do build, nos dá o source map na hora do debug e o melhor de tudo, possui um web server local que nos possibilita live reloading a cada alteração do código. =D

Para um próximo artigo que tal adicionarmos um Lint e uma suite de testes?

Por hoje é só pessoal… Dúvidas e sugestões são sempre bem vindas!

Abraço!