David Soyez @2016
Sommaire
- Qu'est ce que Webpack?
- Quelques chiffres
- Pourquoi Webpack?
- Prerequis
- Installation
- Usage simple
- Usage avance
- Watch Mode & dev-server
- et ensuite...?
Code source des exemples: https://github.com/david-soyez/webpack_intro
Qu'est ce que Webpack?
Webpack prend des modules avec dépendances et génère des assets représentant ces modules.
Webpack est comparable aux outils tels que Grunt, Gulp, RequireJs, Browserify...
Quelques chiffres
Popularité:
Quelques chiffres
Tendance:
Pourquoi Webpack?
- Diviser l'arbre de dépendance en morceaux chargés sur demande
- Gardez le temps de chargement initial faible
- Chaque asset statique doit pouvoir être un module
- Possibilité d'intégrer des bibliothèques 3e partie sous forme de modules
- Possibilité de personnaliser presque chaque partie du module bundler
- Adaptés pour les grands projets
Objectifs:
Pourquoi Webpack?
- Regroupez vos fichiers js dans un seul
- Utilisez les paquets NPM dans sur le frontend
- Ecrire du JavaScript ES2015 / ES2017 (avec l'aide de Babel)
- Minify / Optimize
- Convertir Less / SCSS en CSS
- Utilisez HMR (Hot Module Replacement)
- Inclure tout type de fichier dans votre JavaScript
- et beaucoup d'autres...
Plus concrètement:
Prerequis
- nodejs >=4
- npm
- Connaissance de CommonJs, AMD ou ES2015
Installation
// installation globale
$ npm install --save-dev webpack
// usage global
$ webpack
// installation locale dans un projet
$ npm init
$ npm install --save-dev webpack
// usage local dans un projet
$ nodejs ./node_modules/webpack/bin/webpack.js
$ vim entry.js
document.write("Ca fonctionne.");
$ vim index.html
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>
$ webpack ./entry.js bundle.js
Hash: e50979b7c38d7547d9e8
Version: webpack 1.12.14
Time: 33ms
Asset Size Chunks Chunk Names
bundle.js 1.42 kB 0 [emitted] main
[0] ./entry.js 34 bytes {0} [built]
// création du bundle
Usage simple
sans module
bundle.js
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports) {
document.write("Ca fonctionne.");
/***/ }
/******/ ]);
Usage simple
sans module
$ vim entry.js
var monModule = require('./monModule');
var module1 = new monModule();
document.write(module1.bonjour());
document.write('<br>');
document.write(module1.auRevoir());
$ vim monModule.js
function monModule() {
this.bonjour = function() {
return 'bonjour!';
}
this.auRevoir = function() {
return 'au revoir!';
}
}
module.exports = monModule;
$ webpack ./entry.js bundle.js
// création du bundle
Usage simple
avec module en CommonJs
bonjour!
au revoir!
Usage simple
avec module en CommonJs
Usage simple
$ vim entry.js
// define integrera tout le code dans bundle.js sans faire de requete ajax
define(['./monModule'] , function (module1) {
document.write(module1.bonjour());
document.write('<br>');
document.write(module1.auRevoir());
});
$ vim monModule.js
define([], function() {
return {
bonjour: function() {
return 'bonjour';
},
auRevoir: function() {
return 'au revoir';
}
};
});
$ webpack ./entry.js bundle.js
// création du bundle
L'utilisation de define() générera un bundle.js complet.
module AMD avec define()
Usage simple
module AMD avec define()
L'utilisation de define() générera un bundle.js intégrant tous les modules
$ vim entry.js
require(['./monModule'] , function (module1) {
document.body.innerHTML += module1.bonjour();
document.body.innerHTML += '<br>';
document.body.innerHTML += module1.auRevoir();
});
$ webpack ./entry.js bundle.js
Hash: 3235bc0333357bac68a4
Version: webpack 1.12.14
Time: 43ms
Asset Size Chunks Chunk Names
bundle.js 3.91 kB 0 [emitted] main
1.bundle.js 540 bytes 1 [emitted]
[0] ./entry.js 192 bytes {0} [built]
[1] ./monModule.js 161 bytes {1} [built]
// création du bundle
L'utilisation de require() générera un bundle.js sans monModule.js et effectuera un chargement ajax pour charger ce dernier.
Usage simple
AMD avec require()
Usage simple
AMD avec require()
L'utilisation de require() générera un bundle.js sans monModule.js et effectuera un chargement ajax pour charger ce dernier
Usage avancé
avec fichier de configuration
Afin de sauvegarder les paramètres et gagner du temps nous pouvons creer un fichier de configuration webpack.config.js
module.exports = {
entry: "./entry.js",
output: {
path: __dirname,
filename: "bundle.js"
}
};
$ vim webpack.config.js
Et ensuite lancer simplement la commande webpack:
$ webpack
Hash: cd6d42419beaf70c1a14
Version: webpack 1.12.14
Time: 42ms
Asset Size Chunks Chunk Names
bundle.js 1.81 kB 0 [emitted] main
[0] ./entry.js 167 bytes {0} [built]
[1] ./monModule.js 172 bytes {0} [built]
Dans un projet npm vous pouvez également configurer le paramètre start ou make afin de lancer webpack avec un npm start ou npm run make
Ou par exemple parametrer watch pour lancer le watch mode avec un npm run watch
Usage avancé
les loaders
Les loaders sont des transformations qui sont appliquées sur un fichier de ressources de votre application. Ils prennent une source en entrée et renvoient une nouvelle source modifiées.
Par exemple, il y a des loaders pour CoffeeScript ou JSX.
Les principales fonctionnalités des loaders sont:
- Les loaders peuvent être chaînés.
- Les loaders peuvent être synchrones ou asynchrones.
- Les loaders fonctionnent en node.js et peuvent faire tout ce qui est possible avec.
- Les loaders acceptent des paramètres d’entrée.
- Les loaders peuvent être attachés à des extensions.
- Les loaders peuvent être installés par npm.
- Les loaders peuvent accéder à la configuration.
- Les plugins peuvent rajouter des fonctionnalités aux loaders.
- etc.
Usage avancé
les loaders
Reprenons l'exemple précédent pour y ajouter un loader pour inclure du css:
$ npm install css-loader style-loader --save-dev
Nous devons d'abord installer les loaders css et style:
module.exports = {
entry: "./entry.js",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" }
]
}
};
Nous modifions ensuite webpack.config.js pour y ajouter notre loader:
$ vim webpack.config.js
Usage avancé
les loaders
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript" src="bundle.js" charset="utf-8"></script>
</body>
</html>
Le code source de index.html ne change pas:
require("./style.css");
var monModule = require('./monModule');
var module1 = new monModule();
document.write(module1.bonjour());
document.write('<br>');
document.write(module1.auRevoir());
Nous modifions ensuite entry.js pour y ajouter le require de notre style.css qui aura pour effet de l'inclure dans notre bundle en tant que module:
$ vim entry.js
On peut maintenant créer le bundle.js:
$ webpack
Usage avancé
les loaders
Le css est alors ajouté a l’intérieur de <head> par bundle.js:
/* 2 */
/***/ function(module, exports, __webpack_require__) {
exports = module.exports = __webpack_require__(3)();
exports.push([module.id, "body {\n background: blue;\n color: white;\n}\n", ""]);
/***/ },
Un module est généré et ajouté dans bundle.js:
Usage avancé
les loaders
De la même façon nous pouvons ajouter des fonts et des images avec url-loader. Il permet de traiter et copier nos assets dans le répertoire désiré.
$ npm install url-loader --save-dev
The url loader works like the file loader, but can return a Data Url if the file is smaller than a limit.
Rajoutons notre loader une limite pour que nos assets soit directement inclus en data:base64 en fonction de leurs tailles.
module.exports = {
entry: "./public/entry.js",
output: {
path: "./public/assets", // The output directory as absolute path (required)
publicPath: "/assets/", // specifies the public URL address of the output files when referenced in a browser
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" },
{ test: /\.(png|jpg|ttf)$/, loader: 'url-loader?limit=8192' }
]
}
};
Installons le packet npm:
$ vim webpack.config.js
Usage avancé
les loaders
@font-face {
font-family: "Roboto";
src: url('./Roboto-Black.ttf');
}
body {
background-image: url(./webpack_logo.png);
color: black;
}
.smile {
background-image: url(./smile.png);
width: 48px;
height: 48px;
display: block;
}
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript" src="./assets/bundle.js" charset="utf-8"></script>
<div>
<span class="smile"></span>
</div>
</body>
</html>
$ vim public/style.css
$ vim public/index.html
Usage avancé
les loaders
Watch Mode & dev-server
$ webpack --progress --colors --watch
L'option watch permet de reconstruire automatiquement après un changement du code source.
$ npm install webpack-dev-server -g
$ webpack-dev-server --progress --colors
webpack-dev-server permet la même chose mais en créant un mini serveur http en NodeJs .
http://localhost:8080/ ou http://localhost:8080/webpack-dev-server/
module.exports = {
entry: "./public/entry.js",
output: {
path: "./public/assets", // The output directory as absolute path (required)
publicPath: "/assets/", // specifies the public URL address of the output files when referenced in a browser
filename: "bundle.js"
},
devServer: {
contentBase: 'public'
},
module: {
loaders: [
{ test: /\.css$/, loader: "style!css" },
{ test: /\.(png|jpg|ttf)$/, loader: 'url-loader?limit=8192' }
]
}
};
$ vim webpack.config.js
Watch Mode & dev-server
$ webpack-dev-server --hot --inline
Avec --hot --online comme parametre, les modules sont recharges a chaud:
Il faut egalement ajouter module.hot.accept() dans les modules
et ensuite...?
- Ajouter un loader css, less, sass, minify etc..
- AJouter un loader ES2015(babel)
- Ajouter un loader JSX
- Ajouter un loader React
- Flux, Redux
- ...
Webpack
By David Soyez
Webpack
- 1,127