[英]What is the need for SystemJS in Angular2?
我是Angular和Angular2的初學者。 我對工作流程的結構感到困惑。 我一直在查看Angular2站點中的示例項目 。
如果我錯了,請糾正我,但我所知道的是所有的打字稿都是由打字稿編譯器轉換成javascript的。 然后編譯的javascript實際上是在瀏覽器中運行的。
現在,如果我使用ES6導入語句將javascript文件導入typescript,如下所示:
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,它顯示所有import語句都轉換為require()語句。 首先,require()在ES5 js文件中是如何工作的,如果是這樣的話,那么SystemJS是怎么做的。
這讓我很困惑。 任何幫助將不勝感激。
當tsc
將tsc
編譯成JavaScript時,你最終會在本地系統上獲得一堆js文件。 他們不知何故需要加載到瀏覽器中。 由於瀏覽器不支持本機ES6模塊加載,因此您有兩個選項,要么以正確的依賴順序將它們全部放入index.html
文件中,要么您可以使用加載程序為您完成所有操作。 您為所有模塊指定了根,然后所有文件由該加載器以正確的依賴順序加載和執行。 有許多加載器:requirejs,webpack,systemjs等。 在你的特殊情況下,它是systemjs。
查看ts文件的已轉換的javascript,它顯示所有import語句都轉換為require()語句。
是的,這是SystemJs
加載包的一種方式。 它使用require()
和exports
語法,因為這是用於加載包的CommonJS
語法,並且您在tsconfig.json
指定了此類型:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
如果您要放置module:'es6'
,您會看到在編譯的javascript文件中保留了導入和導出語句。 但是,如前所述,您仍然無法使用此語法,因為瀏覽器本身不支持它。 如果您要放置module:'amd'
,您會看到使用define()
不同語法。 我想systemjs loader在angular2
starter tutorial中是首選,因為它實際上可以加載tsc
支持的所有模塊類型。 但是,如果要將模塊加載為es6
模塊,則必須將module: 'system'
放在tsconfig.json
。 它是一個模塊系統,旨在遵循es6 modules
標准並使用,直到在瀏覽器中完全支持es6 modules
。
設置如何工作
在index.html
添加以下腳本:
<script>
System.import('app').catch(function (err) {
console.error(err);
});
</script>
這是在加載index.html
時執行的。 import('app')
方法指示systemjs
加載app
模塊,該模塊映射到項目目錄結構中的app
文件夾,由systemjs.config.js
的配置指定:
map: {
// our app is within the app folder
app: 'app',
SystemJs在該文件夾中查找main.js
文件。 當找到app/main.js
並將其加載到瀏覽器中時,在其代碼中找到require
的調用:
var app_module_1 = require('./app.module');
然后app.module.js
從本地系統獲取app.module.js
文件。 這又有其自身的依賴性,如:
var core_1 = require('@angular/core');
循環重復 - 加載,搜索依賴關系,加載它們並執行。 這就是systemjs
在瀏覽器中解析,加載和執行所有依賴的方式。
為什么需要映射到核心@angular庫
在systemjs.config.ts
文件中有映射到核心@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
systemjs
加載到瀏覽器中。 它解析其內容並找到以下內容:
var core_1 = require('@angular/core');
現在systemjs
知道它需要解析並加載@angular/core
。 它首先經歷了檢查mappings
的過程,如文檔中所指定的:
map選項與path類似,但在規范化過程中很早就起作用了。 它允許您將模塊別名映射到位置或包。
我稱之為命名模塊的解決方案。 所以,它找到映射和替代@angular/core
與node_modules/@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
,這至少不是一個好的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.