我正在创建我的第一个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的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还可以执行许多其他任务,这些任务太多了,在这里就不赘述了。我已经提供了一个例子:)