JSPM & SystemJS



JSPM & SystemJS

0 1


jspm-slides

Slides for JSPM

On Github blemoine / jspm-slides

JSPM & SystemJS

Benoît Lemoine Développeur FullStack (Scala / TypeScript) chez Captain Dash @benoit_lemoine
Samuel Vaillant Développeur Front-End chez Captain Dash @Samouss_28

Les balises script...

<script src="vendor/moment.js"></script>
<script src="vendor/lodash.js"></script>
<script src="vendor/jquery.js"></script>
<script src="vendor/jquery-ui.js"></script>
<script src="vendor/angular.js"></script>
<script src="src/app.js"></script>

...c'est so 2010

Les problèmes de l'approche traditionnelle

  • Les variables globales (_, $, moment, etc.)
  • Les conflits de versions
  • L'ordre d'exécution
  • Les dépendances transitives

Exemple :

Les modules en JS

AMD

define(function (require, exports) {
    var _ = require('lodash');
    exports.add = function add(a, b) {
      return _.add(a, b);
    };
});

Common JS

var _ = require('lodash');

module.exports = {
  add: function add(a, b) {
    return _.add(a, b);
  };
}

Les modules ES6

//MyMath.js
import _ from 'lodash';

export default function add(a, b) {
  return _.add(a, b);
}
export function multiply(a, b) {
  return a * b;
}
import myAdd from './MyMath.js';
import {multiply} from './MyMath.js';

myAdd(1, 2) //3
multiply(2, 3) //6

ES6-Module Polyfill

System JS

JSPM

Utiliser JSPM

Installer JSPM

npm install jspm@beta --save-dev
  • version bêta 0.17-beta13
  • version bêta 0.16 peut s'utiliser en prod
  • version 0.17 beaucoup de changement

Initialiser le projet

jspm init

---

- Init Mode (Quick, Standard, Custom) [Quick]: Quick
- Local package name (recommended, optional): clock-component
- package.json directories.lib [src]: src
- System.config browser baseURL (optional):
- System.config local package main [clock-component.js]: index.js
- System.config transpiler (Babel, Traceur, TypeScript, None) [babel]: babel
  • init mode : Quick
  • Package name : clock-component
  • directory : src
  • baseURL : . (current directory)
  • main : index.js
  • transpiler : babel
  • téléchargement SystemJS
  • téléchargement transpiler
  • Création d'une section dans `jspm` package.json
  • Création des fichiers de configs

jspm.browser.js

SystemJS.config({
  baseURL: ".",
  paths: {
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*",
    "clock-component/": "src/"
  }
});

jspm.config.js 1/2

SystemJS.config({
  transpiler: "plugin-babel",
  packages: {
    "clock-component": {
      "format": "esm",
      "main": "index.js",
      "meta": {
        "*.js": {
          "loader": "plugin-babel"
        }
      }
    }
  }
});

jspm.config.js 2/2

SystemJS.config({
  packageConfigPaths: [
    "github:*/*.json",
    "npm:@*/*.json",
    "npm:*.json"
  ],
  map: {
    "plugin-babel": "npm:systemjs-plugin-babel@0.0.9"
  }
});

Installer des dépendances

L'installation des dépendances peut être faite via :

  • registry
  • github
  • npm
  • custom
jspm install angular
jspm install github:username/repo
jspm install npm:moment
  • JSPM registry: map mot clé sur un provider spécifique (angular -> github:angular/bower-angular)
  • Permet de récupérer les dependances préconfigurer pour éviter de faire de la configuration manuelle (main, dependencies, format)
  • plugin Github / NPM
  • custom registry (ex: BitBucket)
  • Une fois installé les dépendances sont sauvegarder dans la package.json, jspm.config.js

Surcharger le package.json

Principales propriétés qui peuvent être surchargées :

  • main
  • format
jspm install github:user/repo -o "{ main: 'path/to/main' }"

Surcharger le package.json

jspm install github:eligrey/FileSaver.js
warn Package eligrey/FileSaver.js has no "main" entry point set in its package config.
jspm install github:eligrey/FileSaver.js -o "{ main: 'FileSaver.js' }"
"overrides": {
  "github:eligrey/FileSaver.js@master": {
    "main": "FileSaver.js"
  }
}
  • installation d'un package sans package.json
  • warning pas de main
  • installation avec un override
  • sauvegarde de l'override dasn le package.json

Utiliser SystemJS

index.html
<script src="./jspm_packages/system.js"></script>
<script src="./jspm.browser.js"></script>
<script src="./jspm.config.js"></script>
<script>System.import('bootstrap.js');</script>
bootstrap.js
// import dependency
import moment from 'moment';

// import our module
import ClockComponent from 'clock-component';
// or
import ClockComponent from './src/index.js';

const timestamp = moment().unix();
const component = ClockComponent();

component.render();
  • mode dev
  • ordre des fichiers important

Transpilation

  • Babel par défaut
  • Support de Traceur et TypeScript
  • Transpilation au runtime
  • N requêtes pour N fichiers
  • latence dû à la transpilation
  • Maximum de requête en parralèles (FF & Chrome -> 6)

Performances

  • Éviter la transpilation au runtime
  • Créer un bundle avec le CLI de JSPM
jspm bundle clock-component --watch
  • éviter transpile runtime
  • génération d'un bundle -> un seul fichier
  • génération de sourcemap pour pouvoir lire le code
  • rebuild uniquement le fichier qui a changé grâce à un systeme de cache

Performances

Transpilation au runtime (180 fichiers) :

293 requêtes : 12.75 secondes

Bundle avec l'option --watch :

21 requêtes : 2.35 secondes

  • avantage du runtine, rien besoin de faire fonctionne tout seul
  • pratique pour tester des techno, POC
  • c'est tout passé au bundle dès que possible

Production

Création d'un bundle auto exécutable (via SystemJS Builder) :

jspm build bootstrap.js app.bundle.js

Principales options supportées :

  • minification
  • source maps
  • format
  • runtime
  • rollup
  • génération d'un bundle
  • plus besoin de fichier de config ni de SystemJS
  • rollupjs module bundler nouvelle génération
  • Tree-shaking

Tree-shaking 1/2

bootstrap.js
import moment from 'moment';
import ClockComponent from './src/index.js';

const timestamp = moment().unix();
const component = ClockComponent();

component.render();
src/index.js
export default function ClockComponent() {
  return {
    render: () => 'clock component rendering...'
  };
}

export function otherFunction(x) {
	return x + 10;
}
  • Analayse votre code
  • Supprime le code exporté non utilisé

Tree-shaking 2/2

app.bundle.js
// moment library

function ClockComponent() {
  return {
    render: () => 'clock component rendering...'
  };
}

const timestamp = moment().unix();
const component = ClockComponent();

component.render();
  • Intérêt sur les librairie compatible
  • Fonctionne uniquement avec les modules ES6

Plugins

De nombreux plugins disponibles CSS, JSON...

jspm install css

Usage :

import './style.css!'

Ce qui se passe en réalité :

<head>
  <title>Document</title>
  <link type="text/css" rel="stylesheet" href="style.css">
</head>
  • Intéret avec les modules, tout centralisé
  • Import CSS, HTML

Universal - aka Isomorphic

jspm install --dev npm:express
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server.js';
import {HelloWorld} from 'jspm-react-component';

const app = express();
app.get('/', (req, res) => {
    let componentHTML = ReactDOMServer.renderToString(React.createElement(HelloWorld));
    res.send('' + componentHTML);
});

app.listen('8080', () => console.log('Listening on port 8080'));
jspm run server.js

La concurrence - Webpack

  • Bundle uniquement
  • Pas de package manager
  • Plus à la mode

Conclusion

Liens

Ces slides : http://blemoine.github.io/jspm-slides/#/

JSPM : http://jspm.io

SystemJS https://github.com/systemjs/systemjs

Rollup : http://rollupjs.org

JSPM Beta guide : http://jspm.io/0.17-beta-guide

JSPM & SystemJS