javascript - 为浏览器和 nodejs 构建

标签 javascript node.js typescript browser

我正在尝试制作一个既可以在浏览器中又可以在 Node 中运行的库。

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

  • tsconfig.json(仅包含构建文件)
  • 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 文件(仅包含在 Node 构建中):

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>
  }
}

我遇到的问题是,当我尝试构建到 Node 时,索引文件找不到 collect 函数,而当我构建到浏览器时,query类找不到 collection 类。最好的编码方式是什么,以便我可以构建到 Node 和浏览器?如果我删除 namespace 上的 export,我可以很好地构建到浏览器,但我无法构建到 Node 。

我想使用它们的方式如下:

Node

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 定义为全局),你必须删除所有顶层导出,并且不要设置 moduletsconfig 中:

components/collections.ts

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

components/query.ts

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

现在,您也可以在 Node 中使用相同的生成脚本,如果您添加在运行时检测 Node 环境的代码并将 libjs 分配给 module.exports:

index.ts

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

用于浏览器和 Node 的单个 tsconfig.json(请注意,我将输出从 ../dist 更改为 dist)

{
  "compilerOptions": {
    "outFile": "./dist/libjs.js",
    "removeComments": true,
    "declaration": true
  },
  "files": [

    "components/collections.ts",
    "components/query.ts",
    "index.ts"

  ]
}

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

test-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 Node 中使用它,因为它将 libjs 声明为全局的。对于 Node ,您需要单独的 libjs.d.ts,其中包含一个您必须手动添加或作为构建过程的一部分添加的附加 export = libjs 语句:

完成 Node 的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;

test-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 对于模块来说是完全不必要的。

关于javascript - 为浏览器和 nodejs 构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44709031/

相关文章:

javascript - Vercel 上的 Next.js 部署失败

javascript - 为什么 $(this) 在 javascript 函数中不起作用?

node.js - 适用于 NodeJS 的 Firebase 动态链接构建器 API

typescript - 如何使用父静态方法在 TypeScript 中创建子类?

javascript - 平滑滚动效果在 iOS 上的 iframe 中不起作用

javascript - 在 Laravel 中使用 Dropzone 上传后的成功消息

typescript - 在 TypeScript 中获取递归属性的联合类型

javascript - 捕获产品印象而不会使网站变慢

node.js - NodeJS : TypeError: Converting circular structure to JSON

node.js - Cloudinary API - resources_by_tag