2016-04-27 213 views
1

我有一個大型的Typescript項目,它將連接到單個JS文件中進行部署。 確保以正確順序排列文件的正確方法是什麼?有太多的文件需要手動嘗試和維護。Typescript中的依賴關係解析

如果文件A中的類依賴於文件B中的類,那麼生成的連接文件中的類的排序很重要。如果文件B比文件A晚出現,則在運行時不能解析該類。

這肯定是一個普遍的問題,應該有一個簡單的解決它。 一個警告是我使用命名空間而不是模塊。我不確定整個項目中使用模塊是否可以解決此問題。

下面是一個簡單的例子 TestClassA.ts

namespace Test { 
    'use strict'; 

    import TestClassB = Test.TestClassB; 

    export class TestClassA { 
     private test: TestClassB; 
     constructor() { 
      this.test = new TestClassB(); 
     } 
    } 
} 

TestClassB.ts

namespace Test { 
    'use strict'; 

    export class TestClassB { 

     private value: string; 

     constructor() { 
      this.value = 'test'; 
     } 
    } 
} 

TestClass.spec.ts

'use strict'; 

describe('test',(): void => { 
    it ('should create an object',(): void => { 
     let a: Test.TestClassA = new Test.TestClassA(); 

     expect(a).toBeDefined(); 
    }); 
}); 

在Karma.config文件中指定的文件作爲

files: [ 
     'src/**/*.js', 
     'test/**/*.spec.js' 
    ], 

測試將失敗與例外TestClassB不是構造函數。

相反,如果我指定的Karma.config文件作爲 文件:[ 'SRC/TestClassB.ts', 'SRC/TestClassA.ts', '測試/ **/* spec.ts。']

然後測試會通過。

但隨着數百個文件,這樣做的一個項目變得難以維護。

+0

我現在已經發現,如果我在TestClassA使用時完全量化TestClassB作爲Test.TestClassB的名稱,然後一切都很好,它作品。我原以爲這就是進口聲明中的別名所做的。 –

回答

2

使用ES6導入/導出捆綁器,for example with webpack

代碼

// File TestClassA.ts 

import TestClassB from './TestClassB'; 

export default class TestClassA { 
    private test: TestClassB; 
    constructor() { 
    this.test = new TestClassB(); 
    } 
} 

// File TestClassB.ts 

export default class TestClassB { 
    private value: string; 
    constructor() { 
    this.value = 'test'; 
    } 
} 

配置

// File tsconfig.json 

{ 
    "compilerOptions": { 
    // ... 
    "module": "commonjs", 
    "noEmit": true 
    } 
    // ... 
} 

// File webpack.config.js 

var path = require("path"); 

module.exports = { 
    entry: path.join(__dirname, "TestClassA.ts"), 
    output: { 
    path: __dirname, 
    filename: "bundle.js" 
    }, 
    resolve: { 
    extensions: ["", ".webpack.js", ".web.js", ".ts", ".js"] 
    }, 
    module: { 
    loaders: [ 
     { 
     test: /\.ts$/, 
     loader: "ts", 
     query: { 
      "compilerOptions": { 
      "noEmit": false 
      } 
     } 
     } 
    ] 
    } 
}; 

提示:參見鏈接樓上了解此配置。

命令
# Install (to run once) 
npm install -g webpack typescript 
npm install ts-loader typescript 

# Make the bundle 
webpack 
+0

如果你看看這個問題的其他編輯,你的答案是否仍然適用?我不認爲它確實如此。 –

+0

@LIZARoberts我不使用Karma,我不能幫你配置它。但我添加了一個使用ES6導入/導出而不是'namespaces'的例子。 – Paleo

0

作爲古suggested,所述優選分離代碼分割成多個文件的方式是通過使用模塊代替命名空間。我一直在你的鞋,命名空間確實更適合於創建一個編譯串接輸出,但它只是由開發商和大部分社區的兩個忽略。

對於非平凡的項目你基本上被迫使用模塊,其中優選語法是ES6 syntax

import { ... } from "./path/to/module-file"; 

這將必須由任一種ES6瀏覽器,一個模塊加載處理系統爲< ES6瀏覽器(RequireJS)或NodeJS內置模塊加載系統。模塊肯定有它們的優點,但它們是而不是是命名空間的明顯替代。


然而,有一個理論解我知道:如果你有一個指定的根文件,並命名空間結構反映的目錄佈局(比如:命名空間Test.Helpers是文件夾test/helpers中,請參閱以下鏈接問題),編寫一個遞歸掃描文件以獲得import X = ...語句的工具很容易,然後創建一個_references.ts文件,該文件包含引用路徑的有序列表。類似應該由TypeScript編譯器完成,但它不是。

當在Visual Studio編譯時,此_references.ts文件被自動識別並傳遞到編譯器,但據我所知,您可以手動傳遞文件的編譯器爲好,簡單地通過:

tsc _references.ts --out test.js 

然後它將編譯引用的文件。

在使用ES6模塊導入語法之前,我自己使用了一種用C#編寫的定製的〜200行捆綁程序。還有你要注意一些注意事項:

  • import X = ...語句可以使用來自任何命名空間的相對路徑當多個命名空間嵌套。您需要強制自己只使用絕對名稱空間名稱,或者處理所有情況。
  • 必須檢查循環依賴關係。
  • 可能更多的是我沒有遇到...
+0

我已經建立了一個像這樣的工具來搜索代碼,並以一個可以消除問題的順序創建源文件的輸出文件。那些依賴性最小的文件首先列出等等。但是,這可以通過Grunt for Concatenation導入,但很難爲Wallaby或Karma工作。儘管如此,我發現了一個簡單的解決方案。不要使用導入語句進行別名。這是導致問題的重要聲明。這將創建一個本地類型,該類型設置爲被別名化的類型。如果順序錯誤,這是未定義的。 –

+0

@LIZARoberts但是你必須每次都輸入完全限定的名字,對吧?國際海事組織,提取'進口'別名可以提供一個體面的解決方案,只要其內容是標準化的方式。至少,它證明對我有用。 –