2016-11-18 50 views
37

我是Angular和Angular2的完整初學者。我對工作流程的結構感到困惑。我一直在尋找Angular2網站上的sample projectAngular2中SystemJS的需求是什麼?

糾正我,如果我錯了,但直到現在我知道的是,所有的打字稿是由打字稿編譯器轉譯成JavaScript的。然後編譯的JavaScript實際上是在瀏覽器中運行的。

現在,如果我使用ES6 import語句,如以下各項導入javascript文件到打字稿:

import { NgModule }  from '@angular/core'; 

爲什麼我需要再次使用SystemJS加載它們 - :

map: { 
     // our app is within the app folder 
     app: 'app', 
     // angular bundles 
     '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 

我的意思是不是反作用? 查看ts文件的轉譯後的javascript,它顯示所有導入語句都轉換爲require()語句。首先,require()如何在ES5 js文件中工作,其次如果是這種情況,SystemJS會做什麼。

這真讓我困惑。任何幫助將不勝感激。

+0

AFAIK,瀏覽器還不支持ES6。所以SystemJS幫助它。無論如何等待別人的詳細答案。 – v1shnu

回答

74

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,這至少不是一個好的解決方案。

+0

@Maximus那麼爲什麼我們要在'system.config.js'中分別指定Angular2依賴關係。告訴我一些事情,'app_module'文件具有Angular2的所有依賴關係,爲什麼我們不能只加載它,而忘記單獨提及依賴關係。即使http模塊基於rxjs,@ angular/http和rxjs依賴關係也是分開指定的。 –

+0

_那麼爲什麼我們要在system.config.js_中單獨指定Angular2依賴關係 - 在哪裏顯示代碼。如果你的意思是'rxjs':'npm:rxjs',它不是一個依賴項,它是一個映射條目 –

+0

@Maximus [link](https://angular.io/docs/ts/latest/quickstart.html )轉到'system.config.js'選項卡。你會看到所有的angular2條目都被映射出來了。 **爲什麼需要將它映射出來?**爲什麼我問的是因爲在打印稿編譯期間所有文件都被轉換爲可以使用SystemJS的模塊(這裏不需要轉儲),所以如果我必須添加我需要知道所有的嵌套依賴和所有位置的依賴關係的絕對路徑。例如,我需要知道'@ angular/http'依賴於'rxjs',我需要爲它們提供映射。 –