我正在创建我的第一个Angular应用程序,我要弄清楚模块加载器的角色是什么。 我们为什么需要他们? 我试着在谷歌上搜索,我不明白为什么我们需要安装其中一个来运行我们的应用程序?

难道仅仅使用import从节点模块中加载东西还不够吗?

我遵循了这个教程(使用SystemJS),它让我使用SystemJS .config.js文件:

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

为什么我们需要这个配置文件? 为什么我们需要SystemJS(或WebPack或其他)? 最后,在你看来哪个更好?


如果你去SystemJS的Github页面,你会看到这个工具的描述:

通用动态模块加载器——在浏览器和NodeJS中加载ES6模块、AMD、CommonJS和全局脚本。

因为你在TypeScript或ES6中使用模块,所以你需要一个模块加载器。在SystemJS的情况下,SystemJS .config.js允许我们配置模块名称与相应文件匹配的方式。

这个配置文件(和SystemJS)是必要的,如果你显式地使用它来导入你的应用程序的主模块:

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

当使用TypeScript并将编译器配置为commonjs模块时,编译器创建的代码不再基于SystemJS。在这个例子中,typescript编译器配置文件看起来是这样的:

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

Webpack是一个灵活的模块捆绑器。这意味着它更进一步,不仅处理模块,而且还提供了一种打包应用程序的方法(concat文件,uglify文件,…)。它还为开发提供了一个具有重载功能的开发服务器。

SystemJS和Webpack是不同的,但是使用SystemJS,你仍然需要做一些工作(例如使用Gulp或SystemJS builder)来打包你的Angular2应用程序以用于生产。


SystemJS工作在客户端。它在需要模块(文件)时动态加载它们。你不需要预先加载整个应用程序。例如,您可以在按钮单击处理程序中加载一个文件。

系统JS代码:

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

除了配置它工作,这就是SystemJS的全部!你现在是SystemJS专家了!

Webpack是完全不同的,需要很长时间才能掌握。它不像SystemJS那样做同样的事情,但是当使用Webpack时,SystemJS变得多余了。

Webpack准备了一个叫做bundle.js的文件——这个文件包含了所有的HTML, CSS, JS等。因为所有文件都捆绑在一个文件中,所以现在不需要像SystemJS这样的惰性加载器(其中单个文件 根据需要加载)。

SystemJS的优点是这种惰性加载。应用程序应该加载得更快,因为你不是在一次命中加载所有东西。

Webpack的优点是,虽然应用程序最初可能需要几秒钟来加载,但一旦加载和缓存它就会像闪电一样快。

我更喜欢SystemJS,但Webpack似乎更时髦。

Angular2快速入门使用SystemJS。

Angular CLI使用Webpack。

Webpack 2(将提供摇树功能)还在测试阶段,所以现在可能不是迁移到Webpack的好时机。

注意SystemJS正在实现ES6模块加载标准。Webpack只是另一个npm模块。

任务运行器(想要了解SystemJS可能存在的生态系统的人可选阅读)

SystemJS的唯一职责是惰性加载文件,所以仍然需要一些东西来缩小这些文件,编译这些文件(例如从SASS到CSS)等等。这些必须完成的工作被称为任务。

Webpack在配置后,会正确地为您执行此操作(并将输出捆绑在一起)。如果你想用SystemJS做一些类似的事情,你通常会使用JavaScript任务运行器。最流行的任务运行器是另一个叫做gulp的npm模块。

因此,例如,SystemJS可能会延迟加载一个经过gulp简化的JavaScript文件。Gulp,当正确设置,可以减少文件在飞行和实时重载。实时重新加载是自动检测代码更改并自动刷新浏览器以进行更新。在开发过程中很棒。有了CSS,实时流是可能的(即你看到页面更新了新的样式,甚至不需要页面重新加载)。

Webpack和gulp还可以执行许多其他任务,这些任务太多了,在这里就不赘述了。我已经提供了一个例子:)


So far I was using systemjs. It was loading files one by one and first load was taking 3-4 seconds without minified files. After switching to webpack I got a great performance improvement. Now it takes only to load one bundle file (also polyfills and and vendor libs which almost never changed and almost always cached) and that's it. Now it takes just a second to load the client side app. No additional client side logic. As less the number of individual files loaded as higher the performance. When using systemjs you should think about importing modules dynamically to save in performance. With webpack you focus mainly on your logic because performance will be still be good once the bundle is minified and cached in you browser.