当tsc
将打字稿编译到JavaScript中时,最终会在本地系统上产生一堆js文件。它们不知何故需要加载到浏览器中。由于浏览器不支持原生ES6模块加载,因此您有两种选择,可以按照正确的依赖顺序将它们全部放入index.html
文件中,也可以使用加载程序完成这些操作。您指定所有模块的根目录,然后所有文件都由该加载程序以正确的依赖关系顺序加载和执行。有很多加载器:requirejs,webpack,systemjs和其他。在你的特定情况下,它是systemjs。
查看ts文件的转译javascript,它显示所有 导入语句转换为require()语句。
是的,这是SystemJs
加载包的一种方式。它采用require()
和exports
语法,因为那是CommonJS
语法装载包和您在指定此类型的tsconfig.json
:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
如果你把module:'es6'
,你会看到在你的编译JavaScript文件的导入和导出陈述被保留。但是,如前所述,由于浏览器本身不支持,因此仍然无法使用此语法。如果您要放入module:'amd'
,则会看到使用define()
的不同语法。因为它实际上可以加载tsc
支持的所有模块类型,所以我认为systemjs loader是angular2
入门教程中的首选。但是,如果要将模块作为es6
模块加载,则必须将module: 'system'
放入您的tsconfig.json
。这是一个模块系统,旨在遵循es6 modules
标准,并在浏览器中使用es6 modules
。
设置是如何工作的
在你index.html
添加下面的脚本:
当加载
index.html
被执行
<script>
System.import('app').catch(function (err) {
console.error(err);
});
</script>
。该import('app')
方法指示systemjs
加载由配置在systemjs.config.js
指定其映射到app
文件夹中的项目目录结构app
模块:
map: {
// our app is within the app folder
app: 'app',
SystemJs查找main.js
文件文件夹中。当app/main.js
是发现和加载到浏览器,它里面的代码require
呼叫发现:
var app_module_1 = require('./app.module');
和systemjs然后取出从本地系统app.module.js
文件。这个依次有自己的依赖,如:
var core_1 = require('@angular/core');
而循环重复 - 加载,搜索依赖,加载它们并执行。这就是所有依赖项在systemjs
的浏览器中解析,加载和执行的方式。
为什么需要
在systemjs.config.ts
文件映射到核心@angular库有映射到核心@angular
模块:
map: {
...
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
首先要了解这里的是,这些映射,而不是依赖关系。这意味着如果你的文件都没有导入@angular/core
,它将不会被加载到浏览器。但是,你可能会看到这个特殊的模块内app/app.module.ts
进口:
import { NgModule } from '@angular/core';
现在,为什么映射在那里。假设systemjs
已将您的app/app.module.js
加载到浏览器中。它解析其内容并找到如下:
var core_1 = require('@angular/core');
现在systemjs
明白,它需要解决和负载@angular/core
。它首先通过检查mappings
的过程中,如在该文档中指定:
地图选项类似于路径,但在归一化 过程的早期作用。它允许您将模块别名映射到 位置或程序包。
我将其称为一个命名模块的决议。因此,它找到映射并用node_modules/@angular/core
替代@angular/core
,这就是真实文件的放置位置。
我认为systemjs
试图模仿node.js
使用的方法,你可以指定一个模块没有相对路径标识符['/', '../', or './']
,简直像这样require('bar.js')
和node.js
:
然后Node.js的在开始的父目录当前模块和 增加/ node_modules,并尝试从该 位置加载模块。
如果你愿意,你可以通过使用类似这样的相对路径避免使用命名的映射和进口:
import {NgModule} from '../node_modules/@angular/core';
然而,这应该是在所有引用该项目和lib文件做@angular.core
,包括@angular
,这至少不是一个好的解决方案。
AFAIK,浏览器还不支持ES6。所以SystemJS帮助它。无论如何等待别人的详细答案。 – v1shnu