V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
darklinden
V2EX  ›  Node.js

nodejs 新手,请问下 typescript 工程引入/导出 npm 包和 package.json 的问题

  •  
  •   darklinden · 2022-08-17 06:46:18 +08:00 · 4041 次点击
    这是一个创建于 610 天前的主题,其中的信息可能已经有所发展或是发生改变。

    简单来说,我这边前端和服务器都用到了一块逻辑代码,然后我图方便把它提出来作为 npm 包,一处更改前后都能使用。但是:

    • 前后端都是 typescript
    • 前端工程是 es module 发布类网页应用,后端工程是 node 的 commonjs
    • 前端不支持 bigint ,后端支持
    • 前端查了一下 JSBI 可以 babel 导出时选择替换为 bigint
    • 于是我查了一下找到个 hybrid npm 包的 package.json 写法,就是 esm -> import ,cjs -> require 分开填写
    • 问题又来了,babel 导出的 bigint 的 .d.ts 和 tsc 导出的 JSBI 的 .d.ts 并不一致,并且如果想两边使用方便,确实前端不能看到 bigint 后端不能看到 JSBI
    • 然后我又再起了个 npm 包,把 JSBI 套了一层,在工具类里面处理导出,自己 type 了个 BI 类型,不会暴露出 JSBI 或者 bigint
    • 当然逻辑模块引用工具类的 npm 包时又循环到上面的问题了,公共代码引用方式相同,同一个包,如何用的时候导入命令相同,比如都是 import { BIEx, BI } from 'jsbi-extension'; 但是在不同“语境”下代表的东西不同?

    我不知道我表述清楚没有,最后我的临时解决方案是自己造的这个 jsbi 的套壳起了俩分枝,在公共逻辑模块 build esm/cjs 时分别引用不同的分支,但...感觉各种别扭...请问这种情形的标准解决方案是什么?

    我造的 JSBI 坑在这 https://github.com/darklinden/jsbi-extension 后来想了下也只是因为我这是前后端 esm 和 cjs 的不同才只有两个分支...如果是做成通用的...岂不是要 4 个分支?

    12 条回复    2022-08-18 06:55:50 +08:00
    lyc575757
        1
    lyc575757  
       2022-08-17 07:39:51 +08:00 via Android
    可以看一下 unbuild 这个打包工具 支持同时打包出 esm 和 cjs2 种包。这篇文章有很详细的说明

    https://antfu.me/posts/publish-esm-and-cjs
    lyc575757
        2
    lyc575757  
       2022-08-17 07:47:22 +08:00 via Android
    另外 nodejs 也支持 esm 的 在 package.json 里设置 type 为 module 即可
    darklinden
        3
    darklinden  
    OP
       2022-08-17 07:59:19 +08:00
    @lyc575757 稍微看了下,好像不大对...
    * package.json 我设置了的啊,上面可能没有表述清楚,问题在于 .d.ts 文件声明
    * 分开编译我也做了的,分别使用了两个 tsconfig.json ,只是导出后我自己写脚本处理的 .cjs 和 .mjs
    * 目前是 4 个包不是两个,(cjs + esm) x (JSBI + bigint), 其中 bigint 的导出是使用 JSBI 提供的 babel 插件
    * 上面的问题就导致会生成至少两套 .d.ts ,而且并不相通
    * ··· "exports": {
    ".": {
    "import": "./dist/index.mjs",
    "require": "./dist/index.cjs",
    "types": "./dist/index.d.ts",
    }
    },
    "types": "./dist/index.d.ts",
    ···
    darklinden
        4
    darklinden  
    OP
       2022-08-17 08:01:18 +08:00
    @darklinden emm,刚刚手抖就发出去了...
    无论 types 在 exports 内 还是 外, 目前我都没法指定多个 types 指向同一路径并且区别“语境”
    zhyl
        5
    zhyl  
       2022-08-17 09:34:03 +08:00
    一个想法,前端直接在 html 中引入 bigint 的 polyfill
    RomeoHong
        6
    RomeoHong  
       2022-08-17 09:44:35 +08:00
    生成至少两套 .d.ts ?可以在输出 cjs/esm 时不输入类型文件 ( tsc -m commonjs/esNext --declaration false ),然后单独输出类型文件( tsc --declaration --emitDeclarationOnly )
    zhuisui
        7
    zhuisui  
       2022-08-17 10:09:50 +08:00
    要么把关于 bigint 的实现隐藏起来,这样就可以不被外面看到;
    如果不能隐藏,必须被外面使用,那么要么给外面封装成一套接口,就如你试图做的 BI ,要么就分别单独生成不同的类型文件,就像 @RomeoHong 说的
    darklinden
        8
    darklinden  
    OP
       2022-08-17 14:04:30 +08:00 via iPhone
    @RomeoHong 现在是生成了两套,cjs 和 mjs 各一套 js 和 d.ts…而且问题在于.d.ts 也并不相同
    如何配置 package.json 以达到外部使用库的 typescript 可以正常使用?
    类似宏定义 BI 为如果 bigint 有实现则使用,否则使用 js
    @zhuisui
    duan602728596
        9
    duan602728596  
       2022-08-17 16:41:20 +08:00
    由于有 https://www.npmjs.com/package/babel-plugin-transform-bigint ,可以将 bigint 转换成 JSBI 。所以现在我觉得你可以移除你代码中的 bigint 了,而是将 JSBI 作为类似于 corejs 的 polyfill ,由 babel 来处理。

    还有就是不太推荐用模块类型来判断环境,因为现在 node 也支持 ESM 了,有些会直接将 node 全部切换到 ESM 。别的模块一般是'moduleName'作为 node 环境导入的模块,'moduleName/browser'作为浏览器环境导入的模块。
    darklinden
        10
    darklinden  
    OP
       2022-08-17 22:23:19 +08:00
    @duan602728596 我语文就这么差么...
    * 我在逻辑模块中使用了 jsbi ,因为前端有些场景无法使用 bigint
    * 后端因为是老项目而且很多 commonjs 的写法无法切换到 module ,前端因为使用的游戏引擎的原因无法切换到 commonjs
    * 为了后端“懒”,可以使用 bigint 的 node 特性加减乘除,所以在后端导入逻辑模块的时候需要 babel 转化为 bigint ,并且我引入的 BI 类型也是希望中间模块不显示使用 JSBI 和 bigint 中的任意一个,以保证通用性
    * 现在能做到的就是把需要 babel 转换的从整个中间模块变为了只有一个 JBSI 的引用块,但是这个引用块在中间块和前端分别引用的时候需要编译替换为不同的版本,并且声明文件也需要替换,我觉得这不是一个正常的引用工作流
    duan602728596
        11
    duan602728596  
       2022-08-18 01:19:55 +08:00
    @darklinden
    1. 我的意思是保留 bigint 的写法,JSBI 使用 babel 插件作为 polyfill 处理,这样就不需要导出 JSBI 的类型了。类似于 corejs 的处理。
    2. 开心就好,反正觉得没问题就没问题。
    3. 同 1
    4. 没有 bigint 的环境用 polyfill 处理,可以保证类型的一致性
    darklinden
        12
    darklinden  
    OP
       2022-08-18 06:55:50 +08:00
    @duan602728596
    感谢回复
    * https://github.com/Yaffle/babel-plugin-transform-bigint ``` It will try to detect when an operator is used for bigints, not numbers. This will not work in many cases, so please use JSBI directly only if you know, that the code works only with bigints. ``` 这个 babel 插件的问题和 JSBI to bigint 一样,很多情况下无法有效判别语义...
    * 目前看还真是只能套了一层又一层...反正可以跑...
    * 现在就像是为了把发动机装拖拉机上,传动拉了根橡皮筋,进油口插了根吸管,拿塑料纸裹了裹,外面贴了个 Hello Kitty ...
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4412 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 01:02 · PVG 09:02 · LAX 18:02 · JFK 21:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.