Quais são as diferenças entre o SystemJS e o Webpack?

222

Estou criando meu primeiro aplicativo Angular e gostaria de descobrir qual é o papel dos carregadores de módulos. Por que precisamos deles? Tentei pesquisar e pesquisar no Google e não consigo entender por que precisamos instalar um deles para executar nosso aplicativo?

Não seria suficiente usar apenas importpara carregar coisas dos módulos de nós?

Eu segui este tutorial (que usa SystemJS) e isso me faz usar o systemjs.config.jsarquivo:

/**
 * 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 que precisamos desse arquivo de configuração?
Por que precisamos do SystemJS (ou WebPack ou outros)?
Finalmente, na sua opinião, qual é o melhor?

smartmouse
fonte
4
Aqui você pode ler um artigo realmente bom para comparar SystemJs (Jspm) com Webpack ilikekillnerds.com/2015/07/jspm-vs-webpack .
Sweta
veja esta resposta stackoverflow.com/a/40670147/2545680 para SystemJS
Max Koretskyi

Respostas:

135

Se você for para a página SystemJS Github, verá a descrição da ferramenta:

Carregador de módulo dinâmico universal - carrega módulos ES6, AMD, CommonJS e scripts globais no navegador e no NodeJS.

Como você usa módulos no TypeScript ou ES6, precisa de um carregador de módulos. No caso do SystemJS, o systemjs.config.jsnos permite configurar a maneira pela qual os nomes dos módulos são correspondidos com seus arquivos correspondentes.

Este arquivo de configuração (e SystemJS) é necessário se você o usar explicitamente para importar o módulo principal do seu aplicativo:

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

Ao usar o TypeScript e configurar o compilador para o commonjsmódulo, o compilador cria código que não é mais baseado no SystemJS. Neste exemplo, o arquivo de configuração do compilador de texto datilografado aparecerá assim:

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

O Webpack é um empacotador de módulo flexível. Isso significa que ele vai além e não apenas manipula os módulos, mas também fornece uma maneira de empacotar seu aplicativo (arquivos concat, arquivos uglify, ...). Ele também fornece um servidor de desenvolvimento com recarga de carga para desenvolvimento.

O SystemJS e o Webpack são diferentes, mas com o SystemJS, você ainda tem trabalho a fazer (com o construtor Gulp ou SystemJS, por exemplo) para empacotar seu aplicativo Angular2 para produção.

Thierry Templier
fonte
2
Quando você diz "com o SystemJS, você ainda tem trabalho a fazer (com o construtor Gulp ou SystemJS, por exemplo) para empacotar seu aplicativo Angular2 para produção" é com o que eu entro atualmente npm start?
22416
5
De fato, para produção, não é eficiente carregar muitos arquivos para módulos (arquivos individuais (~ 300 solicitações) ou agrupados (~ 40 solicitações)). Você precisa reunir tudo em um ou dois (seu código e código de biblioteca de terceiros), compilar offline seus modelos (ngc) e aproveitar a agitação da árvore para minimizar o peso dos pacotes configuráveis. Este artigo pode lhe interessar: blog.mgechev.com/2016/06/26/… . Você também precisa uglificar arquivos CSS.
Thierry Templier
1
Com início NPM, você "simplesmente" iniciar um servidor que irá servir o seu pedido com base na configuração SystemJS para módulos ...
Thierry Templier
11
O Google mudou oficialmente para o webpack. Então acho que é melhor ficar com o que a maioria da comunidade usaria. Estou migrando meu projeto systemJS para o webpack em breve. Não tenho muita certeza de como fazê-lo.
user2180794
1
@JonasKello é o caso do CLI angular. Veja este link: github.com/angular/angular-cli na seção "Atualização do Webpack"?
Thierry Templier
190

SystemJS trabalha no lado do cliente. Carrega módulos (arquivos) dinamicamente sob demanda quando eles são necessários. Você não precisa carregar o aplicativo inteiro antecipadamente. Você pode carregar um arquivo, por exemplo, dentro de um manipulador de cliques de botão.

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

Além de configurá-lo para funcionar, é tudo o que há no SystemJS! Agora você é um profissional do SystemJS!

O Webpack é totalmente diferente e leva uma eternidade para dominar. Ele não faz o mesmo que SystemJS, mas, ao usar o Webpack, o SystemJS se torna redundante.

O Webpack prepara um único arquivo chamado bundle.js - esse arquivo contém todo HTML, CSS, JS etc. Como todos os arquivos são agrupados em um único arquivo, não há mais a necessidade de um carregador lento como o SystemJS (onde arquivos individuais são carregados como necessário).

A vantagem do SystemJS é esse carregamento lento. O aplicativo deve carregar mais rápido porque você não está carregando tudo em um único clique.

A vantagem do Webpack é que, embora o aplicativo possa demorar alguns segundos para carregar inicialmente, uma vez carregado e armazenado em cache, é extremamente rápido.

Prefiro o SystemJS, mas o Webpack parece ser mais moderno.

O início rápido do Angular2 usa o SystemJS.

A CLI angular usa o Webpack.

O Webpack 2 (que oferece agitação de árvores) está na versão beta, talvez seja um momento ruim para mudar para o Webpack.

Nota O SystemJS está implementando o padrão de carregamento do módulo ES6 . O Webpack é apenas mais um módulo npm.

Executores de tarefas (leitura opcional para quem deseja entender o ecossistema no qual o SystemJS pode existir)

Com o SystemJS, sua única responsabilidade é o carregamento lento de arquivos, por isso ainda é necessário minimizar esses arquivos, transpilar esses arquivos (por exemplo, do SASS para CSS) etc. Esses trabalhos que devem ser executados são conhecidos como tarefas .

O Webpack, quando configurado, faz isso corretamente para você (e agrupa a saída). Se você quiser fazer algo semelhante ao SystemJS, normalmente usaria um executor de tarefas JavaScript. O executor de tarefas mais popular é outro módulo npm chamado gulp .

Portanto, por exemplo, o SystemJS pode carregar preguiçosamente um arquivo JavaScript minificado que foi minificado pelo gulp. O Gulp, quando configurado corretamente, pode reduzir os arquivos em tempo real e recarregar ao vivo. O recarregamento ao vivo é a detecção automática de uma alteração de código e uma atualização automática do navegador para atualização. Ótimo durante o desenvolvimento. Com CSS, a transmissão ao vivo é possível (ou seja, você vê a página atualizar os novos estilos sem que a página seja recarregada).

Existem muitas outras tarefas que o Webpack e o gulp podem executar, que seriam numerosas demais para serem abordadas aqui. Eu forneci um exemplo :)

danday74
fonte
7
Eu também acho o SystemJS e o JSPM muito mais fáceis de trabalhar do que o webpack. Também achei os pacotes de produção menores (em comparação com outro projeto de exemplo do webpack). Aqui está o meu post sobre o tema: stackoverflow.com/questions/40256204/...
Peter Salomonsen
7
Você pode usar o Webpack & Lazy loading usando angular2-router-loader. Veja mais medium.com/@daviddentoom/…
Alex Klaus
36
Você está errado sobre o Webpack! Permite combinar pacotes com carregamento lento. Além disso, agrupa de forma transparente módulos adiados em pedaços.
dizel3d
3
@AlexKlaus, obrigado pelo exemplo! Eu estava procurando por algo assim :)
tftd
3
"O Webpack é totalmente diferente e leva uma eternidade para dominar. Ele não faz o mesmo que o SystemJS, mas, ao usar o Webpack, o SystemJS se torna redundante." Eu tenho que discordar. O SystemJS ainda permite o desenvolvimento de desenvolvedores sem ter que criar constantemente para cada alteração. Posso fazer uma alteração em um arquivo TS, salvar (que chama automaticamente tsc.exe e compilá-lo), recarregar minha página e não apresentar problemas. Com o Webpack, tenho que reconstruir, o que pode levar muito mais tempo, pois ele recompilará e construirá tudo . Não consegui encontrar nenhuma maneira de evitar isso usando o Webpack.
Polantaris
0

Até agora eu estava usando systemjs. Ele estava carregando os arquivos um por um e o primeiro carregamento demorava de 3 a 4 segundos sem arquivos minificados. Depois de mudar para o webpack, obtive uma grande melhoria de desempenho. Agora é preciso apenas carregar um arquivo de pacote configurável (também polyfills e libs de fornecedores que quase nunca são alterados e quase sempre são armazenados em cache) e é isso. Agora, leva apenas um segundo para carregar o aplicativo do lado do cliente. Nenhuma lógica adicional do lado do cliente. Quanto menor o número de arquivos individuais carregados, maior o desempenho. Ao usar systemjs, você deve pensar em importar módulos dinamicamente para economizar desempenho. Com o webpack, você se concentra principalmente em sua lógica, pois o desempenho ainda será bom quando o pacote for reduzido e armazenado em cache no navegador.

Hrach Gyulzadyan
fonte
3
Você respondeu apenas a uma das perguntas do OP, seria melhor fazer um comentário.
Ben