Konfiguracja Webpack 5 (sass, javascript ES6) na potrzeby projektu front-end
W celu usprawnienia pracy w środowisku Windows posłużymy się module bundler Webpack 5 czyli pakietem modułów łączącym, przekształcającym i pakującym moduły w jeden plik wynikowy pakietu JavaScript automatycznie umieszczanym w nagłówku strony internetowej.
Aby rozpocząć pracę z narzędziem Webpack 5 należy zainstalować Node.js (środowisko uruchomieniowo-wykonawcze JavaScript) z automatycznie instalowanym npm (pozwalającym instalować i odinstalowywać
pakiety i ich zależności – loadery, pluginy). Webpack parsuje (analizuje) kod plików wejściowych (ang. Entry Points) zawartych w pliku konfiguracyjnym webpack.config.js i buduje wykres zależności na podstawie pliku package.json. W ten sposób automatyzuje, optymalizuje zadania np. kompilując Sass do CSS, transpilując ES6+ do ES5 zrozumiałego dla przeglądarek, itd. Ma też na celu tworząc jeden plik wynikowy ograniczenie liczby żądań podczas ładowania kodu co poprawia wydajności takiej strony, aplikacji internetowej.
W Node.js każdy plik jest traktowany jako osobny moduł.
Node.js obsługuje dwa systemy modułów: moduły CommonJS i moduły ECMAScript, czyli zestaw standardów używanych do implementacji modułów JavaScript:
- Standard ECMAScript Modules poprzez użycie instrukcji import i export.
- Standard CommonJS modules poprzez funkcje require() i module.exports, nie obsługujący przeglądarek internetowych, głównie używany z Node w aplikacjach JavaScript po stronie serwera.
W pierwszym kroku zaczynamy od instalacji Node.js:
https://nodejs.org/en > Download for Windows (x64) 18.16.0 LTS Recommended For Most Users
Pobieramy a następnie instalujemy plik node-v18.16.0-x64.msi.
Sprawdzamy zainstalowane wersje poprzez:
cmd (Wiersz polecenia Windows) lub Git Bash Here (Powłoka terminalowa dla Windows,
zapewnia warstwę emulacji dla obsługi wiersza poleceń Git), z której będziemy korzystać w tym projekcie. Jeżeli nie mamy to musimy najpierw zainstalować Git: https://git-scm.com/.
node -v # v18.16.0
npm -v # 9.5.1
W tym projekcie zostaną wykorzystane:
- webpack webpack-cli
- html-webpack-plugin
- webpack-dev-server
- copy-webpack-plugin
- sass sass-loader style-loader css-loader
- postcss-loader postcss autoprefixer
- css-minimizer-webpack-plugin
- babel-loader @babel/core @babel/preset-env
- terser-webpack-plugin
- clean-webpack-plugin
Końcowa struktura katalogów i plików projektu starter-webpack-5, która posłuży nam za bazę startową do pracy nad projektem front-end będzie wyglądać następująco:
- /dist (aplikacja wynikowa)
- dog-paw-heart.jpg
- dog-paw-heart.png
- dog-paw-heart.webp
- /images
- bundle.min.js
- bundle.min.js.LICENSE.txt
- bundle.min.js.map
- index.html
- /src
- dog-paw-heart.jpg
- dog-paw-heart.png
- dog-paw-heart.webp
- app.js
- index.js
- main.scss
- /images
- /javascript
- /scss
- index.html
- /webpack
- /node_modules
- package-lock.json
- package.json
- webpack.config.js
- LICENSE
- README.md
Po przejściu do wybranego miejsca, w którym będziemy tworzyć nasz projekt otwieramy prawym przyciskiem myszy menu kontekstowe w Windows klikając w Git Bash Here i tworzymy główny katalog projektu z podstawowym zapleczem plików:
mkdir starter-webpack-5 # utworzenie katalogu
cd starter-webpack-5 # przejście do katalogu
pwd # sprawdzenie ścieżki /starter-webpack-5
code . # otwarcie projektu w edytorze VSCode
VSCode > Terminal > New Terminal # otwarcie terminala bezpośrednio w VSCode > bash
mkdir src # utworzenie katalogu źródła zasobu
cd src # przejście do katalogu
touch index.html # utworzenie pliku
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Starter Webpack 5 for front-end project</title>
</head>
<body>
<h1>Webpack 5 for front-end application configuration</h1>
<ol>
<li>webpack webpack-cli</li>
<li>html-webpack-plugin</li>
<li>webpack-dev-server</li>
<li>copy-webpack-plugin</li>
<li>sass sass-loader style-loader css-loader</li>
<li>postcss-loader postcss autoprefixer</li>
<li>css-minimizer-webpack-plugin</li>
<li>babel-loader @babel/core @babel/preset-env</li>
<li>terser-webpack-plugin</li>
<li>clean-webpack-plugin</li>
</ol>
</body>
</html>
mkdir javascript # utworzenie katalogu
cd javascript # przejscie do katalogu
touch index.js # utworzenie pliku
Dla testu do index.js wpisujemy przykładowy kod JavaScript:
document.querySelector("h1").style.color = "#00FFFF";
document.addEventListener("click", function () {
document.querySelector("h1").innerHTML = "TEST JavaScript";
});
W index.html dopisujemy ścieżkę przed </head>:
<script defer src="./javascript/index.js"></script>
Sprawdzamy poprawność wyświetlania kodu HTML z JavaScript otwierając w przeglądarce plik index.html. Nagłówek h1 został wyświetlony w kolorze aqua, a po kliknięciu w nagłówek zostaje zmieniona treść tekstu.
cd .. # wyjście z folderu javascript
cd .. # wyjście z folderu src
pwd # katalog główny projektu /starter-webpack-5
mkdir webpack # utworzenie katalogu
cd webpack # przejście do katalogu
pwd # sprawdzenie ścieżki /starter-webpack-5/webpack
Konfigurację projektu rozpoczynamy od stworzenia pliku package.json odnotowującego opis wszystkich zależności.
Będąc w katalogu webpack inicjujemy nasz projekt:
npm init (z ustawianiem) || npm init -y (bez ustawiania)
w czego rezultacie powstaje właśnie ten plik package.json.
Z ustawieniami:
npm init ENTER # konfigurowanie, zainicjowanie pakietu, opisu zależności projektu
package name: (webpack) starter-webpack-5 ENTER
version: (1.0.0) ENTER
description: Starter Webpack 5 for front-end application ENTER
entry point: (index.js) ENTER
test command: ENTER
git repository: https://github.com/AnesseL/starter-webpack-5 ENTER
keywords: webpack javascript js es6 css sass scss ENTER
author: Agnieszka Leśków ENTER
license: (ISC) MIT ENTER
yes ENTER
package.json
{
"name": "starter-webpack-5",
"version": "1.0.0",
"description": "Starter Webpack 5 for front-end application",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/AnesseL/starter-webpack-5.git"
},
"keywords": [
"webpack",
"javascript",
"js",
"es6",
"css",
"sass",
"scss"
],
"author": "Agnieszka Leśków",
"license": "MIT",
"bugs": {
"url": "https://github.com/AnesseL/starter-webpack-5/issues"
},
"homepage": "https://github.com/AnesseL/starter-webpack-5#readme"
}
Bez ustawienia:
npm init -y # -y === yes - ustawia w package.json wartości domyślne
package.json
{
"name": "starter-webpack-5",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
}
Podczas pracy nad konfiguracją projektu, instalacji różnych zależności określamy status zapisu paczek przeznaczonych dla wersji deweloperskiej lub produkcyjnej.
-D === –save-dev === „devDependencies” – to status zależności developerskiej, są to paczki używane tylko dla developmentu. Podczas pracy nad projektem, stosujemy je tylko do budowania wersji deweloperskiej w większości składającej się z wtyczek (ang. plugins) a także ładowarek, wczytywarek (ang. loaders). Przekształcają one różne typy plików nie obsługiwanych domyślnie przez Webpack w moduły na użytek projektu) i nie są później dołączane do kodu produkcyjnego.
Natomiast „Dependencies” – to status zależności do budowania wersji produkcyjnej, w jego skład wchodzą m.in. biblioteki np. jQuery, respond.js, normalize.css, itd..
Zaczynamy instalowanie paczek lokalnie od bazy, która będzie tym zawiadywać:
npm i webpack webpack-cli -D
npm uninstall webpack webpack-cli # usunięcie stosujemy tylko wtedy gdy coś będziemy chcieli usunąć
webpack – to bundler, pakowacz, transpilator JS, potrafi spakować wiele różnych formatów do jednego pliku wynikowego JavaScript
webpack-cli – interfejs wiersza polecenia pakietu webpack, klient webpack
W tym procesie instalacji powstał katalog z pakietami: node_modules i plik package-lock.json
package.json
{
"name": "starter-webpack-5",
"version": "1.0.0",
"description": "Starter Webpack 5 for front-end application",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/AnesseL/starter-webpack-5.git"
},
"keywords": [
"webpack",
"javascript",
"js",
"es6",
"css",
"sass",
"scss"
],
"author": "Agnieszka Leśków",
"license": "MIT",
"bugs": {
"url": "https://github.com/AnesseL/starter-webpack-5/issues"
},
"homepage": "https://github.com/AnesseL/starter-webpack-5#readme",
"devDependencies": {
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1"
}
}
W tym samy katalogu webpack tworzymy plik konfiguracyjny:
touch webpack.config.js # utworzenie pliku konfiguracyjnego
webpack.config.js – to moduł Node.js wymaga użycia Standard CommonJS modules
poprzez funkcje require() i module.exports, a wszystko czego nie wpiszemy do tego pliku przyjmie wartość domyślną. Więc wpisujemy podstawowe ustawienia.
webpack.config.js
const path = require('path'); //podstawowy moduł Node.js
module.exports = {
mode: 'development', //Określone --mode dla skryptu
entry: path.resolve(__dirname, '../src/javascript/index.js'), //Domyślny punkt wejscia
output: {
path: path.resolve(__dirname, '../dist'), //Punkt wyjścia
filename: 'bundle.js',
}
};
A w pliku package.json konfigurujemy rozruch:
package.json
"scripts": {
"dev": "webpack",
"watch": "webpack --watch",
"prod": "webpack --mode production"
},
Po zainstalowaniu bazy najlepszym i najprostszym rozwiązaniem będzie zainstalowanie wtyczki html-webpack-plugin aby móc sprawdzić poprawność wyświetlania kodu HTML z JS.
Podczas pracy nad tym projektem należy pamiętać aby każda instalacja i rozruch odbywały się w folderze webpack.
cd webpack # przejście do folderu jeżeli jesteśmy w innym miejscu
npm i html-webpack-plugin -D
npm uninstall html-webpack-plugin # usunięcie
html-webpack-plugin – webpack podczas procesu pakowania automatycznie i dynamiczne generuje w katalogu wynikowym /dist plik .html wstrzykując w nagłówek strony internetowej link do zasobu:
<script defer src="bundle.js"></script></head>
package.json
"devDependencies": {
"html-webpack-plugin": "^5.5.1",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1"
}
Aby ta wtyczka mogła zacząć spełniać swoje zadania musimy ją wskazać w pliku konfiguracyjnym:
const HtmlWebpackPlugin = require('html-webpack-plugin') //import pluginu
i
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../src/index.html'
})
]
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/javascript/index.js'),
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../src/index.html'
})
]
};
Natomiast w pliku src/index.html zakomentowujemy:
<!-- <script defer src="./javascript/index.js"></script> -->
npm run dev || npm run watch (wyjście Ctrl + C z trybu śledzenia) || npm run prod # trzy wersje rozruchu skryptu
Po wykonaniu rozruchu npm run dev, webpack wygeneruje nam katalog wynikowy /dist z plikami: bundle.js i index.html.
Po otwarciu wygenerowanego pliku w /dist/index.html możemy zauważyć, iż wtyczka html-webpack-plugin sama dynamicznie i automatycznie wstawiła do nagłówka strony przed </head> ścieżkę do wygenerowanego pliku javascript:
<script defer src="bundle.js"></script></head>
Teraz w ramach kontroli sprawdzamy plik /dist/index.html w przeglądarce
czy wyświetla się prawidłowo. Wszystko działa poprawnie tak samo jak w powyższym teście.
Możemy też wykonać testy dla rozruchu npm run watch lub npm run prod, tylko musimy pamiętać o uprzednim każdorazowym usunięciu katalogu wynikowego /dist, aby zobaczyć efekty.
npm run watch # wyjście z trybu śledzenia Ctrl+C
||
npm run prod
tryb –watch pozwala na prace ciągłą tzn. po każdorazowej zmianie automatycznie zapisze do pliku wynikowego
Plik /dist/index.html wyświetla się tak samo jak wcześniej.
W następnym kroku dla usprawnienia pracy pochylimy się nad webpack-dev-server – webpack z serwerem programistycznym, który zapewni nam tryb obserwowania i automatyczne przeładowanie kodu na żywo, dzięki czemu zawartość naszego projektu będzie automatycznie odświeżana w przeglądarce.
npm i webpack-dev-server -D
npm uninstall webpack-dev-server # usunięcie
package.json
"devDependencies": {
"html-webpack-plugin": "^5.5.1",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
Dopisuje rozruch dla webpack-dev-server:
package.json
"scripts": {
"dev": "webpack",
"watch": "webpack --watch",
"prod": "webpack --mode production",
"serve": "webpack serve"
},
Wprowadzamy ustawienia:
webpack.config.js
devServer: {
static: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000,
hot: true
},
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/javascript/index.js'),
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
},
devServer: {
static: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000,
hot: true
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../src/index.html'
})
]
};
npm run serve # rozruch (Ctrl + C - wyjście)
W tym przypadku gdy usuniemy katalog /dist z plikami wynikowymi nie będą one dla nas widoczne, gdyż webpack-dev-server przechowuje je w pamięci.
Pomimo niewidocznych plików wynikowych projekt będzie dostępny dla nas pod adresem http://localhost:9000/. Od teraz a właściwie od momentu rozruchu npm run serve w trakcie pracy i każdroazowej zmianie w kodzie wszystkie zmiany bedą przeładowywane na żywo.
Teraz czas na kolejną wytczkę copy-webpack-plugin stosowaną najczęściej dla wersji produkcyjnej, która kopiuje katalogi, pliki do katalogu wynikowego /dist.
W katalogu src zakładamy katalog /images dodąjac pliki z rozszerzeniem: .jpg, .png, .webp:
cd .. # wyjście z katalogu webpack
cd src # wejście do katalogu src
mkdir images # utworzenie katalogu
W katalogu /images dodajemy pliki z przykładowymi rozszerzeniami:
.webp, .png, .jpg. Natomiast w pliku src/index.html wprowadzamy grafiki:
index.html
<div class="images">
<figure>
<img src="./images/dog-paw-heart.webp" alt="Dog's paw in the heart" style="max-width:100%; height: auto;">
<figcaption>Dog's paw in the heart.</figcaption>
</figure>
<figure>
<img src="./images/dog-paw-heart.png" alt="Dog's paw in the heart" style="max-width:100%; height: auto;">
<figcaption>Dog's paw in the heart.</figcaption>
</figure>
<figure>
<img src="./images/dog-paw-heart.jpg" alt="Dog's paw in the heart" style="max-width:100%; height: auto;">
<figcaption>Dog's paw in the heart.</figcaption>
</figure>
</div>
Przechodzimy do instalacji:
cd .. # wyjście z katalogu src
cd webpack # wejście do katalogu webpack
npm i copy-webpack-plugin -D
npm uninstall copy-webpack-plugin
package.json
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"html-webpack-plugin": "^5.5.1",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
Przechodzimy do konfiguracji:
webpack.config.js
const CopyPlugin = require ( "copy-webpack-plugin" );
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{ from: "../src/images", to: "../dist/images" }
],
}),
],
};
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require ( "copy-webpack-plugin" );
const path = require('path');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/javascript/index.js'),
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
},
devServer: {
static: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000,
hot: true
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../src/index.html'
}),
new CopyPlugin({
patterns: [
{ from: "../src/images", to: "../dist/images" }
],
})
]
};
Wykonujemy przykładowy rozruch npm run dev i otrzymujemy pliki graficzne w katalogu wynikowym /dist:
Nareszcie przyszedł czas na preprocesor CSS.
cd .. # przejście do głównego katalogu starter-webpack-5
pwd # ścieżka /starter-webpack-5
cd src # przejście do folderu src
W katalogu src tworzymy katalog scss z plikiem main.scss:
mkdir scss # utworzenie katalogu
cd scss # przejscie do katalogu
pwd # sprawdzenie ścieżki /webpack-wp/scss
touch main.scss # utworzenie pliku main.scss
Tworzymy w pliku main.scss przykładowe ostylowanie:
main.scss
$red: red;
$green: green;
$blue: blue;
$coral: coral;
$gray: gray;
$white: white;
$black: black;
$bg: $gray;
body {
background: $bg;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
align-content: center;
row-gap: 10px;
column-gap: 10px;
transition: all 300ms ease-in;
}
h1 {
color: $red;
}
h2 {
color: $green;
}
h3 {
color: $blue;
}
h4 {
color: $coral;
}
h5 {
color: $white;
}
h6 {
color: $black;
}
cd .. # przejście do katalogu src
cd .. # przejście do głównego katalogu starter-webpack-5
cd webpack # przejście do katalogu webpack
pwd # sprawdzamy ścieżkę /starter-webpack-5/webpack
Bedąc w katalogu webpack instalujemy wszystko co będzi potrzebne do przetwarzania sass:
npm i sass sass-loader style-loader css-loader -D
npm uninstall sass sass-loader style-loader css-loader # usunięcie
sass – preprocesor CSS
sass-loader – ładuje, obsługuje pliki typu sass/scss, współpracuje z sass, node-sass
style-loader – zmienia kod CSS na JavaScript, ładuje style, automatycznie dodaje style do nagłówka strony
css-loader – ładuje, wczytuje, przetwarza, zwraca, obsługuje zawartośc pliku .css
Wszystko zostanie uruchomione od dołu do góry:
góra
’style-loader’
’css-loader’
’sass-loader’
dół
package.json
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.1",
"sass": "^1.62.1",
"sass-loader": "^13.3.1",
"style-loader": "^3.3.3",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
W /src/javascript/index.js wstawiam na samej górze:
import "../scss/main.scss";
index.js
import "../scss/main.scss";
// document.querySelector("h1").style.color = "#00FFFF";
// document.addEventListener("click", function () {
// document.querySelector("h1").innerHTML = "TEST JavaScript";
// });
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require ( "copy-webpack-plugin" );
const path = require('path');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/javascript/index.js'),
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js',
},
devServer: {
static: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000,
hot: true
},
module: {
rules: [
{
test: /\.css$/i,
use: [ "style-loader", "css-loader"],
},
{
test: /\.s[ac]ss$/i,
use: [
{
// Creates `style` nodes from JS strings (plugin instead of "style-loader")
loader: "style-loader",
options: {}
},
{
// Translates CSS into CommonJS
loader: 'css-loader',
options: {}
},
{
// Compiles Sass to CSS
loader: 'sass-loader',
options: {
implementation: require('sass'), // Prefer `dart-sass`
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../src/index.html'
}),
new CopyPlugin({
patterns: [
{ from: "../src/images", to: "../dist/images" }
],
})
]
};
Sprawdzamy konfigurację preprocesora sass:
npm run dev || npm run watch (wyjście Ctrl + C z trybu śledzenia) || npm run prod
Otwierając w przeglądarce wynikowy index.html widzimy, że nagłówek zmienił kolor na czerwony czyli zostało zastosowane stylowanie z pliku main.scss.
Następnie dokładamy istotne detale:
npm i postcss-loader postcss autoprefixer -D
npm uninstal postcss-loader postcss autoprefixer # usuwanie
postcss-loader:
- – moduł ładując postcss
- – do przetwarzania CSS za pomocą postcss
postcss:
- – pobiera plik CSS jako dane wejściowe, uruchamia wtyczki, kompiluje SASS do CSS, przekształca CSS w JavaScript z pomocą wtyczek js
- – aby działał najpierw należy skonigurować w Webpack’u CSS
- – posiada ogromną liczbę pluginów
autoprefixer:
- – wtyczka postcss przekształcająca CSS poprzez JS
- – analizuje css i automatycznie dodaje prefiksy dostawców do CSS, używając danych z Can I Use (-webkit, -moz, itp.)
Webpack zawsze zaczyna od końca najpierw uruchomi PostCSS na pliku CSS postcss-loader
Ważne jest aby wszystko działało poprawnie więc powinniśmy ustawić w pliku package.json liste do określenia przeglądarek:
Można ustawić wartość domyślną Webpack:
package.json:
"browserslist": [
"defaults"
],
Lub z własnymi ustawieniami, gdzie można zastosować dla przeglądarek określone wartości:
package.json:
"browserslist": [
"last 2 version",
">0.5%",
"Firefox ESR",
"not dead"
],
„last 2 version” – ostatnie 2 wersje przeglądarek
„>0.5%” – więcej niż 0.5% używa tych przeglądarek,
„Firefox ESR” – kanał ESR oferujący tylko poprawki stabilności i bezpieczeństwa Firefox i nic więcej
„not dead” – przeglądarki nadal używane
W tym projekcie zastosujemy:
package.json:
"browserslist": [
"defaults"
],
"devDependencies": {
"autoprefixer": "^10.4.14",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.1",
"postcss": "^8.4.24",
"postcss-loader": "^7.3.2",
"sass": "^1.62.1",
"sass-loader": "^13.3.1",
"style-loader": "^3.3.3",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
Uzupełniamy webpack.config.js o postcss-loader i autoprefixer:
webpack.config.js
module: {
rules: [
{
test: /\.css$/i,
use: [ "style-loader", "css-loader", "postcss-loader"],
},
{
test: /\.s[ac]ss$/i,
use: [
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"autoprefixer",
],
],
},
},
},
],
},
],
},
npm run dev || npm run watch (wyjście Ctrl + C z trybu śledzenia) || npm run prod
W celu sprawdzenia czy autoprefixer działa jak należy, wykonujemy rozruch npm run dev a następnie otwieramy wynikowy plik /dist/index.js i odnajdujemy auto-prefix np. -moz-.
Możemy również skorzystać z mapy źródłowej oferowanej przez Webpack dla skomilowanego kodu.
Aby wygenerować mapę źródłową za pomocą Webpack należy wprowadzić w pliku webpack.config.js wartość source-map dla devtool.
webpack.config.js
devtool: "source-map",
Dzięki tej wartości Webpack dołącza plik z mapą, która mapuje skompilowany kod na pliki źródłowe. Dzięki temu badając JavaScript w przeglądarce debugger będzie nam wskazywał ścieżki do plików źródłowych.
W wyniku rozruchu zostaje wygenerowany plik wynikowy bundle.js.map.
npm i babel-loader @babel/core @babel/preset-env -D
npm uninstall babel-loader @babel/core @babel/preset-env # usunięcie
babel-loader – ładowarka umożliwiająca transpilację plików JavaScript przy użyciu Babel i webpack
@babel/core – rdzeń kompilatora (transpilacja (kompilacja) / tłumaczenie kodu ES6+ do ES5),
uruchamia kompilator babel, który transpiluje kod JavaScript ES6+ do ES5
@babel/preset-env – zbiór wtyczek i podstawowych gotowych ustawień, podobny do autoprefixer, również korzysta z browserlist tak jak autoprefixer
Tak wstępnie ustawione podstawowe środowisko instaluje wszystkie wtyczki ES6.
Aby pracować np. z React.js należy doinstalować dodatkową wtyczkę @babel/preset-react,
z TypeScript JS @babel/preset-typescript, natomiast z Vue.js babel-preset-vue
lub @vue/babel-preset-app, itd..
Ten zestaw wymaga ustawienia w package.json „browserslist”, my ustawiliśmy już jej wartość na:
package.json
"browserslist": [
"defaults"
],
+
webpack.config.js
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
['@babel/preset-env', { targets: "defaults" }]
}
}
}
]
}
package.json
"browserslist": [
"defaults"
],
"devDependencies": {
"@babel/core": "^7.22.1",
"@babel/preset-env": "^7.22.4",
"autoprefixer": "^10.4.14",
"babel-loader": "^9.1.2",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.1",
"postcss": "^8.4.24",
"postcss-loader": "^7.3.2",
"sass": "^1.62.1",
"sass-loader": "^13.3.1",
"style-loader": "^3.3.3",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
W katalogu src/javascript/ tworzymy dodatkowy plik app.js.
cd .. # wyjście z katalogu webpack
cd src # wejście do katalogu src
cd javascript # wejście do katalogu javascript
touch app.js # utworzenie pliku
W pliku src/javascript/app.js wpisujemy przykadowy kod JavaScript:
app.js
export const showParagraph = () => {
const paragraph = document.createElement('p');
paragraph.textContent = "babel-loader @babel/core @babel/preset-env";
paragraph.style.color = "#00ff00";
document.body.appendChild(paragraph);
};
function checkFunction() {
alert("checkFunction() it's OK");
}
export {
checkFunction
};
Natomiast w pliku src/javascript/index.js import z plik app.js:
index.js
import { showParagraph } from './app';
showParagraph();
import { checkFunction } from "./app";
checkFunction();
import "../scss/main.scss";
// document.querySelector("h1").style.color = "#00FFFF";
// document.addEventListener("click", function () {
// document.querySelector("h1").innerHTML = "TEST JavaScript";
// });
Przechodzimy do wykonania rozruchu:
cd .. # wyjście z katalogu javascript
cd src # wejście do katalogu src
cd webpack # wejście do katalogu javascript
npm run dev || npm run watch (wyjście Ctrl + C z trybu śledzenia) || npm run prod
W pierwszej kolejności po otwarciu pliku index.html w przeglądarce zgłasza się alert, natomiast po kliknięciu w OK widzimy dodany napis w kolorze linomki.
Przyszedł już czas na minimalizację pliku wynikowego /dist/bundle.js.
cd webpack # wejście do katalogu webpack
npm i terser-webpack-plugin -D
npm uninstall terser-webpack-plugin # usunięcie
terser-webpack-plugin – ta wtyczka służy do minimalizacji kodu JavaScript
package.json
"devDependencies": {
"@babel/core": "^7.22.1",
"@babel/preset-env": "^7.22.4",
"autoprefixer": "^10.4.14",
"babel-loader": "^9.1.2",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.1",
"postcss": "^8.4.24",
"postcss-loader": "^7.3.2",
"sass": "^1.62.1",
"sass-loader": "^13.3.1",
"style-loader": "^3.3.3",
"terser-webpack-plugin": "^5.3.9",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
W pliku webpack.config.js zmieniamy nazwę pliku wyjściowego na bundle.min.js a także dopisujemy ustawienia konfiguracyjne przeznaczone właśnie dla powyższej wtyczki.
webpack.config.js
const TerserPlugin = require("terser-webpack-plugin");
wraz z:
webpack.config.js
module.exports = {
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.min.js',
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
test: /\.m?js(\?.*)?$/i,
}),
],
},
};
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const path = require('path');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/javascript/index.js'),
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.min.js',
},
devtool: "source-map",
devServer: {
static: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000,
hot: true
},
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader", "postcss-loader"],
},
{
test: /\.s[ac]ss$/i,
use: [{
// Creates `style` nodes from JS strings (plugin instead of "style-loader")
loader: "style-loader",
options: {}
},
{
// Translates CSS into CommonJS
loader: 'css-loader',
options: {}
},
{
// Compiles Sass to CSS
loader: 'sass-loader',
options: {
implementation: require('sass'), // Prefer `dart-sass`
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"autoprefixer",
],
],
},
},
},
],
},
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: "defaults" }]
]
}
}
}
],
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
test: /\.m?js(\?.*)?$/i,
}),
],
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../src/index.html'
}),
new CopyPlugin({
patterns: [{
from: "../src/images",
to: "../dist/images"
}],
}),
]
};
Zastosujemy teraz wtyczkę clean-webpack-plugin, która czyści automatycznie folder wynikowy /dist, usuwa zalegające zbędne katalogi, pliki, itd..
npm i clean-webpack-plugin -D
npm uninstall clean-webpack-plugin # usunięcie
package.json
"devDependencies": {
"@babel/core": "^7.22.1",
"@babel/preset-env": "^7.22.4",
"autoprefixer": "^10.4.14",
"babel-loader": "^9.1.2",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.1",
"postcss": "^8.4.24",
"postcss-loader": "^7.3.2",
"sass": "^1.62.1",
"sass-loader": "^13.3.1",
"style-loader": "^3.3.3",
"terser-webpack-plugin": "^5.3.9",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
Wprowadzamy ustawienia do pliku konfiguracyjnego:
webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
oraz:
webpack.config.js
plugins: [
new CleanWebpackPlugin(),
],
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require('path');
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/javascript/index.js'),
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.min.js',
},
devtool: "source-map",
devServer: {
static: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000,
hot: true
},
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader", "postcss-loader"],
},
{
test: /\.s[ac]ss$/i,
use: [{
// Creates `style` nodes from JS strings (plugin instead of "style-loader")
loader: "style-loader",
options: {}
},
{
// Translates CSS into CommonJS
loader: 'css-loader',
options: {}
},
{
// Compiles Sass to CSS
loader: 'sass-loader',
options: {
implementation: require('sass'), // Prefer `dart-sass`
},
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
[
"autoprefixer",
],
],
},
},
},
],
},
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: "defaults" }]
]
}
}
}
],
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
test: /\.m?js(\?.*)?$/i,
}),
],
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: '../src/index.html'
}),
new CopyPlugin({
patterns: [{
from: "../src/images",
to: "../dist/images"
}],
}),
new CleanWebpackPlugin(),
]
};
npm run dev || npm run watch (wyjście Ctrl + C z trybu śledzenia) || npm run prod
Po usunięciu np. wtyczki wykonujemy rozruch i sprawdzamy przy tej okazji wynikowy plik index.html w przegladarce.
Końcowy zrzut wszystkich katalogów z plikami projektu starter-webpack-5:
Gotowy projekt można zobaczyć pod adresem: https://github.com/AnesseL/starter-webpack-5.