Infelizmente, não tenho tempo/entusiasmo para manter este projeto no momento. Eu recomendo bifurcar este projeto ou ler seu código-fonte para saber como ele foi construído.
Este padrão de webpack é para desenvolvedores iniciantes, intermediários e avançados que desejam criar sites estáticos rapidamente e, ao mesmo tempo, obter todas as otimizações certas para obter uma pontuação perfeita no Google Page Speed Insights e no Google Lighthouse Reports - esta é uma evolução do tris-gulp-boilerplate, agora com Webpack 4. Webpack é o novo padrão para empacotar JS do qual o Gulp não era capaz. Felizmente, o Webpack pode executar tarefas e agrupar js?
O objetivo deste projeto/padrão é atingir as seguintes pessoas:
Os iniciantes ? — que apesar de usarem Gulp/Webpack/Node/Npm ainda precisam de explicações mais completas do que os desenvolvedores mais familiarizados. Eles querem que as coisas funcionem, mas também querem saber como e por quê .
Os traficantes de projetos paralelos ?♀️ - aqueles com todas as grandes ideias, mas não querem perder tempo com configuração. Eles precisam colocar suas ideias, aplicativos e sites no navegador... rapidamente .
Os obsessivos compulsivos ♂️ - pessoas que adoram obter pontuações perfeitas em relatórios de desempenho e otimizações. Pessoas que são organizadas digitalmente e se orgulham de saber que todos os seus arquivos estão minimizados, compactados, compactados e prontos para envio!
Sinta-se à vontade para fazer um fork deste repositório e criar seu próprio fluxo de trabalho baseado neste modelo! Todo mundo é um pouco diferente, eu entendo.
Você precisa de git e node.js em seu computador antes de executar.
git clone https://github.com/tr1s/tris-webpack-boilerplate.git your-project-name
cd your-project-name && rm -rf .git
npm install
npm start
Está tudo pronto, comece a codificar ?? !
Remova tudo na pasta src/styles/
, src/index.html
e src/index.scss/
se quiser começar 100% do zero e/ou criar seu próprio fluxo de trabalho Sass. Baseei minha estrutura de pastas no padrão 7-1.
npm run build
quando estiver pronto para enviar seu site para a plataforma de FTP/hospedagem de sua escolha. Isso criará uma pasta dist
com todos os ativos do seu site otimizados e compactados.
Se você quiser uma explicação detalhada sobre como tudo funciona, leia sobre os recursos abaixo. Caso contrário, continue codificando e divirta-se :)
tris-webpack-boilerplate
Uso
Recursos / Conteúdo
Recursos explicados
Divisão de configuração do Webpack
Servidor de Desenvolvimento Webpack
Ativos HTML e minificação
404 página não encontrada
SCSS para CSS + otimizações
Transpilando ES6
Lista de navegadores
Ativos de imagem + compactação
Carregamento de fonte + pré-carregamento
Compactação de ativos
Plug-in Webpack limpo
Mapas de origem
Geração de favicon
Off-line primeiro e cache
Aplicativo Web Progressivo (PWA)
Te peguei
Contribuindo
Em vez de ter um grande webpack.config.js
, dividiremos nossas compilações de produção e desenvolvimento em duas novas configurações chamadas webpack.dev.js
e webpack.prod.js
. As configurações que desejamos tanto no desenvolvimento quanto na produção irão para a configuração webpack.common.js
.
Quando executamos npm start
, ele executará a compilação de desenvolvimento com base na configuração webpack.dev.js
, que também possui as configurações webpack.common.js
mescladas. Leia mais sobre isso na documentação do Webpack.
/* wenpack.dev.js */const merge = require("webpack-merge");const common = require("./webpack.common.js");/* mescla o webpack.common.js e então você adiciona seu extra */module.exports = merge(common, { modo: "desenvolvimento", /* o resto do código vai aqui */});
Quando executamos npm run build
, ele executará a compilação de produção com base na configuração webpack.prod.js
, que também possui as configurações webpack.common.js
mescladas.
/* webpack.prod.js */const merge = require("webpack-merge");const common = require("./webpack.common.js");/* mescla o webpack.common.js e então você adiciona seu extra */module.exports = merge(common, { modo: "produção",});
Queremos que nossas compilações de desenvolvimento e produção produzam os mesmos resultados visualmente no navegador. Você não quer terminar a codificação, executar a compilação e, em seguida, ter um site totalmente diferente em construção, com imagens ausentes, por exemplo. É por isso que temos webpack.common.js
para lidar com todos os carregadores e gerenciamento de ativos. O webpack.dev.js
será um pouco diferente com um mapa de origem mais leve. Por fim, o webpack.prod.js
cuidará de todas as etapas finais para colocar seu site em produção. Sendo compactação de imagem, compactação de ativos (gzip), minificação de ativos, geração de favicon, armazenamento em cache e criação de uma experiência offline.
Abordarei cada processo abaixo.
O webpack-dev-server está configurado no package.json. npm start
irá executar o servidor e abrir seu projeto no navegador usando a configuração webpack.dev.js
. npm start
é o script padrão do npm, então você não precisa adicionar run
a ele. Mas para o script de construção você precisa digitar npm run build
.
"scripts": { "start": "webpack-dev-server --open --config webpack.dev.js", "build": "webpack --config webpack.prod.js"},
Usamos o html-loader para exportar HTML como uma string e reduzir a saída. Isso permite que você importe seu src/index.html
dentro de seu src/index.js
. Podemos simplesmente minimizar o HTML com uma opção de carregamento minimize: true
, é por isso que o deixamos em webpack.common.js
em vez de movê-lo para webpack.prod.js
.
/* webpack.common.js */{ teste: /.html$/, use: [{loader: 'html-loader', opções: {minimizar: verdadeiro} }]},
/* src/index.js */import "./index.html";
Em seguida, usamos html-webpack-plugin para criar um novo index.html
gerado com todas as importações de ativos corretas.
A opção template:
é de onde você extrai seu HTML de origem. Você pode usar seu próprio modelo html, modelo de guiador ou qualquer um desses outros modelos.
A opção inject:
é para onde seus ativos irão. O Webpack colocará seu script webpack-bundle.js
incluído na parte inferior do corpo por padrão, mas aqui eu mudei para head
porque usaremos o script-ext-html-webpack-plugin para adicionar um atributo defer
ao script e coloque-o no cabeçalho do site. Isso ajuda no desempenho.
/* webpack.common.js */const HtmlWebpackPlugin = require('html-webpack-plugin');const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");plugins: [ novo HtmlWebpackPlugin ({título: 'tris-webpack-boilerplate', nome do arquivo: 'index.html', modelo: './src/index.html', injetar: 'head' }), novo HtmlWebpackPlugin ({título: 'tris-404-page', nome do arquivo: '404.html', modelo: './src/404.html', injetar: 'head' }), novo ScriptExtHtmlWebpackPlugin({defaultAttribute: 'defer' }),],
Continue adicionando new HtmlWebpackPlugin({})
se você pretende ter um site com várias páginas. Nomeie a página apropriadamente com o title:
chave.
Netlify é um serviço gratuito fantástico que permite gerenciar e implantar seus sites. O Netlify procura automaticamente um 404.html
e carrega essa página quando alguém tenta abrir um link quebrado em seu site. Então não há nada com que você se preocupar.
Se você usa um serviço diferente, faça uma pesquisa sobre como vincular sua página 404.html
para que ela fique ativa. É uma ótima maneira de direcionar as pessoas de volta à sua página principal caso elas acessem um link quebrado.
Para usar Sass/SCSS, precisamos usar alguns carregadores para obter os resultados desejados. O carregador css, o carregador postcss e o carregador sass.
test:
está usando regex (expressão regular) para verificar qualquer arquivo sass, scss ou css e, em seguida, executá-los por meio desses três carregadores, que são agrupados em torno do mini-css-extract-plugin, que então gera um único arquivo CSS para você para usar na produção.
Leia mais sobre o conceito de carregadeiras.
/* webpack.common.js */{ teste: /.(sa|sc|c)ss$/, use: [MiniCssExtractPlugin.loader,{loader: 'css-loader', opções: {sourceMap: true }},{ loader: 'postcss-loader', opções: {sourceMap: true }},{ loader: 'sass-loader ', opções: {sourceMap: true }} ]},
A segunda parte da sequência do carregador, o postcss-loader
, é onde você reduzirá e autoprefixará seu css. Para fazer isso criamos um postcss.config.js
na raiz do projeto e configuramos assim...
/* postcss.config.js */const purgecss = require("@fullhuman/postcss-purgecss");module.exports = { plugins: [require("autoprefixer"),require("cssnano")({ preset: "default",}),purgecss({ content: ["./**/*.html"], quadros-chave: true,} ), ],};
Leia sobre autoprefixer e cssnano para configurá-lo mais ao seu gosto, se necessário. Além disso, leia sobre o postcss em geral, pois é uma ferramenta muito poderosa para se ter em seu arsenal.
Purgecss é um plugin postcss fantástico para se livrar de CSS não utilizado em seu código. Purgecss analisa seu conteúdo e seus arquivos CSS. Em seguida, ele combina os seletores usados nos seus arquivos com os dos seus arquivos de conteúdo. Ele remove seletores não utilizados do seu css, resultando em arquivos css menores.
Ele está pronto para funcionar por padrão, mas se você quiser testá-lo visualmente, remova o comentário @import "../node_modules/bulma/bulma";
em index.scss
e, em seguida, execute npm run build
e dê uma olhada no webpack-bundle.css
resultante em sua pasta dist. Você notará que não há muito código. Em seguida, remova o purgecss do seu postcss.config.js
e execute npm run build
novamente, você notará que há mais de 10.000 linhas de código em seu css provenientes do framework Bulma. Como você pode ver, purgecss é perfeito para se livrar de CSS que você não está usando ao usar grandes frameworks como Bootstrap, Foundation, Bulma, etc!
O mini-css-extract-plugin é a etapa final, pois extrai o CSS e dá um nome a ele antes de ser gerado.
/* webpack.common.js */const MiniCssExtractPlugin = require("mini-css-extract-plugin");plugins: [ novo MiniCssExtractPlugin({nome do arquivo: 'webpack-bundle.css',chunkNome do arquivo: '[id].css' })],
Então, basicamente... o css-loader
coletará CSS de todos os arquivos css referenciados em seu aplicativo e os colocará em uma string. Em seguida, postcss-loader
autoprefixa e minimiza seus estilos, então sass-loader
o transforma em um módulo JS e, em seguida, mini-css-extract-plugin
extrai o CSS do módulo JS em um único arquivo CSS para o navegador da web analisar.
Você pode querer usar os recursos e sintaxe JavaScript mais recentes, mas nem todos os navegadores os suportam ainda. Babel cuidará disso para nós.
Aqui estamos testando todos os arquivos js, mas excluindo a pasta node_modules
e, em seguida, executando-o através do babel-loader com a predefinição babel-preset-env.
/* webpack.common.js */{ teste: /.js$/, excluir: /(node_modules)/, use: {loader: 'babel-loader',opções: {predefinições: ['@babel/preset-env']} }}
Desta vez estamos nos aventurando no arquivo webpack.prod.js
. Quando npm run build
, nossa saída js será reduzida e terá mapas de origem completos. Executando no modo dev via npm start
ainda teremos sourcemaps mais leves, mas o js não será minificado.
/* webpack.prod.js */const TerserPlugin = require("terser-webpack-plugin");module.exports = merge(common, { modo: "produção", devtool: "mapa de origem", otimização: {minimizador: [ new TerserPlugin({test: /.js(?.*)?$/i,parallel: true,sourceMap: true, }),], },});
Leia mais sobre as opções na documentação do Terser.
Aqui queremos ter um lugar onde possamos informar a certas ferramentas para quais navegadores gostaríamos de adicionar suporte. Conseguimos isso usando o browserslist e o arquivo .browserslistrc
correspondente na raiz do projeto. Autoprefixer e babel-present-env irão pegar este arquivo e aplicar o que for necessário com base na configuração.
Leia sobre o que mais você pode passar para .browserslistrc
e use browserl.ist para ver quais navegadores serão direcionados especificamente com sua configuração. Ok, acho que já disse navegadores várias vezes?
/* .browserslistrc */> 0,25% não morto
Primeiro testamos jpeg, jpg, png, gif e svg usando regex (expressão regular), depois usamos o file-loader, que resolve importações e requer um arquivo em um URL e emite o arquivo no diretório de saída. Portanto, se você estiver usando um elemento <img>
que captura um arquivo da pasta src/images
, ele será importado e emitido para o caminho de saída especificado images
. O que acaba sendo src/images
se você npm start
(executando dev) ou npm run build
(executando build).
/* webpack.common.js */{ teste: /.(jpe?g|png|gif|svg)$/, use: [{loader: 'file-loader', opções: { nome: '[nome].[ext]', outputPath: 'images/', publicPath: 'images/'}, }]},
Agora queremos apenas otimizar nossas imagens em npm run build
, então editamos nosso webpack.prod.js
como abaixo.
Novamente testamos jpeg, jpg, png, gif e svg usando regex e aplicamos as otimizações apropriadas. gifsicle
é um compressor gif sem perdas, pngquant
é um compressor png com perdas e podemos adicionar um plugin extra chamado imageminMozjpeg
para realizar compactação jpg/jpeg com perdas. Uma aposta segura é definir a qualidade entre 75-90 e você deverá obter uma compactação decente sem perda de qualidade visível.
Sugiro manter a compactação sem perdas e cortar suas imagens no tamanho certo antes de adicioná-las ao projeto. Basta remover as seções principais imageminMozjpeg e pngquant para fazer isso.
Você também pode usar o tinypng para compactação de imagens.
/* webpack.prod.js */const ImageminPlugin = require("imagemin-webpack-plugin").default;const imageminMozjpeg = require("imagemin-mozjpeg");plugins: [ new ImageminPlugin({test: /.(jpe?g|png|gif|svg)$/i,gifsicle: { // compressor gif sem perdas otimizaçãoLevel: 9,},pngquant: { // compressor png com perdas, remova para padrão sem perdas qualidade: "75",},plugins: [ imageminMozjpeg({// compressor jpg com perdas, remova para qualidade sem perdas padrão: "75", }),], }),];
Aqui estamos testando todas as extensões de fonte comuns e usando o carregador de arquivos novamente para resolver nossas importações de fontes e produzi-las.
/* webpack.common.js */{ teste: /.(woff|woff2|ttf|otf)$/, use: [{loader: 'file-loader', opções: {nome: '[nome].[ext]', outputPath: 'fonts/', publicPath: 'fonts/'}, }]},
Em nosso src/styles/base/_typography.scss
estamos carregando as fontes através da regra @font-face
. O Google Webfonts Helper também é uma ferramenta fantástica para auto-hospedar Google Fonts sem complicações. Leia mais sobre a regra @font-face
em truques CSS. Além disso, leia também a propriedade font-display.
É sempre uma boa prática pré-carregar suas fontes. Conseguiremos isso usando o preload-webpack-plugin, e você precisará colocá-lo logo após o HtmlWebpackPlugin
para que funcione corretamente.
/* webpack.common.js */new PreloadWebpackPlugin({ rel: 'pré-carregamento', as(entrada) {if (/.(woff|woff2|ttf|otf)$/.test(entrada)) return 'fonte'; }, lista de permissões de arquivo: [/.(woff|woff2|ttf|otf)$/], incluem: 'allAssets'}),
Aqui estamos de volta à configuração do webpack.prod.js
usando o plugin compression-webpack para compactar apenas os arquivos html, css e javascript. Isso evita a compactação dos arquivos do mapa de origem gerados.
/* webpack.prod.js */module.exports = merge(common, { modo: 'produção', plugins: [new CompressionPlugin({ test: /.(html|css|js)(?.*)?$/i // apenas html/css/js compactado, ignora a compactação de mapas de origem, etc.}),});
Clean-webpack-plugin é apenas um plugin simples de webpack para remover/limpar sua(s) pasta(s) de construção antes de construir uma nova. Observe a estrutura da sua pasta enquanto você executa npm run build
ou npm start
. Sua pasta dist
atual (se você já tiver uma criada) será excluída e uma nova aparecerá imediatamente depois.
/* webpack.common.js */const CleanWebpackPlugin = require("clean-webpack-plugin");plugins: [new CleanWebpackPlugin(["dist"])];
Usar mapas de origem é essencial para depurar seu código nas ferramentas de desenvolvimento.
Como você pode ver quando você npm start
e abre o devtools no Chrome e clica no console, você verá que há dois console.logs vindos das linhas 1 e 2 script.js
Podemos ver isso facilmente em nossa estrutura de pastas em src/scripts/script.js
. Se não usássemos mapas de origem, os devtools nos mostrariam que esses console.logs vêm de nosso pacote webpack-bundle.js
, o que não é muito útil.
Caso semelhante com nossos estilos. Se você der uma olhada no elemento body
no devtools, verá alguns estilos sendo aplicados em nosso arquivo _global.scss
e alguns em nosso arquivo _typography.scss
, ambos localizados em nossa pasta src/styles/base/
. Não seríamos capazes de saber isso se deixássemos de fora os mapas de origem. Isso apenas nos mostraria os estilos que vieram de nosso pacote webpack-bundle.css
.
/* webpack.dev.js */module.exports = merge(common, { modo: "desenvolvimento", devtool: "mapa de origem embutido",});
/* webpack.prod.js */module.exports = merge(common, { modo: "produção", devtool: "mapa de origem",});
Leia mais sobre os diferentes tipos de mapas de origem para descobrir o que funciona melhor para o seu projeto. Além disso, leia sobre a opção devtool nos documentos do webpack.
Este é um ótimo plugin que gera todos os ícones que você precisa com base em uma fonte de imagem. Na minha pasta src/images/
eu tenho um tris-package.svg
que insiro no favicons-webpack-plugin.
Ele irá gerar ícones para apple, android, chrome, firefox, twitter, windows, o que você quiser. Ele irá gerar cada ícone em todos os tamanhos diferentes e importá-los diretamente para o cabeçalho do seu site, onde eles pertencem. O Twitter e o Windows estão definidos como falsos, mas padrão, então os alterei para verdadeiros apenas para cobrir todas as bases, por precaução.
Nota: isso aumenta drasticamente o tempo de construção. O que é compreensível, considerando o quanto isso está fazendo nos bastidores e quanto tempo está economizando no longo prazo. Não se surpreenda se a npm run build
demorar 20 segundos a mais que o normal.
/* webpack.prod.js */const FaviconsWebpackPlugin = require("favicons-webpack-plugin");module.exports = merge(common, { modo: "produção", plug-ins: [novos FaviconsWebpackPlugin ({ logo: "./src/images/favicon.svg", ícones: {twitter: true, windows: true, },}), ],});
Aqui usamos o plugin offline para armazenar em cache todos os nossos ativos no carregamento da página.
Este plugin tem como objetivo fornecer uma experiência offline para projetos webpack . Ele usa ServiceWorker e AppCache como substituto nos bastidores. Simplesmente incluímos este plugin em nosso webpack.prod.js
e o tempo de execução que o acompanha em nosso script de cliente (src/index.js), e nosso projeto ficará pronto para uso offline armazenando em cache todos (ou alguns) os ativos de saída do webpack.
Nota: Se você npm run build
e carregar suas alterações em seu servidor (ou mesmo assim mantiver seu site atualizado), seu site precisará ser fechado e reaberto antes de você ver as alterações. Você não pode abri-lo e continuar atualizando, você precisa fechar a guia e reabri-la para que o cache seja interrompido.
/* webpack.prod.js */const OfflinePlugin = require("plugin-offline");module.exports = merge(common, { modo: "produção", plug-ins: [novo OfflinePlugin()],});
Aplicativos da web progressivos (PWAs) são aplicativos da web que carregam como páginas da web ou sites normais, mas podem oferecer ao usuário funcionalidades como trabalho offline, notificações push e acesso ao hardware do dispositivo tradicionalmente disponível apenas para aplicativos nativos. Os PWAs combinam a flexibilidade da web com a experiência de um aplicativo nativo.
A etapa final para tornar este modelo um PWA é adicionar o manifesto de aplicativo da Web obrigatório à raiz do seu projeto e configurá-lo adequadamente!
O Webpack enfrenta problemas ao tentar agrupar grandes bibliotecas como jQuery. Você acabará com erros de console como $ is not defined
ou jQuery is not defined
. Para resolver isso deixamos o Webpack tratá-lo como externo. Em seguida, definimos as variáveis e incluímos o jQuery por meio de um CDN. A maioria das pessoas tem o jQuery armazenado em cache no navegador, portanto isso não será um problema em termos de desempenho. Eu adicionei o externals:
config por padrão, mas você mesmo terá que adicionar o cdn do jQuery se planeja usá-lo.
Leia mais sobre externos na documentação do Webpack.
/* webpack.common.js */plugins: [],externos: { $: 'jquery', jquery: 'jQuery', 'janela.$': 'jquery',}
/* src/index.html */<head> <scriptdefersrc="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" </script></head>
Eu tento o meu melhor para explicar as coisas completamente, mas se algo puder ser explicado com mais clareza, sinta-se à vontade para enviar uma solicitação pull com algumas sugestões de edições. Obrigado!
Espero que isso tenha ajudado! Siga-me no Twitter se você gosta disso. ?