簡體   English   中英

Angular2中SystemJS的需求是什么?

[英]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是怎么做的。

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

tsctsc編譯成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/corenode_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM