私はAngularとAngular2の完全な初心者です。ワークフローの構造について混乱しています。 Angular2サイトにある サンプルプロジェクト を見てきました。
私が間違っている場合は修正しますが、今まで知っていることは、すべてのTypeScriptがTypeScriptコンパイラーによって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()ステートメントに変換されていることが示されています。まず、ES5でrequire()がどのように機能するか jsファイル、2番目の場合は、SystemJSが実行していることです。
これは本当に私を混乱させます。どんな助けも大歓迎です。
tsc
がTypeScriptをJavaScriptにコンパイルすると、ローカルシステムに大量のjsファイルが作成されます。何らかの形でブラウザにロードする必要があります。ブラウザはまだネイティブES6モジュールの読み込みをサポートしていないため、2つのオプションがあります。それらをすべて、依存関係の正しい順序で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ローダーは、tsc
でサポートされているすべてのモジュールタイプを実際にロードできるため、angular2
スターターチュートリアルで推奨されていると思います。ただし、モジュールを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
に、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
によってブラウザーで解決、ロード、実行される方法です。
@ 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',
ここで最初に理解することは、これらがmappingsであり、依存関係ではないことです。つまり、どのファイルも@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
をチェックするプロセスを通過します。
マップオプションはパスに似ていますが、正規化プロセスの非常に早い段階で機能します。モジュールのエイリアスを場所またはパッケージにマッピングできます。
名前付きモジュールによる解決と呼びます。そのため、マッピングを検出し、@angular/core
をnode_modules/@angular/core
に置き換えます。これが実際のファイルが置かれる場所です。
systemjs
はnode.js
で使用されるアプローチを模倣しようとすると思います。この場合、単にrequire('bar.js')
と['/', '../', or './']
のように、相対パス識別子node.js
なしでモジュールを指定できます。
node.jsは現在のモジュールの親ディレクトリで開始し、/ node_modulesを追加し、その場所からモジュールをロードしようとします。
必要に応じて、次のような相対パスを使用して、名前付きマッピングの使用を避け、インポートすることができます。
import {NgModule} from '../node_modules/@angular/core';
ただし、これは、プロジェクト内の@angular.core
へのすべての参照と、@angular
を含むlibファイルで実行する必要があります。