Introdução a Webpack Parte 2: Loaders

Blog fellyph cintra - logo on white bg

No post anterior vimos uma introdução a Webpack, criamos uma situação básica carregando múltiplos arquivos JavaScript e vimos que Webpack possui 4 elementos chaves: Entry(arquivo de entrada), output(arquivo de saída), loaders e plugins.

Nesse tutorial vamos abordar como trabalhamos como loaders, Webpack em seu core nada mais é que JavaScript carregando JavaScript. Nada mais básico que em uma aplicação web termos uma série de assets com diferentes extensões, jpg, css, js, svg… e como o Webpack se trata com essa situações, a resposta é: Loaders

Loaders

Loaders dão Webpack a possibilidade de processar diferentes tipos de arquivos, define como o Webpack irá ler e exportar os assets do seu projeto. Escritos em Node.JS os loaders precisam regras escritas em expressão regular para definir quais extensões serão carregadas pelo tal.

Temos vários loaders e podemos separa-los nas seguintes categorias:

  • Arquivos
  • JSON
  • Transpiling
  • Templating
  • Styling
  • Linting
  • Frameworks

Para nosso tutorial vamos utilizar os seguintes recursos, babel para fazer o transpiling do nosso ECMAScript2015+ e JSX e Sass para fazer o pre-processamento do nosso estilo. Com esse panorama vamos precisar dos seguintes loaders:

  • Arquivos: url-loader, file-loader
  • Transpiling: babel-loader
  • Styling: style-loader, css-loader, sass-loader

Com essa lista vamos seguir um passo-a-passo e falar sobre cada um desses loaders durante a evolução de nosso projeto.

babel-loader

Hoje desenvolvimento com JavaScript moderno é um requisito quase que obrigatório em projetos web, em nossos exemplos anteriores fizemos o uso de EcmaScript 5, versão suportada por todos os browsers do mercado incluindo internet Explorer, mas se a gente quiser fazer o uso de EcmaScript2015+ e não deixar de fora os usuários de browsers mais antigos, reposta será “transpiling”, ele funciona como uma compilação de código, onde temos EcmaScript 2015+ sendo convertido para EcmaScript 5, no mercado temos algumas ferramentas que realizam esse processo atualmente a ferramenta mais usada no mercado é babel.

Webpack é umas da tecnologias compatíveis com babel, assim podemos fazer o processo de transpiling utilizando babel para criar o nosso bundle. Para isso vamos primeiramente instalar babel-loader em nosso projeto, dentro do nosso terminal, na pasta do seu projeto executamos o seguinte comando:

npm install -D babel-loader @babel/core @babel/preset-env
Code language: CSS (css)

Nesse código temos a instalação do babel-loader, babel core e preset-env, presets são coleções de plugins para o babel suportar uma certa versão, ainda temos presets para cada versão do EcmaScript, react e typescript. Mas a preset-env tem o foco no target environment, ou seja, no ambiente final. Ele suporta as versões mas recentes do ecmaScript, mas o código gerado conseguimos determinar qual será o nível de suporte. Após a instalação dos pacotes nosso package.json ficará da seguinte forma:

{ "name": "webpack-tutorial", "version": "1.0.0", "description": "Webpack tutorial", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+https://github.com/fellyph/webpack-tutorial.git" }, "keywords": [ "tutorial", "webpack" ], "author": "fellyph", "license": "ISC", "bugs": { "url": "https://github.com/fellyph/webpack-tutorial/issues" }, "homepage": "https://github.com/fellyph/webpack-tutorial#readme", "devDependencies": { "@babel/core": "^7.2.2", "@babel/preset-env": "^7.3.1", "babel-loader": "^8.0.5", "webpack": "^4.29.0", "webpack-cli": "^3.2.1" }, "dependencies": { "npm": "^6.7.0" } }
Code language: JSON / JSON with Comments (json)

Depois de instalado os pacotes necessários, vamos incluir o loader em nosso webpack.config.js

const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] } };
Code language: JavaScript (javascript)

No código acima adicionamos um novo atributo chamado module, ele será responsável por definir as regras de como os nosso módulos serão carregados, passamos um array de regras(rules) contendo os seguintes parâmetros:

  • test: contém uma expressão regular para achar os arquivos que iremos aplicar a regra, na sua maioria utilizamos a extensão que buscamos.
  • exclude: também uma expressão regular, contendo os arquivos ou pastas que iremos ignorar.
  • use: qual o loader iremos utilizar para esse caso.

Por exemplo, em nosso código definimos que todos arquivos que terminam com a extensão .js iremos usar o loader ‘babel-loader‘, dentro do nosso código de entrada adicionamos EcmaScript2015 se conferimos o código gerado temos, por exemplo, a keyword ‘const’ convertida para ‘var’. O exemplo completo você pode conferir na branch step-6.

style-loader e css-loader

Continuando a evolução de nosso webpack.config.js vamos carregar o nosso estilo, para essa tarefa vamos instalar dois loaders css-loader e style-loader, css-loader vai ser responsável por carregar o css junto com webpack e style-loader vai pegar o conteúdo carregado pelo webpack e exportá-lo em uma tag style. Agora em nosso terminal iremos rodar o seguinte código:

npm i -D style-loader css-loader

Completa a instalação vamos adicionar o loader em nosso webpack.config.js

const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } }, { test: /\.css$/, exclude: /(node_modules|bower_components)/, use: ['style-loader', 'css-loader'], } ] } };
Code language: JavaScript (javascript)

Após adicionarmos a configuração para carregar nosso css o padrão será o mesmo, regex para achar os arquivos css, quais o loaders iremos utilizar com a propriedade use, adicionei um css simples chamado main.css:

:root { --c-text:#28262C; --c-component-background: #F9F5FF; --c-primary: #14248A; --c-secondary: #D4C2FC; --c-ternary: #998FC7; --e-padding: 1em; } .navigation, .main, .header, .footer { padding: var(--e-padding); } .navigation { background: var(--c-primary); } .main { background: var(--c-component-background); } .header { background: var(--c-component-background); } .footer { background: var(--c-ternary); }
Code language: CSS (css)

Em nosso index.js vamos carregar o css, isso mesmo, faremos o import dentro do nosso arquivo de entrada:

import './css/main.css'; import './js/content'; import './js/header'; import './js/footer';
Code language: JavaScript (javascript)

Quando executarmos o comando webpack em nossa linha de comando teremos a seguinte saída, o arquivo gerado o main.js e os arquivos que serviram de entrada para nosso bundle. O código para esse loader você irá encontrar na branch step-7

Vamos adicionar uma image ao nosso projeto via css, a imagem abaixo será a imagem que iremos trabalhar voce pode salva-la e adicionar na pasta assets/imgs/

Segunda parte de introdução a webpack

Com a image no local definido vamos fazer a seguinte alteracao em nosso CSS:

:root { --c-text:#28262C; --c-component-background: #F9F5FF; --c-primary: #14248A; --c-secondary: #D4C2FC; --c-ternary: #998FC7; --e-padding: 1em; --header-img: url(../../assets/imgs/webpack-logo.png); } .navigation, .main, .header, .footer { padding: var(--e-padding); } .navigation { background: var(--c-primary); } .main { background: var(--c-component-background); } .header { background: var(--header-img); background-repeat: no-repeat; } .footer { background: var(--c-ternary); }
Code language: CSS (css)

Vamos adicionar a nossa imagem como background do nosso header e tentar compilar o nosso código:

Temos um erro de compilacao do nosso codigo

Isso acontece porque não temos o loader apropriado para a extensão .png, para esse caso podemos trabalhar com loaders:

  • file-loader: irá carregar o arquivo e criar uma copia do arquivo em nossa pasta de output(dist)
  • url-loader: irá carregar o arquivo especificado e irá criar uma copia no formato base64.

Para corrigir o nosso projeto iremos instalar dos dois loaders:

npm i -D file-loader url-loader

Com os loaders instalados vamos combinar os dois loaders em uma solução, arquivos pequenos convertemos em base64 e arquivos pesado criamos uma copia em nossa pasta dist, como podemos ver em nosso webpack.config.js (step-8):

const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } }, { test: /\.css$/, exclude: /(node_modules|bower_components)/, use: ['style-loader', 'css-loader'], }, { test: /\.(svg|gif|png|jpe?g)$/, loader: 'url-loader', options: { limit: 100, fallback: 'file-loader', publicPath: '/img', outputPath: '/img', }, }, ] } };
Code language: JavaScript (javascript)

Agora temos loaders para nossos arquivos .js .css e images, caso queiramos trabalhar com pre-processadores, por exemplo, SASS ou LESS, parra o nosso tutorial iremos trabalhar com SASS mas o processo é similar para o LESS. Primeiro em nosso terminal iremos instalar os pacotes necessários:

npm install sass-loader node-sass --save-dev

Com tudo pronto vamos alterar a regra de leitura no nosso css para também aceitar arquivos SASS.

const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } }, { test: /\.(sa|sc|c)ss$/, exclude: /(node_modules|bower_components)/, use: [ 'style-loader', 'css-loader', 'sass-loader', ], }, { test: /\.(svg|gif|png|jpe?g)$/, loader: 'url-loader', options: { limit: 100, fallback: 'file-loader', publicPath: '/img', outputPath: '/img', }, }, ] } };
Code language: JavaScript (javascript)

A principal diferença em nosso webpack.config.js é regex que anteriomente procurava arquivos com a extensão .css agora com a regra ‘(sa|sc|c)ss’ procura arquivos .sass .scss ou .css e por fim adicionamento o sass-loader, se trocarmos a extensão do nosso arquivo .css por .scss ele irá carregar normalmente. Exemplo:

_variables.scss

$c-text:#28262C; $c-component-background: #F9F5FF; $c-primary: #14248A; $c-secondary: #D4C2FC; $c-ternary: #998FC7; $e-padding: 1em; $header-img: url(../../assets/imgs/webpack-logo.png);
Code language: PHP (php)

main.scss

@import 'variables'; .navigation, .main, .header, .footer { padding: $e-padding; } .navigation { background: $c-primary; } .main { background: $c-component-background; } .header { background: $header-img; background-repeat: no-repeat; } .footer { background: $c-ternary; }
Code language: CSS (css)

Concluindo a segunda parte da introdução a webpack

O código completo desse tutorial você irá encontrar na branch step-9 E até o próximo tutorial. Veja mais posts sobre webpack aqui.

Por Fellyph Cintra

Fellyph Cintra é um Google Developer Expert focado em tecnologias web, com participação ativa na comunidade WordPress. Com mais de 14 anos de experiência no mercado, Fellyph já palestrou em mais de 30 eventos ao redor do Brasil e Europa, sempre abordando as boas práticas de desenvolvimento na web.

Deixe um comentário

O seu endereço de e-mail não será publicado.