Webpack + Babel – Criando um boilerplate básico de uma aplicação front-end moderna

Compartilhe nas redes sociais

Olá pessoal! Neste post vamos criar passo a passo uma estrutura básica que você poderá usar em qualquer novo projeto front-end, usando Webpack e Babel.

Update:
Parte 2 disponível: Webpack – Tornando o trabalho com nosso boilerplate front-end mais produtivo.

Não sei se você já parou pra pensar sobre isso, mas, por trás do React, Vue, Angular… estão justamente as tecnologias que vamos aprender aqui.

Você pode pensar: Mas pra que eu deveria saber disso se essas bibliotecas e frameworks JavaScript já fazem esse trabalho por mim?

Eu te respondo: Se você quer ser um profissional melhor e mais completo, é importante que você saiba como algumas coisas funcionam e como são feitas…

Conhecimento nunca é demais! =)

Todo o código que será descrito neste post está disponível neste repositório.

Tecnologias que serão aplicadas:

  • Node Package Manager (npm)
  • Webpack
  • Babel

Mãos à obra!

Novo projeto NPM

Vamos começar criando o diretório onde nosso boilerplate ficará. O meu chamará jj-boilerplate. Usando o terminal basta inserir o comando mkdir jj-boilerplate

Feito isso, vamos entrar na pasta e iniciar um novo projeto do npm com os comandos abaixo:

cd jj-boilerplate

npm init

Após o comando npm init, responda as perguntas que lhe forem feitas e vá apertando a tecla Enter para cada uma até que tudo seja concluído.

Agora que temos um novo projeto npm configurado em nosso diretório, podemos instalar as dependências do nosso boilerplate.

Babel

O Babel é um compilador JavaScript que nos permite escrever códigos usando a sintaxe mais recente da linguagem enquanto ele (Babel) se encarrega de compilar tudo para as versões mais antigas e compatíveis com os browsers.

Use o JavaScript da próxima geração, hoje.

Vamos então adiciona-lo ao nosso projeto:

npm install --save-dev @babel/core @babel/preset-env

npm install --save @babel/polyfill

Para que o Babel consiga trabalhar também com as features do JavaScript async/await e generators precisaremos instalar mais duas dependências:

npm install --save-dev @babel/runtime @babel/plugin-transform-runtime

Feito isso, vamos criar o arquivo de configuração do Babel, o .babelrc.

{
  "presets": ["@babel/preset-env"],
  "plugins": [
    ["@babel/plugin-transform-runtime", {"regenerator":  true}]
  ]
}

Por enquanto tudo certo por aqui.

Webpack

Na sua essência, o Webpack é um empacotador de módulo estático para aplicativos JavaScript modernos. Quando o Webpack processa seu aplicativo, ele cria internamente um gráfico de dependência que mapeia todos os módulos de que seu projeto precisa e gera um ou mais pacotes configuráveis.

Sua instalação é fácil:

npm install webpack --save-dev
npm install webpack-cli --save-dev

O Webpack fará também a ligação com o Babel, compilando nosso código antes de gerar os bundlers, para isso precisamos instalar um loader específico:

npm install --save-dev babel-loader

Agora tudo que precisamos fazer é criar um arquivo chamado webpack.config.js onde adicionaremos algumas linhas de configuração:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');

module.exports = {
    entry: {
        home: './src/home/index.js',
        contact: './src/contact/index.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    module: {
        rules: [
            { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader'}
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Página Inicial',
            hash: true,
            cache: true,
            filename: 'index.html',
            template: 'src/templates/home.html',
            chunks: ['home']
        }),
        new HtmlWebpackPlugin({
            title: 'Fale conosco',
            hash: true,
            cache: true,
            template: 'src/templates/contact.html',
            filename: 'contact.html',
            chunks: ['contact']
        })
    ]
};

Vamos entendê-lo.

A chave entry informa para o Webpack qual arquivo ele deverá usar como ponto de partida para fazer seu trabalho.

A chave output informa em qual diretório deverá ficar e qual nome o arquivo final deverá ter.

A chave rules serve para informar ao Webpack quais loaders queremos usar, no caso estamos usando o babel-loader nos arquivos de extensão .js, isso aplicará a compilação aos códigos Javascript.

Por fim, a chave plugins informa quais plugins desejamos usar. No nosso caso o html-webpack-plugin, cuja finalidade é automaticamente inserir os arquivos de bundle gerados pelo Webpack em uma página HTML.

Você deveria ler toda a documentação do Webpack para entender melhor como tudo funciona. Sério, é muito interessante!

Em uma linguagem simples, nosso arquivo de configuração está dizendo ao Webpack:

“Pegue os arquivos JavaScript das pastas home e contact, use o Babel e faça a compilação para ES5, gere respectivamente os arquivos index.html e contact.html baseados nos templates que lhe informei e, então, insira os arquivos já compilados em seus respectivos documentos html.”

É fácil!

Vamos codar de verdade agora!?

Para verificar se nossas configurações estão funcionando corretamente precisaremos de um pouco de código JavaScript.

Seguindo a configuração que criamos em nosso arquivo webpack.config.js, precisaremos ter a seguinte estrutura de arquivos e diretórios:

jj-boilerplate (root)
-- dist
-- src
   -- contact
      -- index.js
   -- home
      -- index.js
   -- templates
      -- contact.html
      -- home.html
   -- tools
      -- message.js

Vamos então cria-la.

src/tools/message.js:

export const showMessage = (message = '') => {
    alert(message);
};

src/contact/index.js:

import { showMessage } from '../tools/message';

showMessage('Estamos na Página de contato');

src/home/index.js:

import { showMessage } from '../tools/message';

showMessage('Estamos na Home');

src/templates/contact.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title><%= htmlWebpackPlugin.options.title%></title>
</head>
<body>
    <h1><%= htmlWebpackPlugin.options.title%></h1>
    <p><a href="/index.html">Voltar para home</a></p>
</body>
</html>

src/templates/home.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title><%= htmlWebpackPlugin.options.title%></title>
</head>
<body>
    <h1><%= htmlWebpackPlugin.options.title%></h1>
    <p><a href="/contact.html">Página de contato</a></p>
</body>
</html>

Nada de complexo né? Apenas alguns arquivos .js que importam outro arquivo, e uma chamada de função.

“Buildando” tudo

Agora que já temos nossas dependências instaladas, nossos arquivos de configuração do Babel e do Webpack e nosso código de exemplo devidamente criados, temos que criar as instruções de execução no package.json.

Vamos lá?

package.json

Certifique-se que no seu arquivo, a chave scripts fique igual à seguinte:

"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"
},

Com isso, temos agora um meio de “buildar” nosso codigo. =)

Se no seu terminal, dentro do diretório root do seu projeto, você executar
npm run build o Webpack vai fazer seu trabalho e irá disponibilizar no diretório dist o código gerado.

Após isso, no diretório dist existirão os seguintes arquivos:
contact.html, contact.js, home.js e index.html

Esses serão seus arquivos finais. Basta disponibiliza-los em seu web-server preferido, acessar o index.html e ver como tudo está funcionando perfeitamente.

Tem mais?

Obviamente, em um projeto real de front-end nós teremos que manipular arquivos css com ou sem a ajuda de pré-processadores. Na verdade seria muito legal também se pudéssemos ir automaticamente refazendo o build toda vez que o código for alterado. Ou se conseguissemos ter um web server já embutido, pra ir visualizando o código gerado pelo webpack… né?

E se pudéssemos também já ir trabalhando com testes? Ou talvez ter um Linter configurado… enfim, tem muita coisa que seria legal ter em mãos!

Então, já vou escrever um outro post ensinando a deixar nosso boilerplate ainda mais robusto.

Por hoje é só pessoal!

Dúvidas e/ou sugestões são muito bem vindas.

Até mais.