Angular2中对SystemJS的需求是什么? [英] What is the need for SystemJS in Angular2?

查看:58
本文介绍了Angular2中对SystemJS的需求是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Angular和Angular2的完整入门者.我对工作流程的结构感到困惑.我一直在看Angular2中的示例项目.地点.

I am a complete beginner to Angular and Angular2. I am confused about how the workflow is structured. I have been looking at the sample project that is present in the Angular2 site.

如果我错了,请更正我,但是直到现在我所知道的是,所有打字稿都是由打字稿编译器转译为javascript的.然后,已编译的javascript实际上就是在浏览器中运行的.

Correct me if I am wrong but what I know till now is that all the typescript is transpiled into javascript by the typescript compiler. Then the compiled javascript is actually what runs in the browser.

现在,如果我要使用ES6 import语句将javascript文件导入typescript,如下所示:

Now if I am importing the javascript files into typescript using ES6 import statements like the following-:

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在做什么.

I mean isn't that counter productive ? Looking at the transpiled javascript of the ts files it shows all import statements are converted into require() statements. First of all how does require() work in a ES5 js file, and second if thats the case what is SystemJS doing.

这真让我感到困惑.任何帮助将不胜感激.

This really confusing me. Any help will be greatly appreciated.

推荐答案

tsc将打字稿编译为JavaScript时,您最终会在本地系统上得到一堆js文件.它们需要以某种方式加载到浏览器中.由于浏览器尚不支持本机ES6模块加载,因此您有两个选择,要么按照正确的依赖顺序将它们全部放入index.html文件,要么可以使用加载程序为您完成所有操作.您为所有模块指定根目录,然后该加载器按照正确的依存顺序加载和执行所有文件.加载程序有很多:requirejs,webpack,systemjs等.在您的特定情况下,它是systemjs.

When tsc compiles typescript into JavaScript, you end up with a bunch of js files on your local system. They somehow need to be loaded into a browser. Since browsers don't support native ES6 module loading yet, you have two options, either put them all into your index.html file in the correct order of dependencies, or you can use a loader to do that all for you. You specify the root for all modules, and then all files are loaded and executed by that loader in the correct order of dependencies. There are many loaders: requirejs, webpack, systemjs and others. In your particular case it's systemjs.

查看ts文件的转译javascript,它显示了所有 import语句将转换为require()语句.

Looking at the transpiled javascript of the ts files it shows all import statements are converted into require() statements.

是的,这是SystemJs加载捆绑包的一种方式.它使用require()exports语法,因为这是用于加载捆绑软件的CommonJS语法,并且您在tsconfig.json中指定了此类型:

Yes, this is a way for SystemJs to load bundles. It uses require() and exports syntax because that's the CommonJS syntax for loading bundles and you specified this type in your tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",

如果要放置module:'es6',您会看到在已编译的javascript文件中,保留了import和export语句.但是,如前所述,由于浏览器本身不支持此语法,因此您仍然不能使用此语法.如果要放入module:'amd',则会看到使用define()的不同语法.我想在angular2入门教程中首选systemjs加载器,因为它实际上可以加载tsc支持的所有模块类型.但是,如果要将模块作为es6模块加载,则必须将module: 'system'放入tsconfig.json中.这是一个模块系统,旨在遵守es6 modules标准,并且一直使用到直到浏览器完全支持es6 modules为止.

If you were to put module:'es6', you would see that in your compiled javascript files the import and export statements are preserved. However, as mentioned before, you still can't use this syntax as browsers don't support it natively. If you were to put module:'amd', you would see different syntax that uses define(). I guess the systemjs loader is preferred in angular2 starter tutorial since it actually can load all module types supported by tsc. However, if you want to load modules as es6 modules, you have to put module: 'system' in your tsconfig.json. It's a module system designed to adhere to es6 modules standard and used until there's a full support of es6 modules in browsers.

设置的工作方式

在您的index.html中,添加以下脚本:

In your index.html you add the following script:

<script>
    System.import('app').catch(function (err) {
        console.error(err);
    });
</script>

加载index.html时执行的

. import('app')方法指示systemjs加载app模块,该模块映射到项目目录结构中的app文件夹,该文件夹由systemjs.config.js中的配置指定:

which is executed when index.html is loaded. The import('app') method instructs systemjs to load app module which is mapped to app folder in your project directory structure as specified by the configuration in systemjs.config.js:

map: {
    // our app is within the app folder
    app: 'app',

SystemJs在该文件夹中查找main.js文件.当找到app/main.js并将其加载到浏览器中时,在其代码内将找到require的调用:

SystemJs looks for main.js file in that folder. When app/main.js is found and loaded into a browser, inside it's code the call of require is found:

var app_module_1 = require('./app.module');

和systemjs然后从本地系统获取app.module.js文件.反过来,这也有自己的依赖性,例如:

and systemjs then fetches app.module.js file from local system. This one in turn has its own dependcies, like:

var core_1 = require('@angular/core');

然后重复该循环-加载,搜索依赖关系,加载它们并执行.这就是systemjs在浏览器中解析,加载和执行所有依赖关系的方式.

And the cycle repeats - load, search for dependencie, load them and execute. And this is the way all dependecies are resolved, loaded and executed in a browser by the systemjs.

为什么需要到核心@angular库的映射

systemjs.config.ts文件中,有到核心@angular模块的映射:

In the systemjs.config.ts file there are mapping to the core @angular modules:

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中:

The first thing to understand here is that these are mappings, not dependencies. It means that if none of your files import @angular/core, it will not be loaded to a browser. However, you may see that this particular module is imported inside app/app.module.ts:

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

现在,为什么有映射.假设systemjsapp/app.module.js加载到浏览器中.它解析其内容并找到以下内容:

Now, why the mappings are there. Suppose systemjs loaded your app/app.module.js into the browser. It parses its content and finds the following:

var core_1 = require('@angular/core');

现在systemjs了解它需要解析和加载@angular/core.首先按照文档中指定的步骤检查mappings:

Now systemjs understands that it needs to resolve and load @angular/core. It first goes through the process of checking mappings, as specified in the docs:

map选项类似于路径,但在 规范化过程.它允许您将模块别名映射到 位置或包裹.

The map option is similar to paths, but acts very early in the normalization process. It allows you to map a module alias to a location or package.

我称其为命名模块的分辨率.因此,它找到映射并将@angular/core替换为node_modules/@angular/core,这是放置实际文件的位置.

I would call it a resolution by a named module. So, it finds the mapping and substitutes @angular/core with node_modules/@angular/core and this is where the real files are placed.

我认为systemjs试图模仿node.js中使用的方法,您可以在其中指定没有相对路径标识符['/', '../', or './']的模块,就像这样require('bar.js')node.js:

I think systemjs tries to imitate the approach used in node.js where you can specify a module without relative path identifiers ['/', '../', or './'], simply like this require('bar.js') and node.js:

然后,Node.js从当前模块的父目录开始,然后 添加/node_modules,并尝试从中加载模块 位置.

then Node.js starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location.

如果需要,可以避免使用命名映射,而可以通过使用相对路径进行导入,如下所示:

If you wanted, you could avoid using named mappings and import by using relative path like this:

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

但是,应该在项目和lib文件中的所有对@angular.core的引用中进行此操作,包括@angular,至少可以说这不是一个好的解决方案.

However, this should be done in all references to @angular.core in the project and lib files, including @angular, which is not a good solution to say the least.

这篇关于Angular2中对SystemJS的需求是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆