【问题标题】:how to use SystemJS to bundle angular TypeScript with internal modules如何使用 SystemJS 将 Angular TypeScript 与内部模块捆绑在一起
【发布时间】:2015-09-13 21:17:18
【问题描述】:

我们正在考虑将我们的一些 Angular 项目转移到 typescript 并在内部模块/命名空间方面遇到一些问题。

我们在 github 上发布了这个工作示例:https://github.com/hikirsch/TypeScriptSystemJSAngularSampleApp

步骤:

npm install jspm -g
npm install
cd src/
jspm install
jspm install --dev
cd ..
gulp bundle
cd src/
python -m SimpleHTTPServer

这是应用程序的要点: index.ts

/// <reference path="../typings/tsd.d.ts" />
/// <reference path="../typings/typescriptApp.d.ts" />

import * as angular from 'angular';

import {ExampleCtrl} from './controllers/ExampleCtrl';
import {ExampleTwoCtrl} from './controllers/ExampleTwoCtrl';

export var app = angular.module("myApp", []);

app.controller("ExampleCtrl", ExampleCtrl);
app.controller("ExampleTwoCtrl", ExampleTwoCtrl);

ExampleCtrl.ts

/// <reference path="../../typings/tsd.d.ts" />
/// <reference path="../../typings/typescriptApp.d.ts" />


export class ExampleCtrl {
    public static $inject:Array<string> = [];

    constructor() {

    }

    public name:string;
    public hello_world:string;

    public say_hello() {
        console.log('greeting');

        this.hello_world = "Hello, " + this.name + "!";
    }
}

ExampleTwoCtrl.ts

/// <reference path="../../typings/tsd.d.ts" />
/// <reference path="../../typings/typescriptApp.d.ts" />

export class ExampleTwoCtrl {
    public static $inject:Array<string> = [];

    constructor() {

    }

    public name:string;
    public text:string;

    public second() {
        this.text = "ExampleTwoCtrl: " +  this.name;
    }
}

如上所述,这一切都很好。但我们宁愿将所有东西都放在这样的命名空间下:

module myApp.controllers {
    export class ExampleController {
        ...
    }
}
//do we need to export something here?

然后像这样使用它:

这将在运行 gulp bundle 任务时正确编译,但在浏览器中出现错误 /// ///

import * as angular from 'angular';

import ExampleCtrl = myApp.controllers.ExampleCtrl;
import ExampleTwoCtrl = myApp.controllers.ExampleTwoCtrl;

export var app = angular.module("myApp", []);

app.controller("ExampleCtrl", ExampleCtrl);
app.controller("ExampleTwoCtrl", ExampleTwoCtrl);

浏览器错误:

Uncaught ReferenceError: myApp is not defined(anonymous function) @ build.js:5u @ build.js:1i @ build.js:1c @ build.js:1(anonymous function) @ build.js:1(anonymous function) @ build.js:1
build.js:1 Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to:
Error: [$injector:nomod] Module 'myApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.3.15/$injector/nomod?p0=myApp
    at http://localhost:8000/build/build.js:1:4007
    at http://localhost:8000/build/build.js:1:12353
    at e (http://localhost:8000/build/build.js:1:11925)
    at t.register.e (http://localhost:8000/build/build.js:1:12237)
    at http://localhost:8000/build/build.js:1:20741
    at o (http://localhost:8000/build/build.js:1:4392)
    at p (http://localhost:8000/build/build.js:1:20519)
    at Bt (http://localhost:8000/build/build.js:1:22209)
    at t.register.s (http://localhost:8000/build/build.js:1:10038)
    at Q (http://localhost:8000/build/build.js:1:10348)
http://errors.angularjs.org/1.3.15/$injector/modulerr?p0=myApp&p1=Error%3A%…0%20at%20Q%20(http%3A%2F%2Flocalhost%3A8000%2Fbuild%2Fbuild.js%3A1%3A10348)

【问题讨论】:

    标签: angularjs typescript ecmascript-6 systemjs es6-module-loader


    【解决方案1】:

    根据typescript documentation,编译到commonjs时不需要使用内部模块。如前所述:

    TypeScript 中外部模块的一个关键特性是两个不同的 外部模块永远不会为同一范围贡献名称。 因为外部模块的使用者决定分配什么名称 它,无需主动将导出的符号包装在 命名空间。

    我发现将 typescript 与 commonjs 加载器(我正在使用 browserify)一起使用的最佳方法是执行以下操作:

    class ExampleTwoCtrl {
        public static $inject:Array<string> = [];
    
        constructor() {
    
        }
    
        public name:string;
        public text:string;
    
        public second() {
            this.text = "ExampleTwoCtrl: " +  this.name;
        }
    }
    
    export = ExampleTwoCtrl
    

    并像这样使用它:

    import MyController = require('./ExampleTwoCtrl');
    var a = new MyController();
    

    话虽如此,我从John Papa's talk at AngularU 观看了录音,他们演示了一些使用 typescript 编写的 systemjs 捆绑的代码,没有任何导入,只是内部 ts 模块。我在推特上询问了哪里可以找到示例代码,但还没有得到回复。

    【讨论】:

    • 使用的示例代码链接到幻灯片 18 上的此处docs.google.com/presentation/d/…
    • 他们使用的方法本质上只是将项目中每个 JS 的脚本标签转储到 html 页面上,不管它是否被使用。我们一直在寻找一种方法,我们可以告诉它哪个文件启动应用程序并让它适当地构建文件。我们在不使用模块的情况下所拥有的似乎可以完成它。只是想弄清楚我们如何使用模块来实现它(本质上只是希望所有东西都被命名)
    • 我也这么认为,但事实并非如此。如果您检查 index.html (github.com/johnpapa/hottowel-angular-typescript/blob/master/src/…),它根本不使用 systemjs。他们显示的代码不同,因为有一个 systemjs 和一些其他文件以及一个加载 main.js 的脚本(如果我没记错的话,至少 50 个视频)
    • 还有@1:05 在index.html 中有一个System.import('app/app') 的示例,然后app.ts 包含所有其他内容的配置、导入和引导。
    • 我实际上就此事与 John papa 进行了交谈,我认为他不会选择 SystemJS。我认为他更喜欢一次捆绑所有内容并加载它。我认为他相信在一般情况下,您的 javascript 文件不包括供应商文件不应该那么大。
    猜你喜欢
    • 2015-12-27
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    • 2015-01-07
    相关资源
    最近更新 更多