¿Cuáles son las diferencias entre SystemJS y Webpack?

222

Estoy creando mi primera aplicación Angular y averiguaría cuál es el papel de los cargadores de módulos. ¿Por qué los necesitamos? Traté de buscar y buscar en Google y no puedo entender por qué necesitamos instalar uno de ellos para ejecutar nuestra aplicación.

¿No podría ser suficiente usar importpara cargar cosas desde módulos de nodo?

He seguido este tutorial (que usa SystemJS) y me hace usar el systemjs.config.jsarchivo:

/**
 * 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);

¿Por qué necesitamos este archivo de configuración?
¿Por qué necesitamos SystemJS (o WebPack u otros)?
Finalmente, en tu opinión, ¿cuál es el mejor?

ratón inteligente
fuente
44
Aquí puede leer un artículo realmente bueno para comparar SystemJs (Jspm) con Webpack ilikekillnerds.com/2015/07/jspm-vs-webpack .
Sweta
vea esta respuesta stackoverflow.com/a/40670147/2545680 para SystemJS
Max Koretskyi

Respuestas:

135

Si va a la página de SystemJS Github, verá la descripción de la herramienta:

Cargador de módulo dinámico universal: carga módulos ES6, AMD, CommonJS y scripts globales en el navegador y NodeJS.

Debido a que usa módulos en TypeScript o ES6, necesita un cargador de módulos. En el caso de SystemJS, systemjs.config.jsnos permite configurar la forma en que los nombres de los módulos coinciden con sus archivos correspondientes.

Este archivo de configuración (y SystemJS) es necesario si lo usa explícitamente para importar el módulo principal de su aplicación:

<script>
  System.import('app').catch(function(err){ console.error(err); });
</script>

Al usar TypeScript y configurar el compilador para el commonjsmódulo, el compilador crea código que ya no se basa en SystemJS. En este ejemplo, el archivo de configuración del compilador mecanografiado aparecería así:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs", // <------
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}

Webpack es un paquete de módulos flexible. Esto significa que va más allá y no solo maneja módulos, sino que también proporciona una forma de empaquetar su aplicación (archivos concat, archivos uglify, ...). También proporciona un servidor de desarrollo con recarga de carga para el desarrollo.

SystemJS y Webpack son diferentes, pero con SystemJS, todavía tiene trabajo que hacer (con Gulp o SystemJS Builder, por ejemplo) para empaquetar su aplicación Angular2 para producción.

Thierry Templier
fuente
2
Cuando dice "con SystemJS, todavía tiene trabajo que hacer (con Gulp o SystemJS Builder, por ejemplo) para empaquetar su aplicación Angular2 para producción", ¿es con lo que tengo actualmente npm start?
smartmouse
55
De hecho, para la producción, no es eficiente cargar muchos archivos para módulos (archivos individuales (~ 300 solicitudes) o agrupados (~ 40 solicitudes)). Debe reunir todo en uno o dos (su código y el código de la biblioteca de terceros), compilar fuera de línea sus plantillas (ngc) y aprovechar el movimiento de los árboles para minimizar el peso de los paquetes. Este artículo podría interesarle: blog.mgechev.com/2016/06/26/… . También necesita uglify archivos CSS.
Thierry Templier
1
Con npm start, usted "simplemente" inicia un servidor que servirá a su aplicación en función de su configuración de SystemJS para módulos ...
Thierry Templier
11
Google se ha mudado oficialmente a webpack. Así que supongo que es mejor seguir con lo que la mayoría de la comunidad usaría. Estoy migrando mi proyecto systemJS a webpack pronto. Sin embargo, no estoy completamente seguro de cómo hacerlo.
user2180794
1
@JonasKello ese es el caso del cli angular. Consulte este enlace: github.com/angular/angular-cli en la sección "Actualización de paquete web".
Thierry Templier
190

SystemJS funciona del lado del cliente. Carga módulos (archivos) dinámicamente a pedido cuando se necesitan. No tiene que cargar toda la aplicación por adelantado. Podría cargar un archivo, por ejemplo, dentro de un controlador de clic de botón.

Código SystemJS:

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

Aparte de configurarlo para que funcione, ¡ eso es todo lo que hay en SystemJS! Ahora eres un profesional de SystemJS!

Webpack es completamente diferente y lleva mucho tiempo dominarlo. No hace lo mismo que SystemJS pero, cuando usa Webpack, SystemJS se vuelve redundante.

Webpack prepara un único archivo llamado bundle.js: este archivo contiene todos los HTML, CSS, JS, etc. Debido a que todos los archivos están agrupados en un solo archivo, ahora no hay necesidad de un cargador lento como SystemJS (donde los archivos individuales se cargan como necesario).

La ventaja de SystemJS es esta carga lenta. La aplicación debería cargarse más rápido porque no está cargando todo de una vez.

La ventaja de Webpack es que, aunque la aplicación puede tardar unos segundos en cargarse inicialmente, una vez cargada y almacenada en caché, es muy rápida.

Prefiero SystemJS pero Webpack parece estar más de moda.

El inicio rápido de Angular2 usa SystemJS.

CLI angular utiliza Webpack.

Webpack 2 (que ofrecerá sacudidas de árbol) está en versión beta, por lo que quizás sea un mal momento para pasar a Webpack.

Nota SystemJS está implementando el estándar de carga del módulo ES6 . Webpack es solo otro módulo npm.

Corredores de tareas (lectura opcional para aquellos que desean comprender el ecosistema en el que podría existir SystemJS)

Con SystemJS, su única responsabilidad es la carga lenta de archivos, por lo que todavía se necesita algo para minimizar esos archivos, transpilarlos (por ejemplo, de SASS a CSS), etc. Estos trabajos que deben realizarse se conocen como tareas .

Webpack, cuando está configurado, lo hace correctamente por usted (y agrupa la salida). Si desea hacer algo similar con SystemJS, normalmente usaría un corredor de tareas de JavaScript. El corredor de tareas más popular es otro módulo npm llamado gulp .

Entonces, por ejemplo, SystemJS podría cargar de forma diferida un archivo JavaScript minificado que ha sido minificado por gulp. Gulp, cuando se configura correctamente, puede minimizar archivos sobre la marcha y recargar en vivo. La recarga en vivo es la detección automática de un cambio de código y una actualización automática del navegador para actualizar. Genial durante el desarrollo. Con CSS, es posible la transmisión en vivo (es decir, ve que la página actualiza los nuevos estilos sin que la página se vuelva a cargar).

Hay muchas otras tareas que pueden realizar Webpack y Gulp que serían demasiado numerosas para cubrir aquí. He proporcionado un ejemplo :)

danday74
fuente
77
A mí también me parece mucho más fácil trabajar con SystemJS y JSPM que con webpack. También encontré que los paquetes de producción son más pequeños (en comparación con otro proyecto de ejemplo de paquete web). Aquí está mi publicación sobre el tema: stackoverflow.com/questions/40256204/…
Peter Salomonsen
77
Puede usar Webpack & Lazy loading con el uso angular2-router-loader. Ver más medium.com/@daviddentoom/…
Alex Klaus
36
¡Estás equivocado acerca de Webpack! Le permite combinar la agrupación con la carga diferida. Además, agrupa de forma transparente los módulos diferidos en trozos.
dizel3d
3
@AlexKlaus gracias por el ejemplo! Estaba buscando algo así :)
tftd
3
"Webpack es completamente diferente y lleva mucho tiempo dominarlo. No hace lo mismo que SystemJS, pero cuando se usa Webpack, SystemJS se vuelve redundante". Tengo que estar en desacuerdo. SystemJS todavía permite el desarrollo de desarrolladores sin tener que construir constantemente para cada cambio. Puedo hacer un cambio en un archivo TS, guardar (que llamará automáticamente a tsc.exe y compilarlo), luego volver a cargar mi página y no tener ningún problema. Con Webpack, tengo que reconstruir, lo que puede llevar mucho más tiempo porque recompilará y compilará todo . No he podido encontrar ninguna manera de evitar eso usando Webpack.
Polantaris
0

Hasta ahora estaba usando systemjs. Estaba cargando archivos uno por uno y la primera carga tardaba 3-4 segundos sin archivos minificados. Después de cambiar a webpack obtuve una gran mejora en el rendimiento. Ahora solo se necesita cargar un archivo de paquete (también polyfills y libs de proveedores que casi nunca cambiaron y casi siempre se almacenaron en caché) y eso es todo. Ahora solo lleva un segundo cargar la aplicación del lado del cliente. Sin lógica adicional del lado del cliente. Cuanto menor sea el número de archivos individuales cargados, mayor será el rendimiento. Cuando use systemjs, debe pensar en importar módulos dinámicamente para ahorrar en rendimiento. Con webpack te enfocas principalmente en tu lógica porque el rendimiento seguirá siendo bueno una vez que el paquete se minimice y se almacene en caché en tu navegador.

Hrach Gyulzadyan
fuente
3
Solo respondió una de las preguntas de OP, hubiera sido mejor hacer un comentario.
Ben