Bom dia amigos!
Apresento a vocês uma tradução do artigo "Webpack: Uma introdução suave", de Tyler McGinnis.
Antes de explorar uma nova tecnologia, pergunte-se duas vezes:
- Por que essa ferramenta é necessária?
- Que tarefas ele executa?
Se você não puder responder a essas perguntas, talvez não precise da tecnologia que está estudando. Vamos tentar responder a essas perguntas em relação ao Webpack.
Por que você precisa de um webpack?
Webpack é um construtor de módulo. Ele analisa os módulos do aplicativo, cria um gráfico de dependência e, em seguida, monta os módulos na ordem correta em um ou mais pacotes, que podem ser referenciados pelo arquivo "index.html".
App.js -> |
Dashboard.js -> | Bundler | -> bundle.js
About.js -> |
Que problemas o webpack resolve?
Normalmente, ao criar um aplicativo JavaScript, o código é dividido em várias partes (módulos). Então, no arquivo "index.html", você deve especificar um link para cada script.
<body>
...
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="libs/react.min.js"></script>
<script src='src/admin.js'></script>
<script src='src/dashboard.js'></script>
<script src='src/api.js'></script>
<script src='src/auth.js'></script>
<script src='src/rickastley.js'></script>
</body>
Isso não é apenas tedioso, mas também sujeito a erros. É importante não apenas não esquecer nenhum script, mas também organizá-los na ordem correta. Se você carregar um script que dependa do React antes de carregar o próprio React, seu aplicativo será interrompido. Webpack resolve esses problemas. Não há necessidade de se preocupar em incluir todos os scripts em sequência.
<body>
...
<script src='dist/bundle.js'></script>
</body>
Como aprenderemos em breve, coletar módulos é apenas um aspecto de como um webpack funciona. Se necessário, você pode forçar o webpack a fazer algumas transformações de módulo antes de adicioná-los ao pacote. Por exemplo, a conversão de SASS / LESS em CSS regular ou JavaScript moderno em ES5 para navegadores mais antigos.
Instalando um webpack
Após inicializar o projeto com npm, para que o webpack funcione, você precisa instalar dois pacotes -
webpacke webpack-cli.
npm i webpack webpack-cli -D
webpack.config.js
Depois de instalar esses pacotes, o webpack precisa ser configurado. Para isso, é criado um arquivo
webpack.config.jsque exporta o objeto. Este objeto contém configurações do webpack.
module.exports = {}
A principal tarefa de um webpack é analisar módulos, transformá-los de forma opcional e combiná-los de forma inteligente em um ou mais pacotes, de forma que o webpack precisa saber três coisas:
- Ponto de entrada do aplicativo
- Conversões a serem realizadas
- Onde colocar o pacote gerado
Ponto de entrada
Não importa quantos módulos um aplicativo contenha, sempre haverá um único ponto de entrada. Este módulo inclui o resto. Normalmente, esse arquivo é index.js. Pode ser assim:
index.js
imports about.js
imports dashboard.js
imports graph.js
imports auth.js
imports api.js
Se informarmos ao webpack o caminho para esse arquivo, ele o usará para criar o gráfico de dependência do aplicativo. Para fazer isso, você precisa adicionar uma propriedade
entryàs configurações do webpack com o valor do caminho para o arquivo principal:
module.exports = {
entry: './app/index.js'
}
Conversão com carregadores
Depois de adicionar o ponto de entrada, você precisa informar o webpack sobre as transformações que precisam ser realizadas antes de gerar o pacote. Para isso, são usados carregadores.
Por padrão, ao gerar gráficos de dependência baseados em operador, o
import / require()webpack só pode processar arquivos JavaScript e JSON.
import auth from './api/auth' //
import config from './utils/config.json' //
import './styles.css' // ️
import logo from './assets/logo.svg' // ️
É improvável que você se atreva a se limitar a arquivos JS e JSON em seu aplicativo; provavelmente você também precisará de estilos, SVGs, imagens, etc. É aí que entram os carregadores. A principal tarefa dos carregadores, como o nome indica, é permitir que o webpack funcione com mais do que apenas arquivos JS e JSON.
A primeira etapa é instalar o carregador. Como queremos carregar o SVG, use o npm para instalar o svg-loader.
npm i svg-inline-loader -D
Em seguida, adicione-o às configurações do webpack. Todos os carregadores estão incluídos em uma série de objetos
module.rules:
module.exports = {
entry: './app/index.js',
module: {
rules: []
}
}
As informações do carregador consistem em duas partes. O primeiro é o tipo de arquivo que está sendo processado (
.svgno nosso caso). O segundo é o carregador usado para processar este tipo de arquivo ( svg-inline-loaderno nosso caso).
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' }
]
}
}
Agora podemos importar arquivos SVG. Mas e quanto aos nossos arquivos CSS? Para estilos usados
css-loader.
npm i css-loader -D
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: 'css-loader' }
]
}
}
Agora podemos importar arquivos SVG e CSS. No entanto, para que nossos estilos funcionem corretamente, precisamos adicionar outro carregador. Graças a,
css-loaderpodemos importar arquivos CSS. Mas isso não significa que eles serão incluídos no DOM. Queremos não apenas importar esses arquivos, mas também colocá-los em uma tag <style>para que se apliquem aos elementos DOM. Para isso você precisa style-loader.
npm i style-loader -D
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }
]
}
}
Observe que, como dois carregadores são usados para processar arquivos CSS, o valor da propriedade
useé um array. Também preste atenção na ordem dos carregadores, primeiro style-loader, então css-loader. É importante. O webpack irá aplicá-los na ordem inversa. Ele é usado primeiro css-loaderpara importações e './styles.css', em seguida, style-loaderpara injetar estilos no DOM.
Os carregadores podem ser usados não apenas para importar arquivos, mas também para convertê-los. O mais popular é converter o JavaScript da próxima geração em JavaScript moderno usando o Babel. É usado para isso
babel-loader.
npm i babel-loader -D
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(js)$/, use: 'babel-loader' }
]
}
}
Existem carregadores para quase qualquer tipo de arquivo.
Ponto de saída
Agora, o webpack conhece o ponto de entrada e os carregadores. A próxima etapa é especificar o diretório do pacote. Para fazer isso, adicione uma propriedade
outputàs configurações do webpack.
const path = require('path')
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(js)$/, use: 'babel-loader' }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
}
}
Todo o processo se parece com isto:
- O webpack recebe um ponto de entrada localizado em
./app/index.js - Ele analisa as instruções
import / requiree cria um gráfico de dependência - O webpack começa a construir o pacote convertendo o código usando os carregadores apropriados
- Ele coleta um pacote e o coloca em
dist/index_bundle.js
Plugins
Vimos como usar carregadores para processar arquivos individuais antes ou durante a geração de um pacote. Ao contrário dos carregadores, os plug-ins permitem que você execute tarefas após criar um pacote. Essas tarefas podem envolver o próprio pacote e outro código. Você pode pensar nos plug-ins como carregadores mais poderosos e menos limitados.
Vamos dar um exemplo.
HtmlWebpackPlugin
A principal tarefa de um webpack é gerar um bundle que possa ser referenciado em
index.html.
HtmlWebpackPlugincria index.htmlno diretório com o pacote e adiciona automaticamente um link para o pacote nele.
Nomeamos o pacote
index_bundle.jse o colocamos dist. HtmlWebpackPluginirá criar um novo arquivo index.htmlno diretório diste adicionar um link para o pacote - <script src='index_bundle.js'></script>. Ótimo, não é? Uma vez que é index.htmlgerado HtmlWebpackPlugin, mesmo que mudemos o ponto de saída ou o nome do bundle, ele HtmlWebpackPluginreceberá essa informação e mudará o conteúdo index.html.
Como usamos este plugin? Como de costume, você precisa instalá-lo primeiro.
npm i html-webpack-plugin -D
Em seguida, adicione a propriedade às configurações do webpack
plugins.
const path = require('path')
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(js)$/, use: 'babel-loader' }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
},
plugins: []
}
Criamos uma instância
HtmlWebpackPluginem um array plugins.
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(js)$/, use: 'babel-loader' }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
]
}
EnvironmentPlugin
Se estiver usando o React, você desejará definir
process.env.NODE_ENVum valor productionantes de implantar o aplicativo. Isso permitirá que o React entre em produção, removendo ferramentas de desenvolvimento, como avisos. O pacote da web permite que você faça isso por meio de um plugin EnvironmentPlugin. Faz parte do webpack, portanto não é necessário instalá-lo.
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(js)$/, use: 'babel-loader' }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin(),
new webpack.EnvironmentPlugin({
'NODE_ENV': 'production'
})
]
}
Agora, em qualquer lugar em nosso aplicativo, podemos definir o modo de produção com
process.env.NODE_ENV.
HtmlWebpackPlugine EnvironmentPluginé apenas uma pequena parte do sistema de plug-ins do webpack.
Modo (modo)
No processo de preparação de um aplicativo para produção, há várias etapas a serem executadas. Acabamos de cobrir um deles - configuração
process.env.NODE_ENVpara valor production. Outra ação é reduzir o código e remover comentários para reduzir o tamanho do pacote.
Existem plug-ins especiais para resolver essas tarefas, mas existe uma maneira mais fácil. Nas configurações do webpack, ele pode ser definido
modecomo developmentou productiondependendo do ambiente de desenvolvimento.
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './app/index.js',
module: {
rules: [
{ test: /\.svg$/, use: 'svg-inline-loader' },
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(js)$/, use: 'babel-loader' }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
],
mode: 'production'
}
Observe que removemos
EnvironmentPlugin. O fato é que, após definir modeo valor, o productionwebpack atribui o process.env.NODE_ENVvalor automaticamente production. Também reduz o código e remove avisos.
Lançamento de um webpack
No momento que sabemos como funciona o webpack e como configurá-lo, resta executá-lo.
Temos um arquivo
package.jsonque podemos criar scriptpara rodar webpack.
"scripts": {
"build": "webpack"
}
Agora, ao executar o comando
npm run buildno terminal, um webpack será lançado, o que criará um pacote otimizado index_bundle.jse o colocará nele dist.
Modos de desenvolvimento e produção
Resumindo, terminamos com o webpack. Finalmente, vamos dar uma olhada em como alternar entre os modos.
Ao construir para produção, queremos otimizar tudo ao máximo. No caso do modo de desenvolvimento, o oposto é verdadeiro.
Para alternar entre os modos, você precisa criar dois scripts em
package.json.
npm run buildirá construir o pacote de produção.
npm run startiniciará o servidor de desenvolvimento e observará as alterações do arquivo.
Se você se lembra, definimos isso
modecomo um valor productionnas configurações do webpack. No entanto, não precisamos disso agora. Queremos que a variável de ambiente tenha um valor apropriado dependendo do comando que está sendo executado. Vamos mudar o script buildem package.json.
"scripts": {
"build": "NODE_ENV='production' webpack",
}
Se você tiver o Windows, o comando seria:
"SET NODE_ENV='production' && webpack".
Agora, nas configurações do webpack, podemos alterar o valor
modedependendo de process.env.NODE_ENV.
...
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'
}
Para construir um pacote pronto para nosso aplicativo, simplesmente o executamos
npm run buildno terminal. Os distarquivos de diretório são criados index.htmle index_bunlde.js.
Servidor de desenvolvimento
Quando se trata de desenvolver um aplicativo, a velocidade é essencial. Não queremos reiniciar o webpack e esperar por uma nova construção a cada mudança. É aqui que o pacote é útil
webpack-dev-server.
Como o nome sugere, este é um servidor webpack para desenvolvimento. Em vez de criar um diretório
dist, ele armazena dados na memória e os processa em um servidor local. Além do mais, ele suporta reinicialização ao vivo. Isso significa que qualquer alteração webpack-dev-serverreconstruirá os arquivos e reiniciará o navegador.
Instale o pacote.
npm i webpack-dev-server -D
Tudo o que resta a fazer é adicionar o script
startao package.json.
"scripts": {
"build": "NODE_ENV='production' webpack",
"start": "webpack-dev-server"
}
Agora temos dois comandos: um para iniciar o servidor de desenvolvimento e outro para construir o pacote concluído.
Espero que o artigo tenha sido útil para você. Obrigado pela atenção.