What are differences between SystemJS and Webpack?

smartmouse picture smartmouse · Jul 8, 2016 · Viewed 92.2k times · Source

I'm creating my first Angular application and I would figure out what is the role of the module loaders. Why we need them? I tried to search and search on Google and I can't understand why we need to install one of them to run our application?

Couldn't it be enough to just use import to load stuff from node modules?

I have followed this tutorial (that uses SystemJS) and it makes me to use systemjs.config.js file:

/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function(global) {
  // map tells the System loader where to look for things
  var map = {
    'app':                        'transpiled', // 'dist',
    '@angular':                   'node_modules/@angular',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    'rxjs':                       'node_modules/rxjs'
  };
  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
  };
  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'forms',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // Individual files (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // Bundled (~40 requests):
  function packUmd(pkgName) {
    packages['@angular/'+pkgName] = { main: '/bundles/' + pkgName + '.umd.js', defaultExtension: 'js' };
  }
  // Most environments should use UMD; some (Karma) need the individual index files
  var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
  // Add package entries for angular packages
  ngPackageNames.forEach(setPackageConfig);
  var config = {
    map: map,
    packages: packages
  };
  System.config(config);
})(this);

Why we need this configuration file?
Why we need SystemJS (or WebPack or others)?
Finally, in your opinion what is the better?

Answer

danday74 picture danday74 · Oct 27, 2016

SystemJS works client side. It loads modules (files) dynamically on demand when they are needed. You don't have to load the entire app up front. You could load a file, for example, inside a button click handler.

SystemJS code:

// example import at top of file
import myModule from 'my-module'
myModule.doSomething()

// example dynamic import (could be placed anywhere in your code)
// module not loaded until code is hit
System.import('my-module').then((myModule) {
  // myModule is available here
  myModule.doSomething()
});

Other than configuring it to work, that's all there is to SystemJS! You are now a SystemJS pro!

Webpack is entirely different and takes forever to master. It does not do the same thing as SystemJS but, when using Webpack, SystemJS becomes redundant.

Webpack prepares a single file called bundle.js - This file contains all HTML, CSS, JS, etc. Because all files are bundled in a single file, there is now no need for a lazy loader like SystemJS (where individual files are loaded as needed).

The upside of SystemJS is this lazy loading. The app should load faster because you are not loading everything in one hit.

The upside of Webpack is that, although the app may take a few seconds to load initially, once loaded and cached it is lightning fast.

I prefer SystemJS but Webpack seems to be trendier.

Angular2 quickstart uses SystemJS.

Angular CLI uses Webpack.

Webpack 2 (which will offer tree shaking) is in beta so maybe it's a bad time to move to Webpack.

Note SystemJS is implementing the ES6 module loading standard. Webpack is just another npm module.

Task runners (optional reading for those who want to understand the ecosystem in which SystemJS might exist)

With SystemJS its sole responsibility is the lazy loading of files so something is still needed to minify those files, transpile those files (e.g. from SASS to CSS), etc. These jobs that must be done are known as tasks.

Webpack, when configured, correctly does this for you (and bundles the output together). If you want to do something similar with SystemJS you would typically use a JavaScript task runner. The most popular task runner is another npm module called gulp.

So, for example, SystemJS might lazy load a minified JavaScript file that has been minified by gulp. Gulp, when setup correctly, can minify files on the fly and live reload. Live reloading is the automatic detection of a code change and an automatic browser refresh to update. Great during development. With CSS, live streaming is possible (i.e. you see the page update the new styles without the page even reloading).

There are many other tasks which Webpack and gulp can perform which would be too numerous to cover here. I've provided an example :)