简体   繁体   English

Package.json 具有多个入口点

[英]Package.json with multiple entrypoints

I have a library which was used as follows我有一个使用如下的库

import { Foo } from '@me/core';
const foo = new Foo();

The package.json of that library looks like该库的package.json看起来像

"name": "@me/core",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"license": "MIT",
...

With dist/index.js its entrypoint.使用dist/index.js作为入口点。 Now, however, I would provide an import for NodeJs projects only and one for web projects.但是,现在我将只为 NodeJs 项目提供一个导入,为 web 项目提供一个导入。 Ideally I would have something like this for NodeJs理想情况下,我会为 NodeJs 准备这样的东西

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

and if you're working on a web-project you could do如果你正在做一个网络项目,你可以做

import { Foo } from '@me/core/web';

My understanding is that both @me/core/nodejs and @me/core/web will be different NPM packages this way, which is not what I want.我的理解是, @me/core/nodejs@me/core/web这样都会有不同的 NPM 包,这不是我想要的。 I want it to be in 1 npm package.我希望它在 1 npm package 中。

I tried to changed the library's index.ts file, from我试图改变图书馆的 index.ts 文件,从

export * from './foo';

into进入

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

export { web, nodejs };

This actually works, but I have to use it now (in a NODEJS project) as follows这确实有效,但我现在必须使用它(在 NODEJS 项目中),如下所示

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

const foo = new nodejs.Foo();

Is there maybe a way to import this such that I don't need the nodejs everytime?有没有办法导入这个,这样我就不需要每次都需要nodejs了?

As you can see I'm not so sure what I should do here so any help would be appreciated!如您所见,我不太确定我应该在这里做什么,所以我们将不胜感激!

UPDATE: Based on the suggestions by @Klaycon I see the following error:更新:根据@Klaycon 的建议,我看到以下错误:

在此处输入图像描述

As you're using ECMAScript modules, please refer to node.js docs on package entry points :当您使用 ECMAScript 模块时,请参阅package 入口点上的 node.js 文档:

In a package's package.json file, two fields can define entry points for a package: "main" and "exports".在包的 package.json 文件中,两个字段可以定义 package 的入口点:“main”和“exports”。 The "main" field is supported in all versions of Node.js, but its capabilities are limited: it only defines the main entry point of the package. Node.js 的所有版本都支持“main”字段,但它的功能是有限的:它只定义了 package 的主入口点。
The "exports" field provides an alternative to "main" where the package main entry point can be defined while also encapsulating the package, preventing any other entry points besides those defined in "exports". “exports”字段提供了“main”的替代方案,其中可以定义 package 主入口点,同时还封装 package,防止除“exports”中定义的入口点之外的任何其他入口点。 This encapsulation allows module authors to define a public interface for their package.这种封装允许模块作者为其 package 定义一个公共接口。

So, in your package.json, you could define exports like this:因此,在您的 package.json 中,您可以像这样定义exports

  "main": "dist/index.js",
  "exports": {
    ".": "dist/index.js",
    "./nodejs": "dist/nodejs",
    "./web": "dist/web",
  }

The accepted answer, using the exports field, is one way to do it, but not the only way -- and as you've found, isn't currently supported by Typescript.使用exports字段的公认答案是一种方法,但不是唯一方法 - 正如您所发现的,Typescript 目前不支持。

Look at the @angular/material package, which works similarly to what you have in mind.查看@angular/material package,它的工作原理与您的想法相似。 In @angular/material/package.json , you've got a module field that points to an empty JS file, and a typings field that points to an empty .d.ts file.@angular/material/package.json中,您有一个指向空 JS 文件的module字段和一个指向空typings文件的.d.ts字段。 But you've also got @angular/material/button/package.json which points (indirectly) to the implementation of MatButton (and a bunch of other stuff).但是你也有@angular/material/button/package.json它(间接地)指向MatButton的实现(以及一堆其他的东西)。 When you import {MatButton} from "@angular/material/button" , it resolves this package file, looks at its module and typings fields, and uses those to resolve the runtime code and exported types, respectively.当您import {MatButton} from "@angular/material/button" ,它会解析此typings文件,查看其module和类型字段,并使用它们分别解析运行时代码和导出类型。

You could do the same thing: @me/core/package.json would have module and typings fields that point to empty files;你可以做同样的事情: @me/core/package.json会有指向空文件的moduletypings字段; @me/core/node/package.json would point to code for your Node-specific Foo class, and @me/core/web/package.json would point to code for your browser version of Foo . @me/core/node/package.json将指向您的特定于节点的Foo Foo的代码, @me/core/web/package.json将指向您的浏览器版本的代码。

Try to add the following code to the tsconfig.json :尝试将以下代码添加到tsconfig.json

{
  "compilerOptions": {
    "moduleResolution": "NodeNext"
  }
}

And then you can import the module like this:然后你可以像这样导入模块:

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

If you Don't Want to Touch the tsconfig.json you can use the following for the import:如果您不想触摸tsconfig.json ,您可以使用以下内容进行导入:

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

References参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM