Proiect Webpack/Babel pentru aplicatii JavaScript ES6
Tutorial - Crearea unui proiect de la zero pentru ES6 folosind Webpack si Babel
In acest articol vom crea un proiect Webpack, capabil sa transforme automat codulul ES6+ in cod ES5 (compatibil cu majoritatea browserelor).
Noile versiuni JavaScript vin cu imbunatatiri importante si am vrea sa le utilizam la dezvoltare. Chiar daca aceste noi caracteristici (let, const, arrow functions, clase etc.) nu sunt disponibile pe toate browserele, putem folosi un transpiler precum BabelJS pentru a transforma codul ES6+ in cod compatibil cu browserele mai vechi.
Este ceea ce vom face in acest tutorial.
Initializarea unui proiect nou:
Intr-un folder nou initializam un nou proiect Node:
> npm init
Raspundem la intrebarile primite:
package name: (00_02z_es6) d3js-es6-starter
version: (1.0.0)
...
npm
a generat un nou fisier pentru noi: package.json
Acum putem sa ne adaugam dependentele.
Instalare Webpack
Vom instala webpack
si webpack-cli
. Webpack este un bundler care ne ajuta sa impachetam codul pentru a fi gata de livrare catre serverul de productie. Odata cu aceasta impachetare a tuturor fisierelor necesare in productie, putem aplica diverse transformari ale codului. In felul asta vom transforma si codul ES6 in cod ES5.
> npm i webpack webpack-cli --save-dev
+ webpack-cli@3.2.1
+ webpack@4.28.4
added 394 packages in 83.275s
- organizam dependentele proiectului in doua mari categorii, librarii care se vor duce in productie (fara argumentul
--save-dev
) si librarii utile doar la dezvoltare (folosim argumentul--save-dev
).
Crearea comenzilor build
Vom crea comenzi care impacheteaza fisierele intr-un director (dist). Acest director va contine fisiere statice (html, css, js, imagini, fonturi…) ce pot fi trimise catre orice server de web pentru a fi afisate in browser.
Vor fi doua comenzi, una pentru dezvoltare (fisierele nu vor fi minificate) si alta va si minifica fisierele (elimina spatiile, redenumeste variabilele cu altele mai scurte, etc.)
In fisierul package.json
:
// package.json
"scripts": {
"dev": "webpack --mode development ./src/js/index.js --output ./build/main.js",
"build": "webpack --mode production ./src/js/index.js --output ./build/main.js"
},
- rulam cele doua comenzi din terminal astfel:
> npm run dev
si > npm run build
Dar deocamdata nu avem ce impacheta. Inainte sa scriem o mica aplicatie, vom mai instala niste pachete utile.
ES6 / Babel
Webpack nu stie sa interpreteze codul ES6 de unul singur. Are nevoie de ajutor. Si acel ajutor vine de la BabelJS.
Folosind Babel, vom scrie cod ES6+, folosind ultimele specificatii, dar codul final va fi transformat in ES5, compatibil cu majoritatea browserelor.
Webpack foloseste loadere si plugin-uri pentru a prelua codul din fisiere si a aplica diverse transformari asupra lui inainte de a scrie in destinatia finala.
Vom instala si configura componentele Babel pentru Webpack:
- babel core
- babel loader
- babel preset env pentru compilarea codului Javascript ES6 in ES5
> npm i @babel/core babel-loader @babel/preset-env --save-dev
+ @babel/core@7.2.2
+ babel-loader@8.0.5
+ @babel/preset-env@7.2.3
added 113 packages in 14.063s
Configurarea Babel
Cream un nou fisier in radacina proiectului: .babelrc
// .babelrc
{
"presets": [
"@babel/preset-env"
]
}
- am configurat proprietatea presets cea care ne spune ce versiune JavaScript avem de gand sa scriem in fisierele
.js
. @babel/preset-env inseamna ca vrem sa scriem in ultima versiune JavaScript (ES6+)
Configuram acum loaderele Babel. Cream un fisier nou de configurare Webpack:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
Testam ES6
Haideti sa facem un mic test sa vedem daca ceea ce scriem noi in ES6 se va compila in ES5:
Pentru asta vom crea un fisier in calea src/js/index.js
:
// src/index.js
class MyClass {
constructor() { }
print() {
console.log('Test ES6')
}
}
let c = new MyClass();
c.print();
- am scris o clasa in ES6, ma astept ca dupa compilare sa ajunga la destinatie ca o functie (nu avem clase in ES5).
Rulam comanda > npm run dev
...
Asset Size Chunks Chunk Names
main.js 4.77 KiB main [emitted] main
Entrypoint main = main.js
[./src/js/index.js] 974 bytes {main} [built]
Verificam continutul fisierului build/main.js
si cautam numele clasei MyClass. In loc sa gasim class MyClass
vom gasi function MyClass
:
Acum avem tot ce ne trebuie ca sa compilam cod ES6, insa vom mai instala cateva componente care ne usureaza dezvoltarea, inclusiv un server web de dezvoltare care sa reincarce automat aplicatia web la fiecare modificare in fiserele sursa.
Instalare plugin pentru procesare HTML
Vrem ca Webpack sa preia automat un template index.html
si sa-l duca in build
. Pe langa asta vrem sa incarce si bundle-ul final in pagina (main.js).
> npm i html-webpack-plugin html-loader --save-dev
+ html-loader@0.5.5
+ html-webpack-plugin@3.2.0
added 46 packages in 17.08s
Acum cream un fisier src/index.html
:
<!-- src/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ES6, Webpack and Babel Starter</title>
</head>
<body>
<h1> ES6, Webpack and Babel - Starter Project </h1>
<div id="app"></div>
</body>
</html>
Configurare html-webpack-plugin
Adaugam urmatorul cod in webpack.config.js
:
// webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
{
...,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [{
loader: "html-loader",
options: { minimize: true }
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
Acum putem verifica functionarea plugin-ului. Ne asteptam sa apara si fisierul build/index.html
. Iar daca verificam continutul, observam ca incarca fisierul main.js
.
> npm run dev
Built at: 2019-01-17 15:14:12
Asset Size Chunks Chunk Names
./index.html 208 bytes [emitted]
main.js 4.77 KiB main [emitted] main
Entrypoint main = main.js
[./src/js/index.js] 974 bytes {main} [built]
In build/index.html
a aparut si urmatorul cod: <script type="text/javascript" src="main.js"></script>
Prelucrarea CSS (preluarea si transferul in fisier CSS separat)
Implicit, Webpack nu stie sa prelucreze CSS intr-un fisier independent de aplicatia principala (main.js).
Vom folosi plugin-ul mini-css-extract-plugin
pentru a extrage CSS in bundle separat, dedicat stilurilor CSS.
vom folosi loaderul css-loader
pentru a instrui Webpack cum sa prelucreze fisierele .css, adica ce sa faca atunci cand intalneste un fisier .css. Aceste fisiere .css le vom trata ca pe niste module si le importam din fisiere .js. Pentru fiecare fisier .js care importa .css, Webpack va incarca acel fisier .css si il va trimite catre un bundle main.css
.
Instalam mini-css-extract-plugin
si css-loader
> npm i mini-css-extract-plugin css-loader --save-dev
+ mini-css-extract-plugin@0.5.0
+ css-loader@2.1.0
added 20 packages in 17.312s
Apoi, configuram pluginul:
// webpack.config.js
...
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
...
loader: "babel-loader"
...
},
{
...
loader: "html-loader",
...
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
}
]
},
plugins: [
new HtmlWebPackPlugin({
...
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
Urmeaza sa testam functionalitatea plugin-ului si pentru asta cream un nou fisier .css
:
/* src/js/index.css */
h1 {
color: #0044af;
font-size: 0.9rem;
}
Incarcam css
-ul in fisierul index.js
, ca modul:
// src/index.js
import styles from "./index.css";
...
Acum css-ul este prelucrat de loader si trimis in directorul build.
Rulam comanda > npm run dev
Built at: 2019-01-17 18:43:03
Asset Size Chunks Chunk Names
./index.html 292 bytes [emitted]
main.css 59 bytes main [emitted] main
main.js 5.45 KiB main [emitted] main
Entrypoint main = main.css main.js
Directorul build contine si un bundle special pentru css-uri, fisierul main.css
iar index.html
are cod de incarcare a lui in pagina:
<!-- build/index.html -->
...
<link href="main.css" rel="stylesheet">
</head>
Putem sa testam aplicatia finala cu un server web sau deschizand direct index.html
, insa vrem sa instalam un server de dezvoltare care sa actualizeze automat aplicatia si sa o reincarce in browser pentru noi.
Server Web pentru dezvoltare
Mai avem putin si terminam proiectul nostru ES6. Vom instala un server pentru dezvoltare (modulul webpack-dev-server
):
> npm i webpack-dev-server --save-dev
+ webpack-dev-server@3.1.14
added 139 packages in 15.9s
Definim comanda care va porni serverul de dezvoltare:
// webpack.config.js
"scripts": {
"start": "webpack-dev-server --mode development ./src/js/index.js --open",
"dev": "..."
}
– argumentul --open
va deschide si browserul implicit
Acum pornim serverul cu comanda > npm run start
(comanda start poate fi pornita si cu > npm start
).
Cu serverul pornit, incercati sa modifiati codul sursa (src/index.html
, src/js/index.css
sau src/js/index.js
) si observam cum se actualizeaza aplicatia in browser.
Extra - minify CSS
Opriti serverul de dezvoltare (CTRL ^C) si incercati sa rulati alternativ comenzile:
> npm run dev
> npm run build
Prima comanda nu aplica minificare a doua aplica. Observam, in cazul comenzii build, ca main.js
este minificat dar nu si main.css
.
Pentru asta avem nevoie sa definim un minifier extern de CSS. Webpack ne sa posibilitatea sa facem asta, dar va trebui sa furnizam un minifier si pentru .js pentru ca nu va mai functiona cel intern.
Deci, vom instala plugin-uri externe pentru minificare.
Apoi vom suprascrie setarea optimization.minimizer
.
- odata suprascrisa aceasta setare, nu mai functioneaza minificarea pentru fisierele
.js
- asa ca trebuie sa instalam si un plugin pentru minificarea fisierelor
.js
Instalam plugin-urile:
> npm i optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin --save-dev
+ optimize-css-assets-webpack-plugin@5.0.1
+ uglifyjs-webpack-plugin@2.1.1
added 103 packages in 14.501s
Configuram plugin-urile de minificare:
// webpack.config.js
...
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({})
]
},
...
}
Rulam alternativ comenzile build
si dev
:
> npm run build
> npm run dev
- observam ca
build
minifica codul iardev
creeaza doar bundle-ul dar nu aplica minificarea - si face asta atat pentru CSS cat si pentru JS
Codul CSS minificat:
/* build/main.css */
h1{color:#0044af;font-family:sans-serif}
Concluzie
In acest tutorial am pus cap la cap, de la zero, tehnologii web necesare pentru dezvoltarea aplicatiilor JavaScript ES6+. Am creat un proiect starter care poate fi folosit ca punct de plecare pentru alte proiecte care necesita ES6 transpiling - conversia codului ES6 in cod ES5, compatibil cu mai toate browserele.
Pentru asta am folosit Webpack, Babel si loadere si plugin-uri pentru Webpack.
Proiectul stie sa compileze automat sursele si sa retrimita in browser actualizarile fara sa fie nevoie de Browser Refresh (F5). Developerii se pot concentra pe cod.
Share this post
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email