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
    					

    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

    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
    					

    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"
      }
    }
    					

    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();

    Transpilation

    • Babel par défaut
    • Support de Traceur et TypeScript
    • Transpilation au runtime

    Performances

    • Éviter la transpilation au runtime
    • Créer un bundle avec le CLI de JSPM
    
    jspm bundle clock-component --watch
    

    Performances

      Transpilation au runtime (180 fichiers) :

      293 requêtes : 12.75 secondes


      Bundle avec l'option --watch :

      21 requêtes : 2.35 secondes

    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

    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;
    }
    

    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();
    

    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>
    						

    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