具有多个入口点的 Package.json

Jea*_*eri 11 node.js npm

我有一个使用如下的库

import { Foo } from '@me/core';
const foo = new Foo();
Run Code Online (Sandbox Code Playgroud)

package.json该库的样子的

"name": "@me/core",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",
...
Run Code Online (Sandbox Code Playgroud)

dist/index.js它的入口点。但是,现在,我将仅为 NodeJs 项目提供一个导入,为 Web 项目提供一个导入。理想情况下,我会为 NodeJs 准备这样的东西

import { Foo } from '@me/core/nodejs';
Run Code Online (Sandbox Code Playgroud)

如果你正在做一个网络项目,你可以做

import { Foo } from '@me/core/web';
Run Code Online (Sandbox Code Playgroud)

我的理解是,无论@me/core/nodejs@me/core/web会有所不同NPM包这种方式,这不是我想要的。我希望它在 1 个 npm 包中。

我试图改变图书馆的 index.ts 文件,从

export * from './foo';
Run Code Online (Sandbox Code Playgroud)

进入

import * as nodejs from './nodejs';
import * as web from './web';

export { web, nodejs };
Run Code Online (Sandbox Code Playgroud)

这实际上有效,但我现在必须使用它(在 NODEJS 项目中)如下

import { nodejs } from '@me/core';

const foo = new nodejs.Foo();
Run Code Online (Sandbox Code Playgroud)

有没有办法导入这个,这样我就不需要nodejs每次?

正如你所看到的,我不太确定我应该在这里做什么,所以任何帮助将不胜感激!

更新:根据@Klaycon 的建议,我看到以下错误:

在此处输入图片说明

Kla*_*con 8

当您使用 ECMAScript 模块时,请参阅有关包入口点的node.js 文档:

在包的 package.json 文件中,两个字段可以定义包的入口点:“main”和“exports”。所有版本的 Node.js 都支持“main”字段,但它的功能是有限的:它只定义包的主入口点。
“exports”字段提供了“main”的替代方案,其中可以定义包主入口点,同时封装包,防止除“exports”中定义的入口点之外的任何其他入口点。这种封装允许模块作者为他们的包定义一个公共接口。

所以,在你的 package.json 中,你可以这样定义exports

  "main": "dist/index.js",
  "exports": {
    ".": "dist/index.js",
    "./nodejs": "dist/nodejs",
    "./web": "dist/web",
  }
Run Code Online (Sandbox Code Playgroud)

  • 这看起来像是解决方案,但我无法让它工作:(如果包的名称是 **@me/core** 应该 **core** 那么是 `exports` 键的一部分?如果你有是正确的,那么我应该如何导入它?就像这样 **import { Foo } from '@me/core/nodejs';**?现在它给了我以下错误: **Cannot find module '@me/core /nodejs' 或其相应的类型声明**。我是否也应该在某个地方定义类型文件?不知怎的,似乎 **exports** 被完全忽略了 (2认同)

Cod*_*rer 5

使用该exports字段的公认答案是一种方法,但不是唯一方法——正如您所发现的,Typescript 目前不支持。

查看@angular/material包,它的工作原理与您的想法类似。在 中@angular/material/package.json,您有一个module指向空 JS 文件的typings字段和一个指向空.d.ts文件的字段。但是你也有@angular/material/button/package.json哪些(间接)指向MatButton(以及一堆其他东西)的实现。当你import {MatButton} from "@angular/material/button",它解析这个包文件,查看它的moduletypings字段,并使用它们分别解析运行时代码和导出的类型。

你可以做同样的事情:@me/core/package.json有指向空文件的moduletypings字段;@me/core/node/package.json将指向特定于 Node 的Foo类的@me/core/web/package.json代码,并指向浏览器版本的Foo.