【问题标题】:How can I debug modular TypeScript with source maps?如何使用源映射调试模块化 TypeScript?
【发布时间】:2013-05-06 04:54:10
【问题描述】:

我很难在 Chrome 开发工具中进行 TypeScript 调试。我已经为我的所有 .ts 文件生成了源映射,并且 javascript 看起来是正确的,但是 Chrome 只加载 index.html 中引用的 js 文件并忽略所有模块。这有点道理,因为 Typescript 编译器似乎没有对我的模块做任何事情。如果有人可以在下面的示例中解释我做错了什么,那就太好了。

我的项目设置是这样的:

root/
  src/
    Company.ts
    User.ts
  app.ts
  index.html

Company.ts

module Company {

    export class Job {
        public title:string;
        public description:string;

        constructor(title:string, desc:string){
            this.title = title;
            this.description = desc;
        };
    }
}

User.ts

 ///<reference path="Company.ts"/>

module User {
    export class Person {
        public first:string;
        public last:string;
        private myJob:Company.Job;
        private myAccount:User.Account;

        constructor(firstName:string, lastName:string){
            this.first = firstName;
            this.last = lastName;
        }

        public getName():string{
            return this.first + ' ' + this.last;
        }

        public setJob(job:Company.Job){
            this.myJob = job;
        }

        public setAccount(acct:User.Account){
            this.myAccount = acct;
        }

        public toString():string{
            return "User: " + this.getName()
                    + "\nUsername: " + this.myAccount.userName
                    + "\nJob: " + this.myJob.title;
        }
    }

    export class Account {
        public userName:string;
        private _password:string;

        constructor(user:Person){
            this.userName = user.first[0] + user.last;
            this._password = '12345';
        }
    }
}

app.ts

///<reference path="src/User.ts"/>
///<reference path="src/Company.ts"/>

(function go(){
    var user1:User.Person = new User.Person('Bill','Braxton');
    var acct1:User.Account = new User.Account(user1);
    var job1:Company.Job = new Company.Job('Greeter','Greet');

    user1.setAccount(acct1);
    user1.setJob(job1);
    console.log(user1.toString());
}());

index.html

<!DOCTYPE html>
<html>
<head>
    <title>TypeScript Test</title>
    <script src="app.js"/>
    <script>
        go();
    </script>
</head>
<body>

</body>
</html>

编译器命令

tsc --sourcemap --target ES5 --module commonjs file.ts

当我在 Chrome 中打开 index.html 并打开 Sources 面板 Chrome Dev Tools 时,它会显示 app.js 和 app.ts,但不会显示其他 .ts 模块。所以 app.ts 的源映射是可以工作的,但是如何加载其他模块以便它们可以在 Chrome 中调试呢?

【问题讨论】:

    标签: typescript google-chrome-devtools source-maps


    【解决方案1】:

    当您使用参考 cmets 时,您必须自己加载所有模块(即添加多个脚本标签,或合并和缩小文件等)。

    如果你想使用模块加载器,你需要使用import 语句,这将被转换为你选择的模块加载器的 require 方法调用(可能是 Web 的 RequireJS)。

    示例 1 - DIY

    <script src="/src/Company.js"></script>
    <script src="/src/User.js"></script>
    <script src="app.js"></script>
    

    示例 2 - RequireJS

    src/Company.ts

    export class Job {
        public title: string;
        public description: string;
    
        constructor(title: string, desc: string) {
            this.title = title;
            this.description = desc;
        }
    }
    

    请注意,我已删除 module 声明。当您使用 RequireJS 导入模块时,文件名将成为模块名...

    src/User.ts

    import company = module('Company');
    
    export class Account {
        public userName: string;
        private _password: string;
    
        constructor(user: Person) {
            this.userName = user.first[0] + user.last;
            this._password = '12345';
        }
    }
    
    export class Person {
        public first: string;
        public last: string;
        private myJob: company.Job;
        private myAccount: Account;
    
        constructor(firstName: string, lastName: string) {
            this.first = firstName;
            this.last = lastName;
        }
    
        public getName(): string {
            return this.first + ' ' + this.last;
        }
    
        public setJob(job: company.Job) {
            this.myJob = job;
        }
    
        public setAccount(acct: Account) {
            this.myAccount = acct;
        }
    
        public toString(): string {
            return "User: " + this.getName()
                + "\nUsername: " //+ this.myAccount.userName
                + "\nJob: " + this.myJob.title;
        }
    }
    

    这里有一些变化——我们有import 语句而不是指向文件的注释。我们还在这里引用Account 而不是User.Account。同样,封闭模块消失了,因为文件就是模块。

    app.ts

    import Company = module('src/Company');
    import User = module('src/User');
    
    (function go() {
        var user1: User.Person = new User.Person('Bill', 'Braxton');
        var acct1: User.Account = new User.Account(user1);
        var job1: Company.Job = new Company.Job('Greeter', 'Greet');
    
        user1.setAccount(acct1);
        user1.setJob(job1);
        console.log(user1.toString());
    } ());
    

    在此处再次导入语句。附带说明一下,go 函数看起来会立即执行,因此您无需手动再次调用它 - 您可以删除函数名称以防止意外执行此操作。

    Index.html

    <script data-main="app.js" src="require.js"></script>
    

    你需要在你的项目中include the RequireJS script。您只需将其指向您的第一个文件,它将加载所有其余文件。您会注意到在您编译的 JavaScript 中,您的 import 语句被转换为对 RequireJS require 函数的调用:

    var Company = require("./src/Company");
    var User = require("./src/User");
    

    这会触发 RequireJS 为您加载脚本。

    您也可以use RequireJS manually if you want more control(即直接使用require 方法而不是使用import 语句。

    【讨论】:

    • 好的,我在想模块加载器可能必须手动实现。您是否打算在最后一句话中包含链接?看起来它以蓝色突出显示,但没有链接。
    • 我已经添加了 RequireJS 示例。
    • 好东西!我一直避免使用 RequireJS,因为我的印象是 TypeScript 更适合 CommonJS 规范(并且默认使用它)。不过,这很好,因为我更喜欢 AMD/RequireJS。感谢您非常详细的回答!
    猜你喜欢
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    • 2021-09-07
    • 2019-09-29
    • 1970-01-01
    • 2018-09-28
    • 2016-09-20
    • 2018-12-04
    相关资源
    最近更新 更多