我正在尝试创建一个既可以在浏览器中也可以在节点中工作的库。
我有三个json配置文件,后两个扩展tsconfig.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 文件(仅包含在节点版本中):
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>
}
}
我遇到的问题是,当我尝试构建到节点时,索引文件找不到collect
函数,当我构建到浏览器时,query
类找不到{{ 1}}类。编写代码的最佳方法是什么,以便我可以构建节点和浏览器?如果我删除了collection
上的export
,我可以很好地构建浏览器,但我无法构建到节点。
我想使用它们的方式如下:
的NodeJS
namespace
浏览器
const libjs = require('libjs')
let c = libjs.collect([1, 123, 123, 1231, 32, 4])
答案 0 :(得分:1)
当您编译顶级export ...
的文件时,每个文件都被视为具有自己范围的模块,每个文件中的namespace libjs
是不同的,并且与libjs
分开在每个其他文件中。
如果要生成可在没有模块加载器的浏览器中使用的单个脚本(将libjs
定义为全局),则必须删除所有顶级导出,并且不要设置module
完全在tsconfig
:
<强>组件/ 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
分配给module.exports
,您也可以在节点中使用相同的生成脚本:
<强> 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中的节点中立即使用生成的脚本:
<强>测试js.js 强>
const lib = require('./dist/libjs')
console.log(typeof lib.collect);
let c = lib.collect([1, 123, 123, 1231, 32, 4])
不幸的是,你不能在带有生成libjs.d.ts
的typescript中的节点中使用它,因为它将libjs
声明为全局。对于节点,您需要单独的libjs.d.ts
,其中包含一个您必须手动添加或作为构建过程的一部分添加的export = libjs
语句:
为节点
完成 dist / libjs.d.tsdeclare 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;
<强>测试ts.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"
]
}
您可以选择使用完全不同的路径并构建由模块组成的库,但为此您必须在浏览器中使用模块加载器(或使用webpack构建),您可能需要阅读this answer解释为什么namespace libjs
完全不需要模块。