Les Frameworks JavaScript

Animée par Charles Jacquin

Rappel ES5

JQuery ?

Les Objets de type Array (tableaux ...)

Les méthodes du prototype d'Array

Les objets de type array possède les méthodes suivantes :

  • push
  • pop
  • shift
  • unshift
  • concat
  • splice
  • slice
  • forEach
  • map
  • filter
  • reduce
  • find
  • ...

Ajouter des éléments à un Array

var languages = ['C++','Java','JavaScript'];

languages.push('Python');
languages.unshift('C');

console.log(languages);
// ['c','c++','Java','JavaScript','Python']

Pour ajouter un element en fin de tableau, il faut utiliser la méthode push.

Pour ajouter un element en début de tableau, il faut utiliser la méthode unshift.

Retirer des éléments à un Array

var languages = ['C++','Java','JavaScript', 'C#', 'Python'];

languages.pop();
languages.shift();

console.log(languages);
// ['Java','Javascript', 'C#']

languages.splice(1,1); 
// le premier param est la position de l'élement à supprimer, 
// le deuxième param est le nombre d'élément à supprimer.

console.log(languages);
// ['Java', 'C#']

Pour retirer un element en fin de tableau, il faut utiliser la méthode pop.

Pour retirer un element en début de tableau, il faut utiliser la méthode shift.

Pour toutes les autres positions, il faut utiliser la méthode splice.

Réordonner un tableau

var myStringArray = [13,5,3,24,7,6,75,45];

myStringArray.sort(function(a,b){
    return a-b;
});
// Ascendant
console.log(myStringArray);

myStringArray.sort(function(a,b){
    return b-a;
});
//descendant
console.log(myStringArray);

//inverse l'ordre d'un tableau (les derniers seront les premiers)
myString.reverse();
console.log(myStringArray);

La methode sort va nous permettre de réordonner un tableau de string ou un tableau de number.

la méthode reverse inverse l'ordre des éléments.

Transformer en String

var myArray = ['foo','bar'];

console.log(myArray.join('/'));  //affiche foo/bar
console.log(myArray.join());  //affiche foo,bar

La méthode join permet de réunir tous les éléments d'un tableau dans une chaine de caractère.

Le deuxième paramètre (optionnel), indique la chaine de caractère qui delimitera les élements

La méthode toString appelé sur un array appelera en réalité join

Extraire une portion d'un tableau

var myArray = ['foo','bar', 'toto', 'tata'];

var slicedArray = myArray.slice(1,2);

console.log(slicedArray.join());
//affiche bar, toto 

La méthode slice retourne un nouveau tableau qui contient une portion du tableau de base.

Si le tableau est un tableau d'objet, les deux tableaux contiennent des références vers les mêmes objets.

Déterminer la position d'un élémént

var myArray = ['foo','bar', 'toto', 'tata', 'bar'];

console.log(myArray.indexOf('bar'));
//affiche 1 

console.log(myArray.indexOfLast('bar'));

Les méthodes indexOf et indexOfLast retourne la position dans le tableau de l'élément fournit en paramètre. 

Si l'élément ne se trouve pas dans le tableau retourne -1

La méthode forEach

var myArray = ['foo','bar', 'toto', 'tata'];

myArray.forEach(function(value, index){
    console.log(value, index);
    //ici on peut manipuler chaque valeur une par une
})

Pour boucler dans un tableaux nous n'auront pas forcément besoin d'utiliser le for.

La fonction fournit en paramètre sera appelée à chaque itération de la boucle.

Il n'est pas possible d'utiliser breack avec la methode Array.prototype.forEach

!

La méthode map

var nombrePair = [2,4,6,8,10];

nombreImpair = nombrePair.map(function(value, index){
    console.log(value, index);
    return value -1;
})

console.log(nombrePair.join());
// affiche 2,4,6,8,10

console.log(nombreImpair.join());
// affiche 1,3,5,7,9

La fonction map retourne un nouveau tableau, chaque élément du tableau originel sera transformé par le callback.

inside the map method

Array.prototype.map = function(projection){
    //la function retourne un array créons le
    var response = [];
    //on lance la boucle
    this.forEach(function(value, index){
        //on stocke dans le tableau de réponse, la valeur modifiée 
        //par la fonction passée en paramétre
        response.push(projection(value));
    })
    //on retourne le tableau
    return response;
}

Réecrivons la fonction map :

La méthode filter

var nombres = [1,2,3,4,5,6,7,8,9,10];

var nombrePair = nombres.filter(function(value){
  return value % 2 === 0;
});

var nombreImpair = nombres.filter(function(value){
    return value % 2 === 1;
});

console.log('nombre pair : ', nombrePair.join());
// affiche 2,4,6,8,10

console.log('nombre impair : ',nombreImpair.join());
// affiche 1,3,5,7,9

La methode filter retourne un nouveau tableau contenant tous les éléments du premier tableau pour lesquel le callback retourne true.

La méthode reduce

var nombres = [1,2,3,4];

var reducedArray = nombres.reduce(function(valeurPrecedente, valeurCourante, index){
  return valeurPrecedente + valeurCourante;
}, 0);

console.log(reducedArray);
// affiche 10

La methode reduce est un accumulateur, elle traite chaque valeur de la liste de la gauche vers la droite afin de réduire le tableau à une seule valeur.

La méthode find

var users = [
  {
    name: 'foo'
  },
  {
    name: 'bar'
  }
];

var fooUser = users.find(function(user) {
  return user.name === 'foo';
})

console.log(fooUser);
// affiche { name: 'foo' }

La méthode find permet de retrouver le premier élément du tableau correspondant à l'expression booléene retournée.

Es2015 (ex ES6)

ES6 ~ ES2015

  • Classes, Inheritance

  • Modules

  • Iterators, Generators

  • Scoping

  • Promises, Proxies

  • Arrow functions

  • Collections

  • ...

Nouvelles Features

ECMAScript ?

  • Dernière version finallisé ECMAScript6 (ES6, ES2015, Harmony)

  • Changement de convention de nommage (ES7 = ES2016)

Compatibillité

ECMAScript?

  • Un standard pour les languages de script 

  • Le language le plus populaire est JavaScript

  • ActionScript, Lua pour les plus connus

May '95

Dec '95

Sep '95

1997

Aug '96

1999

1998

2009

2003

2015

2011

2016

Mocha  (Brendan Eich, Netscape)

LiveScript

JavaScript

Edition 1

JScript  (Microsoft)

Edition 2

Edition 3

Edition 4

Edition 5

Edition 5.1

Edition 6

Edition 7

ECMA-262 specification

ES6 Transpilation

  • Un Transpiler est un type de compilateur qui transforme du code d'un language vers un autre

  • ES5 est largement supporté par les browsers

    • Le code ES6 doit être compilé

  • Deux transpiler ES6 -> ES5

    • Traceur (Google)

    • Babel (Community)

ES6 Transpilation

  • Babel est le standard:

    • Le code compilé est plus lisible (sic)

    • Support de JSX (pour React)

  • Une autre alternative consiste à utiliser un preprocesseur JS

    • CoffeeScript

    • Dart

    • Typescript

    • Flow

Traceur ES6 -> ES5 transpilation

/*jshint esnext: true */

import Todo from './todo';
import {values} from './generators';

class TodoList {
  constructor() {
    this.todos = {}; 
    this.length = 0;
  }

  add(text, done = false) {
    let todo = new Todo(text, done);
    this.todos[String(todo.timestamp)] = todo;
    this.length++;
  }

  archiveCompleted() {
    for (let todo of values(this.todos)) {
      if (todo.done) this.delete(todo);
    }
  }

  delete(todo) {
    delete this.todos[String(todo.timestamp)];
    this.length--;
  }

  getUncompletedCount() {
    let count = 0;
    for (let todo of values(this.todos)) {
      if (!todo.done) count++;
    }
    return count;
  }
}

export default TodoList;
$traceurRuntime.registerModule("todoservice.js", [], function() {
  "use strict";
  var __moduleName = "todoservice.js";
  var Todo = $traceurRuntime.getModule($traceurRuntime.normalizeModuleName("./todo", "todoservice.js")).default;
  var values = $traceurRuntime.getModule($traceurRuntime.normalizeModuleName("./generators", "todoservice.js")).values;
  var TodoList = function() {
    function TodoList() {
      this.todos = {};
      this.length = 0;
    }
    return ($traceurRuntime.createClass)(TodoList, {
      add: function(text) {
        var done = arguments[1] !== (void 0) ? arguments[1] : false;
        var todo = new Todo(text, done);
        this.todos[String(todo.timestamp)] = todo;
        this.length++;
      },
      archiveCompleted: function() {
        var $__7 = true;
        var $__8 = false;
        var $__9 = undefined;
        try {
          for (var $__5 = void 0,
              $__4 = (values(this.todos))[Symbol.iterator](); !($__7 = ($__5 = $__4.next()).done); $__7 = true) {
            var todo = $__5.value;
            {
              if (todo.done)
                this.delete(todo);
            }
          }
        } catch ($__10) {
          $__8 = true;
          $__9 = $__10;
        } finally {
          try {
            if (!$__7 && $__4.return != null) {
              $__4.return();
            }
          } finally {
            if ($__8) {
              throw $__9;
            }
          }
        }
      },
      delete: function(todo) {
        delete this.todos[String(todo.timestamp)];
        this.length--;
      },
      getUncompletedCount: function() {
        var count = 0;
        var $__7 = true;
        var $__8 = false;
        var $__9 = undefined;
        try {
          for (var $__5 = void 0,
              $__4 = (values(this.todos))[Symbol.iterator](); !($__7 = ($__5 = $__4.next()).done); $__7 = true) {
            var todo = $__5.value;
            {
              if (!todo.done)
                count++;
            }
          }
        } catch ($__10) {
          $__8 = true;
          $__9 = $__10;
        } finally {
          try {
            if (!$__7 && $__4.return != null) {
              $__4.return();
            }
          } finally {
            if ($__8) {
              throw $__9;
            }
          }
        }
        return count;
      }
    }, {});
  }();
  var $__default = TodoList;
  return {get default() {
      return $__default;
    }};
});
$traceurRuntime.getModule("todoservice.js" + '');

ES5

ES6

Babel ES6 -> ES5 transpilation

/*jshint esnext: true */

import Todo from './todo';
import {values} from './generators';

class TodoList {
  constructor() {
    this.todos = {}; 
    this.length = 0;
  }

  add(text, done = false) {
    let todo = new Todo(text, done);
    this.todos[String(todo.timestamp)] = todo;
    this.length++;
  }

  archiveCompleted() {
    for (let todo of values(this.todos)) {
      if (todo.done) this.delete(todo);
    }
  }

  delete(todo) {
    delete this.todos[String(todo.timestamp)];
    this.length--;
  }

  getUncompletedCount() {
    let count = 0;
    for (let todo of values(this.todos)) {
      if (!todo.done) count++;
    }
    return count;
  }
}

export default TodoList;
/*jshint esnext: true */

'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

var _todo = require('./todo');

var _todo2 = _interopRequireDefault(_todo);

var _generators = require('./generators');

var TodoList = (function () {
  function TodoList() {
    _classCallCheck(this, TodoList);

    this.todos = {};
    this.length = 0;
  }

  _createClass(TodoList, [{
    key: 'add',
    value: function add(text) {
      var done = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];

      var todo = new _todo2['default'](text, done);
      this.todos[String(todo.timestamp)] = todo;
      this.length++;
    }
  }, {
    key: 'archiveCompleted',
    value: function archiveCompleted() {
      var _iteratorNormalCompletion = true;
      var _didIteratorError = false;
      var _iteratorError = undefined;

      try {
        for (var _iterator = (0, _generators.values)(this.todos)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var todo = _step.value;

          if (todo.done) this['delete'](todo);
        }
      } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator['return']) {
            _iterator['return']();
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError;
          }
        }
      }
    }
  }, {
    key: 'delete',
    value: function _delete(todo) {
      delete this.todos[String(todo.timestamp)];
      this.length--;
    }
  }, {
    key: 'getUncompletedCount',
    value: function getUncompletedCount() {
      var count = 0;
      var _iteratorNormalCompletion2 = true;
      var _didIteratorError2 = false;
      var _iteratorError2 = undefined;

      try {
        for (var _iterator2 = (0, _generators.values)(this.todos)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
          var todo = _step2.value;

          if (!todo.done) count++;
        }
      } catch (err) {
        _didIteratorError2 = true;
        _iteratorError2 = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion2 && _iterator2['return']) {
            _iterator2['return']();
          }
        } finally {
          if (_didIteratorError2) {
            throw _iteratorError2;
          }
        }
      }

      return count;
    }
  }]);

  return TodoList;
})();

exports['default'] = TodoList;
module.exports = exports['default'];

ES5

ES6

Modules

  • ES6 amène la standardisation

    • ​Actuellement: AMD, CommonJS

    • Avant: Rien (global)

  • Avec ECMAScript 6, les modules sont des fichiers

    • un module par fichier

    • un fichier par module

Modules

  • Une donnée exportée dans un module est accessible partout où le module est importé

// ClientService.js

class ClientService {

    constructor() { this.clients = [];     }

    addClient(client) { this.clients.add(client); }

}

export default ClientService();
import ClientService from './ClientService';

class ClientComponent {
    clientService = new ClientService();

    submitClient(client) {

        this.clientService.addClient(client);

    }

}

ES6

ES6

module.exports = ClientService;

CommonJS

export default ClientService;

ES6

var Service = require('./ClientService');
import Service from ('./ClientService');

Modules (ES6 vs CommonJS)

Modules

  • Default exports

    • Un seul par module

    • Lors de l'import, le nom du module est libre

// ClientService.js

class ClientService {

    constructor() { this.clients = [];     }

    addClient(client) { this.clients.add(client); }

}

export default new ClientService();

ES6

import ClientService from './ClientService';

ES6

import MyService from './ClientService';

class ClientComponent {

    submitClient(client) {

        MyService.addClient(client);

    } }

Modules

Default exports

//------ MyClass.js ------
class MyClass { ... };
export default MyClass;

//------MyFunction.js ----
function myFunction() { ... };
export default myFunction;
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

Named exports

// ----- main.js ---
import * as lib from './lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(4, 3)); // 5
// ----- main.js ---
import MyClass from './MyClass'
import thatFunction from './myFunction'

var my = new MyClass();
var res = thatFunction();
// Constants.js

var $BANKRUPTCY_MIN_DEBT = 1001; var $SEQUESTRATION_MIN_DEBT = 3000;

export $BANKRUPTCY_MIN_DEBT; export $SEQUESTRATION_MIN_DEBT;

ES6

Modules (named exports)

// Constants.js

var $BANKRUPTCY_MIN_DEBT = 1001; var $SEQUESTRATION_MIN_DEBT = 3000;

export {  $BANKRUPTCY_MIN_DEBT, $SEQUESTRATION_MIN_DEBT }

ES6

  • Plusieurs export par module

  • Peut être mixer avec default

import { $BANKRUPTCY_MIN_DEBT,
$SEQUESTRATION_MIN_DEBT } from './Constants';

//do something

Modules (actuel)

  • CommonJS

  • AMD

// someModule.js
function doSomething () {
    console.log("foo");
}

exports.doSomething = doSomething;


//otherModule.js
var someModule = require('someModule');    
someModule.doSomething();
// someModule.js
define(["lib"], function (lib) {
    function doSomething() {
           console.log("foo");
    }
    return {
        doSomething: doSomething
    }
});

//otherModule.js
require(["someModule"], function(someModule){
    someModule.doSomething();
});
  • Syntaxe compacte

  • chargement synchrone

  • node.js, browserify, webpack

  • Chargement asynchrone

  • RequireJS

  • Renommage à l'import:

Modules

ES6

ES6

import {$BANKRUPTCY_MIN_DEBT as minBank,
    $SEQUESTRATION_MIN_DEBT as minSeq
    } from './Constants';

function isEligibleForBankruptcySequestration(
    isScottish, debtTotal) {
   
    var minDebt;

    if(isScottish) { minDebt = minSeq }
        else { minDebt = minBank };

    return debtTotal >= minDebt;

}
// Constants.js

var $BANKRUPTCY_MIN_DEBT = 1001;
var $SEQUESTRATION_MIN_DEBT = 3000;

export $BANKRUPTCY_MIN_DEBT;
export $SEQUESTRATION_MIN_DEBT;

Fonctionnalitées ES2015

Déclarations de variables

let foo = 4;

foo = 5;

const bar = {};

bar.foo = 'bar';

lorsqu'il est utilisé dans une boucle le scope de let est limité à la boucle.

(ce n'était pas le cas avec "var")

function doSomething() {
  let i = 4;
  for (let i = 0; i < 50; i++) {
    console.log(i)
  }
  console.log(i):
}

String interpolations

const name = 'white'; const myOldSchoolString = 'yo Mr ' + name;

const myEs2015String = `yo Mr ${name}`;

Arrow function (lambda)

Une arrow function est une fonction qui ne crée pas de nouveaux contexte this.

const myLambda = () => {

}

//parfait pour les callbacks myAsyncCall(myParam, (data) => {

})

myPromise()
  .then(data => {

  })
  .catch(err => {

  })

Plus de 

var self = this;

Si il n y a qu'un seul paramètre, les parenthèses sont optionnelles

Destructuring

const obj = { test: 123, test2: 456, test3: 789 }

const { test2, test3 } = obj

console.log(test2) // 456
console.log(test3) // 789 

...spread

Spread accepte une collection (Array ou Object)

const add = (a, b) => a + b;
let args = [3, 5];
add(...args);
let cde = ['c', 'd', 'e'];
let scale = ['a', 'b', ...cde, 'f', 'g']; 
// ['a', 'b', 'c', 'd', 'e', 'f', 'g']
let mapABC  = { a: 5, b: 6, c: 3};
let mapABCD = { ...mapABC, d: 7}; 
// { a: 5, b: 6, c: 3, d: 7 }

S'utilise lors de l'appel de la fonction

...rest

Rest partage la syntaxe de Spread, mais permet à une fonction d’accéder à un nombre variable de paramètres.

function add(...numbers) {
  return numbers[0] + numbers[1];
}
add(3, 2);        // 5
function print(a, b, c, ...more) {
  console.log(more[0]);
  console.log(arguments[0]);
}
print(1, 2, 3, 4, 5); // 4  1

S'utilise lors de la déclaration de la fonction

//modern style
const addEs6 = (...numbers) => numbers.reduce((p, c) => p + c, 0);

addEs6(1, 2, 3);  // 6

Les Promises

Abstraction qui permet d'écrire du code asynchrone lisible et maintenable.

function myPromisedTimer (timer) {
  return new Promise((resolve, reject) => {
    if(typeof timer !== 'number')
      return reject(new Error('timer must be a number'))
    setTimeout(() => {
      resolve(`${timer} second later`);
    },timer * 1000)
  })
}

myPromisedTimer(6)
  .then(message => console.log(message))
  .catch(err => console.error(err))

Pour les vieux navigateurs, il faudra utiliser un polyfill.

Les Promises (suite)

Enchainement

function myPromisedTimer (timer) {
  return new Promise((resolve, reject) => {
    if(typeof timer !== 'number')
      return reject(new Error('timer must be a number'))
    setTimeout(() => {
      resolve(timer * 2);
    },timer * 1000)
  })
}

myPromisedTimer(6)
  .then(newTimer => {
    return myPromisedTimer(9);
  })
  .then(newTimer => {
    return myPromisedTimer(2)
  })
  .catch(err => console.error(err))

Les Promises (suite)

Traitements parallèles

Promise.all([
  myPromisedTimer(4),
  myPromisedTimer(8),
  anotherPromise()
])
  .then(response => {
    //response is an array of 3
  })
  .catch(err => console.error(err))

Les Classes

export class User {
  constructor(name) {
    this.name = name
  }

  doSomething() {
    console.log(this.name);
  }

  static aStaticMethod() {
    
  }
}

const myUser = new User('toto')
export function User(name) {
  this.name = name
}

User.prototype.doSomething() {
  console.log(this.name);
}

User.aStaticMethod() {
    
}

var myUser = new User('toto')

Les Classes

import {Person} from './Person'

export class User extends Person {
  constructor(name, email) {
    super(email)
    this.name = name
  }

  doSomething() {
    console.log(this.name);
  }
}

const myUser = new User('toto', 't@gm')

myUser.sendEmail()
export class Person {
  constructor(email) {
    this.email = email
  }
  
  sendEmail() {

  }
}

Héritage

ES7/2016 async await

const fetchPosts = async () => {
  let result
  try {
    const response = await fetch('http://webapi/post')
    result = response.json()
  } catch (err) {
    console.error(err)
  }
  return result
}


ES7/2016 décorators

function readOnly (target, key, descriptor) {
  descriptor.writable = false
  return descriptor
}

class Cat {
  @readOnly
  miaule() {
    return `${this.name} says miaou`
  }
}

décorer une propriété

ES7/2016 décorators

function isSuperHero (target) {
  target.isSuperHero = true
  return target
}

@isSuperHero
class Cat {
  @readOnly
  miaule() {
    return `${this.name} says miaou`
  }
}

console.log(Cat.isSuperHero) //true

décorer une classe

Introduction

Application Web centrée SERVEUR

Application Web centrée CLIENT

Single Page Application (SPA)

Historique du Web "Riche"

Dans les années 90, les RIA c’est… des applets Java !

Dans les années 2000, on voit apparaître…

  • Adobe Flash
  • GWT (2006)
  • Silverlight (2007)
  • ExtJS (2007)
  • JavaFX (2008)
  • Les frameworks MVC JavaScript
    • Backbone.js (2010)
    • Ember.js (2011)
    • AngularJS (2012)
    • React.js (2013)
    • Vue.js (2014)

Et en 2016...

M.E.A.N.

LAMP

MEAN

 

2

ou

ou

ou

MEAN?

  • 100% Javascript
  • persistence au format JSON
  • Trés rapide grace a Node
  • Flexible
  • Scalable et facile à maintenir
  • Facile à déployer

Environnement de développement

Node.js & npm

Node.js est utilisé comme plateforme de développement.

npm est le gestionnaire de paquets pour Node.js, et permet d'installer les outils de l'environnement de développement ainsi que les dépendances de notre projet.

$ npm search
nom-du-module $ npm install nom-du-module $ sudo npm install nom-du-module -g $ npm install $ npm update

Package.json

  "dependencies": {
    "@angular/http": "2.0.0-rc.2",
    "@angular/common": "2.0.0-rc.2",
    "@angular/compiler": "2.0.0-rc.2",
    "@angular/core": "2.0.0-rc.2",
    "@angular/forms": "^0.1.0",
    "@angular/platform-browser": "2.0.0-rc.2",
    "@angular/platform-browser-dynamic": "2.0.0-rc.2",
    "@angular/platform-server": "2.0.0-rc.2",
    "@angular/router": "3.0.0-alpha.7",
    "@angular/router-deprecated": "2.0.0-rc.2",

    "ie-shim": "^0.1.0",
    "core-js": "^2.4.0",
    "rxjs": "5.0.0-beta.9",
    "zone.js": "~0.6.12"
  }
  • Transpilation ES6 => ES5
  • Interprétation du JSX

webpack

module bundler.

The

  • production

  • unbiased

  • flexible

  • extensible

  • open source

Webpack va prendre en charge le build et le développement de A à Z.

Installation

$ npm i webpack webpack-dev-server -D

Une fois l'installation terminée, nous avons accés à ces deux éxécutables dans les "scripts" du package.json

{ 
  "scripts": { 
    "build:prod": "webpack --progress -p",
    "server:dev":
    "webpack-dev-server --inline --progress"
  }
}

webpack.config.js

module.exports =  { debug: true, cache: true,
    devtool: 'cheap-module-eval-source-map', entry: { vendor: './src/vendor.js', main: './src/app.js', }, output: {
    path: 'dist', filename: '[name].bundle.js', sourceMapFilename: '[name].map', chunkFilename: '[id].chunk.js' },
    plugins: [ new DefinePlugin({ 'ENV': JSON.stringify(process.env.ENV), }), ], module: { loaders: [ { test: /\.js$/,
    loader: 'babel-loader' }, { test: /\.css$/, loader: 'style!css' }, { test: /\.html$/, loader: 'raw-loader' }, ]   }
    });

Hot Module Replacement

Remplace le live-reload

Applique des changements dans votre application sans rechargement de la page.

Fonctionne grace à un webSocket.

Nécessite l'utilisation de plugins.

ESLint

Outils de qualimétrie pour le js et le jsx

Fonctionne avec l'ensemble des outils de dev traditionnels: IDE, build ....

.eslintrc

Fichier de configuration à placer dans le repertoire concerné.

Possibilité d'avoir plusieurs fichiers par projet.

{
  "parser": "babel-eslint",
  "extends": "airbnb",
  "env": {
    "browser": true,
    "node": true
  },
  "rules": {
    "semi": [
      "error",
      "never"
    ],
    "arrow-body-style": 0,
    "arrow-parens": 0,
    "no-confusing-arrow": 0,
    "no-console": 0
  }
}

Example pour React