为浏览器和nodejs构build

我正在试图build立一个在浏览器和节点都可以工作的库。

我有三个jsonconfiguration文件,后两个扩展tsconfig.json

  • tsconfig.json(只包含构build文件)
  • tsconfig.browser.json
  • tsconfig.node.json

tsconfig.browser.json

 { "extends": "./tsconfig.json", "compilerOptions": { "target": "es6", "module": "system", "outFile": "../dist/browser/libjs.js", "removeComments": true, "declaration": true } } 

tsconfig.node.json

 { "extends": "./tsconfig.json", "compilerOptions": { "module": "commonjs", "moduleResolution": "node", "outDir": "../dist/node", "removeComments": true, "declaration": true, "declarationDir": "../dist/node/typings" }, "files": [ "./index" ] } 

我有这个index.ts文件(只包括在节点构build):

 export { collect } from './components/collections' export { query } from './components/query' 

然后我在collections.ts文件中有这个:

 export namespace libjs { export function collect<T>(data: T[]) { // Do some stuff } export class collection(){} } 

和这个query.ts文件:

 export namespace libjs { export class query<T> { private _results: collection<T> } } 

我遇到的问题是,当我尝试构build到节点时,索引文件找不到collectfunction,并且当我build立到浏览器query类找不到collection类。 什么是最好的方式来编码,所以我可以构build到节点和浏览器? 如果我删除namespace上的export ,我可以build立到浏览器罚款,但我不能build立到节点。

我想用这些方法如下:

的NodeJS

 const libjs = require('libjs') let c = libjs.collect([1, 123, 123, 1231, 32, 4]) 

浏览器

 <script src="/js/libjs.js"></script> <script> let c = libjs.collect([1, 123, 123, 1231, 32, 4]) </script> 

当您编译具有export ...的文件时,每个文件都被视为一个具有自己范围的模块,并且每个文件中的namespace libjs与每个其他文件中的libjs不同且独立。

如果你想生成一个可以在没有模块加载器的情况下在浏览器中使用的脚本(将libjs定义为全局的),你必须删除所有的顶层导出,并且不要在tsconfig设置module

组件/ collections.ts

 namespace libjs { export function collect<T>(data: T[]) { // Do some stuff } export class collection<T>{} } 

组件/ query.ts

 namespace libjs { export class query<T> { private _results: collection<T> } } 

现在,如果添加在运行时检测节点环境的代码并将libjs分配给libjs ,则可以在节点中使用同样生成的脚本:

index.ts

 namespace libjs { declare var module: any; if (typeof module !== "undefined" && module.exports) { module.exports = libjs; } } 

单一的tsconfig.json浏览器和节点(请注意,我改变了从../dist dist输出)

 { "compilerOptions": { "outFile": "./dist/libjs.js", "removeComments": true, "declaration": true }, "files": [ "components/collections.ts", "components/query.ts", "index.ts" ] } 

您可以在javascript中的node中立即使用生成的脚本:

testingjs.js

 const lib = require('./dist/libjs') console.log(typeof lib.collect); let c = lib.collect([1, 123, 123, 1231, 32, 4]) 

不幸的是,你不能在生成libjs.d.ts打字机节点中使用它,因为它将libjs声明为全局的。 对于节点,您需要单独的libjs.d.ts ,其中包含一个额外的export = libjs语句,您必须手动添加或作为构build过程的一部分:

完成节点的dist / libjs.d.ts

 declare namespace libjs { function collect<T>(data: T[]): void; class collection<T> { } } declare namespace libjs { class query<T> { private _results; } } declare namespace libjs { } // this line needs to be added manually after compilation export = libjs; 

testingts.ts

 import libjs = require('./dist/libjs'); console.log(typeof libjs.collect); let c = libjs.collect([1, 123, 123, 1231, 32, 4]) 

tsconfig.test.json

 { "compilerOptions": { "module": "commonjs", "moduleResolution": "node", "removeComments": true }, "files": [ "./test-ts.ts", "./dist/libjs.d.ts" ] } 

你可以select走完全不同的路线,并build立一个由模块组成的库,但为此,你必须在浏览器中使用模块加载器(或使用webpack构build),而且你可能需要阅读这个答案,解释为什么namespace libjs是完全的不必要的模块。