Pokračování článku Webpack - krok za krokem
6. Loadery a pluginy
Nyní se budeme zabývat tím, co webpack může udělat automaticky prostřednictvím některých konfigurací.
6.1. Loadery
Webpack umožňuje použití loaderů k průběžnému zpracování souborů. To umožní sdružovat libovolný statický zdroj mimo JavaScript. Vzhledem k tomu, že webpack stále neví, co dělat s těmito loadery, webpack config objekt používá module
vlastnost, aby zjistil, jaký loader má fungovat a jak je provádět.
module
vlastnost samotného config
objektu jeho objektem. Pracuje s některými dalšími možnostmi uvedenými níže:
# module.noParse
Zabraňuje zpracování webových souborů z libovolného souboru odpovídající danému datu RegExp
. Ignorované soubory by neměly být volány pro import, požadavek, definici nebo jakýkoli jiný mechanismus importu. To může zvýšit výkon při ignorování velkých knihoven.
module: {
noParse: /jquery|lodash/
}
# module.rules
Každý loader se nastavuje jako soubor pravidel uvnitř array
. Zatímco každý prvek tohoto pole je předmětem obsahujícím jednotlivé loadery a jejich příslušné konfigurace.
Pravidlo lze rozdělit na tři části - Podmínky, Výsledky a Vnořená pravidla.
1. Podmínky: Existují dvě vstupní hodnoty pro podmínky
a. Zdroj: Absolutní cesta k požadovanému souboru.
b. Vydavatel: Umístění importu.
V pravidle vlastností test
, include
, exclude
a resource
jsou porovnány se zdrojem a vlastnosti issuer
je uzavřeno s vydavatelem.
2. Výsledky: Používají pouze tehdy, když se shoduje podmínka Pravidla. Existují dvě výstupní hodnoty pravidla:
a. Použité loadery: Množina loaderů použitých na prostředek.
b. Možnosti parseru: Objekt voleb, který by měl být použit k vytvoření parseru pro tento modul.
3. Vnořená pravidla: V rámci vlastností rules
a oneOf
. Tato pravidla jsou vyhodnocována, když se splňuje podmínka Pravidla.
Teď jednoduššejí :)
Loader potřebuje některé další informace, aby v modulu fungoval správně a efektivně. Uvádíme je module.rules
s některými konfiguračními parametry.
test:
(povinné) Loader musí vědět, s jakou příponou bude pracovat. definujeme pomocí RegExp
.
test: /\.js$/
include:
(volitelně) Loader potřebuje adresář, aby zjistil, kde jsou uloženy pracovní soubory.
include: /src/
exclude:
(volitelně) Můžeme ušetřit spoustu nežádoucích procesů - nechceme analyzovat moduly uvnitř adresáře node_modules
a ušetříme spoustu paměti a času provádění.
exclude: /node_modules/
use:
(požadováno) Pravidlo musí mít vlastnost loader
, která je řetězecem. Uvedete loadery, které chcete použít pro daný úkol. Loadery mohou být řetězeny složením více loaderů, které budou aplikovány zprava doleva (poslední nakonfigurované).
Může mít vlastnost options
, která je řetězcem nebo objektem. Tato hodnota je předána loaderu, který by ji měl interpretovat načtením.
Pro kompatibilitu je také možné použít vlastnost query
, což je alias vlastnosti property. Použijte options
místo property.
use: {
loader: "babel-loader",
options: {
presets: ['env']
}
}
Detail konfigurace module.rules
: https://webpack.js.org/configuration/module/#module-rules
6.2. Plguiny
Možnost plugins
se používá k přizpůsobení procesu vytváření webového balíčku. Webpack je dodáván s řadou vestavěných pluginů dostupných pod webpack.[plugin-name]
Webpack má v konfiguračním objektu vlastnost plugins
pro konfiguraci pluginu.
7. Některé LOADERY a PLUGINY v akci
7.1. clean-webpack-plugin (PLUGIN)
Pokaždé, když chceme vidět naši produkční dist
složku, je třeba ji vymazat. clean-webpack-plugin
provádí odstranění / čištění složek sestavení před buildováním. Nastavení je velmi snadné:
Instalovat přes npm
> npm i -D clean-webpack-plugin
Import do souboru webpack.config.js
const CleanWebpackPlugin = vyžaduje ('clean-webpack-plugin');
Nyní budeme poprvé používat plugin. Webpack má v objektu config
nastavení konfigurace pluginu. Každý plugin potřebuje vytvořit instanci, která bude použita v objektu config. Takže definování ve vlastnostech je následující:
plugins: [
new CleanWebpackPlugin(['dist'])
]
Zde jsme v příkladu clean-webpack-plugin
zmínili dist
jako prvek pole. Webpack nyní ví, že chceme vyčistit / odstranit složku dist
pokaždé před buildováním našeho balíčku. Tato instance může mít více adresářů / cest jako prvků pole a více možností jako objekt.
Syntaxe pro použití clean-webpack-webpack:
plugins: [
new CleanWebpackPlugin(paths [, {options}])
]
Měli byste sledovat proces odstranění a vytváření vašeho adresáře živě a také ve vašem IDE.
Nyní bude webpack.config.js vypadat následovně:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const config = {
context: path.resolve(__dirname, 'src'),
entry: {
// removing 'src' directory from entry point, since 'context' is taking care of that
app: './app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './assets/js/[name].bundle.js'
},
plugins: [
new CleanWebpackPlugin(['dist'])
],
devServer: {
contentBase: path.resolve(__dirname, "./dist/assets/media"),
compress: true,
port: 12000,
stats: 'errors-only',
open: true
},
devtool: 'inline-source-map'
}
module.exports = config;
7.2. babel-loader (LOADER)
Všichni chceme napsat nějaký kód ES2015 / ES6, ne? Ale až dosud náš prohlížeč není plně schopný interpretovat syntaxi ES6, musíme nejprve přenést náš ES6 kód do ES5 a pak ho použít v našem balíčku. Babel přebírá tuto odpovědnost za nás. Prostě potřebujeme do naší konfigurace zahrnout babel-loader
, který bude dělat za nás několik jednoduchých kroků.
Nainstalujte babel-loader
> npm i -D babel-core babel-loader
Vytvořte soubor .babelrc
v kořenovém adresáři projektu, abyste povolili některé přednastavení babel (již jsme to udělali v části nastavení projektu. Již jej najdete v kořenovém adresáři projektu)
Nainstalujte jej babel-preset-env
pro kompilaci závislou na prostředí
> npm i -D babel-preset-env
Chcete-li povolit přednastavení, musíte jej definovat ve vašem souboru .babelrc
, například takto:
{
"presets": ["env"]
}
Toto lze také dát také do souboru package.json, potom není nutné .babelrc
.
"scripts": {
"babel": {
"presets": ["env"]
}
}
Tato vlastnost lze vložit do příslušného modulu v konfiguračním souboru
module: {
rules: [
{
test: /\.js$/,
include: /src/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['env']
}
}
}
]
}
Z našeho zavaděče víme, že:: test
nechá loader zjistit, se kterými formáty bude pracovat include
:nechá loader zjistit, do kterého adresáře bude ukládat exclude
:nechá loader zjistit, kterému adresář by se měl vyhnout při parsování use
: nechá loader zjistit, s jakým konkrétním loaderem používá use.loader
a s jakými konfiguračními možnostmi use.options
Webpack konfigurační soubor:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const config = {
context: path.resolve(__dirname, 'src'),
entry: {
// removing 'src' directory from entry point, since 'context' is taking care of that
app: './app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './assets/js/[name].bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
include: /src/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['env']
}
}
}
]
},
plugins: [
new CleanWebpackPlugin(['dist'])
],
devServer: {
contentBase: path.resolve(__dirname, "./dist/assets/media"),
compress: true,
port: 12000,
stats: 'errors-only',
open: true
},
devtool: 'inline-source-map'
}
module.exports = config;
Konfigurace v .babelrc
{
"presets": ["env"]
}
7.3. html-loader (LOADER) a html-webpack-plugin (PLUGIN)
Protože chceme upravit dotazy index.html
v src
adresáři a chceme vidět změny ve výstupním dist
adresáři, musíme vytvořit a aktualizovat index.html do dest pokaždé, když webpack provede build náš projekt.
Pro vyřešení našeho problému potřebujeme společně použít loader a plugin. Protože - html-loader
: Exportuje HTML jako řetězec. HTML je minimalizováno, když to překladač požaduje. html-webpack-plugin
: Zjednodušuje vytváření souborů HTML, které budou sloužit vašim svazkům webpacku.
Instalace závislostí
> npm i -D html-loader html-webpack-plugin
Konfigurace html-loader
{ test: /\.html$/, use: ['html-loader']
Import html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
Použití pluginu
plugins: [
new HtmlWebpackPlugin({
template: 'index.html'
})
]
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
context: path.resolve(__dirname, 'src'),
entry: {
// removing 'src' directory from entry point, since 'context' is taking care of that
app: './app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './assets/js/[name].bundle.js'
},
module: {
rules: [
//babel-loader
{
test: /\.js$/,
include: /src/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['env']
}
}
},
//html-loader
{ test: /\.html$/, use: ['html-loader'] }
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
//html-webpack-plugin instantiation
new HtmlWebpackPlugin({
template: 'index.html'
})
],
devServer: {
contentBase: path.resolve(__dirname, "./dist/assets/media"),
compress: true,
port: 12000,
stats: 'errors-only',
open: true
},
devtool: 'inline-source-map'
}
module.exports = config;
Teď je nastavena každá věc. Ve svém src/index.html
můžeme něco psát a pak spustit příkazy pro sestavení npm run dev
: Uvidíte, že naše aplikace nyní funguje a můžete vidět html prvek v prohlížeči. Vložený soubor js byl vložen do html před koncem značky body npm run build:prod
: Sledujte proces vytváření výstupu index.html a změny použité v dist / index.html
Zdroje:
html-loader: webpack-doc, github-doc
html-webpack-plugin: webpack-doc, github-doc
7.4. css-loader (LOADER), style-loader (LOADER), sassloader (LOADER), extract-text-webpack-plugin (PLUGIN)
Použití CSS a SASS s webovým balíčkem může vypadat jako nějaký další problém s některými dalšími kroky. Webpack zkompiluje css a tlačí kód do balíčku js. Ale potřebujeme jej extrahovat ze svazku a poté vytvořit stejný .css soubor a pak ho zasunout do našeho dist/index.html
a pak přidat css do DOM. Ne doslovně.
Zkombinujme 3 loadery a jeden plugin, aby jsme je viděli společně pracovat na požadovaném výstupu: style-loader
Přidá CSS do DOM vložením < style >
značky css-loader
: Interpretuje @import a url() pomocí import/require() sass-loader
: Načte soubor SASS/SCSS a zkompiluje ho do CSS node-sass
: Poskytuje vazbu pro Node.js do LibSass. Sass-loader vyžaduje node-sass a webpack jako peerDependency. Tímto způsobem můžete přesně řídit verze.extract-text-webpack-plugin
: Extrahujte text ze svazku nebo svazků do samostatného souboru.
Instalace závislostí
> npm i -D sass-loader node-sass css-loader style-loader extract-text-webpack-plugin
Musíme importovat naše app.scss
do naší app.js
, abychom nechali webpack vědět o závislostech. Takže v našem app.js
budeme psát:
import './assets/scss/app.scss';
Kromě toho zkontrolujte, zda naše moduly sass fungují dobře, přidejte ještě jeden soubor .scss do našeho src/assets/scss
adresáře přes terminal
> touch src/assets/scss/_colors.scss
Importujte nově vytvořený _color.scss
soubor app.scss
a přidejte styl s:
@import '_colors';
body {
background: $bgcolor;
}
a definujte $bgcolor v souboru _color.scss:
$bgcolor : #e2e2e2;
Importujte extract-text-webpack-plugin
do konfiguračního souboru
const ExtractTextPlugin = require('extract-text-webpack-plugin');
Musíme importovat webpack
do našeho webpack.config.js
pro použití pluginu:
const webpack = require('webpack');
Nyní se náš pracovní postup rozděluje na dva typy požadavků.
(1) Chceme mít pouze jeden .css soubor do našeho výstupu
(2) Chceme více než jeden .css soubory jako výstup
Pro jeden stylový soubor (pracujeme takto):
Nejprve musíme vytvořit instanci, ExtractTextPlugin
, do které budeme definovat náš výstupní název souboru:
const extractPlugin = new ExtractTextPlugin({
filename: './assets/css/app.css'
});
Zadruhé, při konfiguraci našich loaderů css/sass musíme použít dříve vytvořenou instanci s její extract()
metodou (tj. extractPlugin.extract()
) A uvnitř metody předáme požadované loadery jako argument ve formě objektu.
Takže naše konfigurace těchto loaderů bude:
{
test: /\.scss$/,
include: [path.resolve(__dirname, 'src', 'assets', 'scss')],
use: extractPlugin.extract({
use: ['css-loader', 'sass-loader'],
fallback: 'style-loader'
})
}
Nyní přídáme instanci z ExtractTextPlugin
(která je extractPlugin
) uvnitř sekce plugins
:
plugins: [
extractPlugin
]
Jestliže nebudeme používat plugin html-loader, můžeme použít klasický způsob načtení js a css souborů:
<link rel="stylesheet" href="./assets/app.css">
<script src="./assets/main.bundle.js"></script>
Pro více stylů (pouze pro příklady):
Práce s více styly není noc nového, protože se vychází z předchozích znalostí pro jediný styl.
Stačí vytvořit tolik instancí, ExtractTextPlugin
kolik chcete, podle počtu stylových souborů. Vytváříme zde dvě instance, jednu pro css a jednu pro kompilovanou sass
const extractCSS = new ExtractTextPlugin('./assets/css/[name]-one.css');
const extractSASS = new ExtractTextPlugin('./assets/css/[name]-two.css');
Loadery budou vypadat:
{ test: /\.css$/, use: extractCSS.extract([ 'css-loader', 'style-loader' ]) },
{ test: /\.scss$/, use: extractSASS.extract([ 'css-loader', 'sass-loader' ], fallback: 'style-loader') }
Přidání instancí do pluginu:
plugins: [
extractCSS,
extractSASS
]
Nyní jej spusťte npm run dev
pro zobrazení ve vašem prohlížeči.
Pro zobrazení případných debugovacích chyb, zavedeme do zdrojové mapy sourceMap:true.
{
test: /\.scss$/,
include: [path.resolve(__dirname, 'src', 'assets', 'scss')],
use: extractPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
],
fallback: 'style-loader'
})
}
Ověřte zda se provedly změny ve stylech a zobraste si výsledek v prohlížeči.
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpack = require('webpack');
const extractPlugin = new ExtractTextPlugin({ filename: './assets/css/app.css' });
const config = {
context: path.resolve(__dirname, 'src'),
entry: {
app: './app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './assets/js/[name].bundle.js'
},
module: {
rules: [
//babel-loader
{
test: /\.js$/,
include: /src/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['env']
}
}
},
//html-loader
{ test: /\.html$/, use: ['html-loader'] },
//sass-loader
{
test: /\.scss$/,
include: [path.resolve(__dirname, 'src', 'assets', 'scss')],
use: extractPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
],
fallback: 'style-loader'
})
}
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: 'index.html'
}),
extractPlugin
],
devServer: {
contentBase: path.resolve(__dirname, "./dist/assets/media"),
compress: true,
port: 12000,
stats: 'errors-only',
open: true
},
devtool: 'inline-source-map'
}
module.exports = config;
7.5. Souborový loader (LOADER)
Máne nastavenou konfiguraci pro každou věc kromě statických souborů, jako jsou obrázky, písma. Nyní si nastavíme statické soubory s velmi užitečným načítáním file-loader
Nainstalujte zavaděč souborů
> npm i -D file-loader
Konfigurace file-loader
{
test: /\.(jpg|png|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: './assets/media/',
publicPath: './assets/media/'
}
}
]
}
Nemusíme přidávat publicPath a přidáme načítání souborů s fonty:
//file-loader(for images)
{
test: /\.(jpg|png|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: './assets/media/'
}
}
]
},
//file-loader(for fonts)
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
}
Pomocí loaderu konfigurujeme umístění fontů, které můžete importovat pomocí deklarace @font-face
. Do souboru kaskádového stylu vložte:
@font-face {
font-family: 'MyFont';
src: url('./my-font.woff2') format('woff2'),
url('./my-font.woff') format('woff');
font-weight: 600;
font-style: normal;
}
Nyní přidejte obrázky do adresáře src/assets/media
a vytvořte element img
v souboru src/index.html
.
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpack = require('webpack');
const extractPlugin = new ExtractTextPlugin({ filename: './assets/css/app.css' });
const config = {
context: path.resolve(__dirname, 'src'),
entry: {
app: './app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: './assets/js/[name].bundle.js'
},
module: {
rules: [
//babel-loader
{
test: /\.js$/,
include: /src/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['env']
}
}
},
//html-loader
{ test: /\.html$/, use: ['html-loader'] },
//sass-loader
{
test: /\.scss$/,
include: [path.resolve(__dirname, 'src', 'assets', 'scss')],
use: extractPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
],
fallback: 'style-loader'
})
},
//file-loader(for images)
{
test: /\.(jpg|png|gif|svg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: './assets/media/'
}
}
]
},
//file-loader(for fonts)
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
}
]
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: 'index.html'
}),
extractPlugin
],
devServer: {
contentBase: path.resolve(__dirname, "./dist/assets/media"),
compress: true,
port: 12000,
stats: 'errors-only',
open: true
},
devtool: 'inline-source-map'
}
module.exports = config;
Spusťte npm run dev
a npm run build:prod
a ověřte si jak vše funguje.