简体   繁体   English

package.json 中的根目录

[英]Root directory in package.json

My question concerns an existing library that I wish to publish as an NPM module.我的问题涉及我希望作为 NPM 模块发布的现有库。 The library is already in use, and currently require d via the local file system.该库已在使用中,当前require通过本地文件系统 d。

How can I specify the root directory of my module's files?如何指定模块文件的根目录?

If I have a structure like:如果我有这样的结构:

.
├── package.json
├── src
|   ├── js
|   └────── lib
|   └───────── my
|   └───────────── thing.js
|   └───────────── that.js

How do I specify that the root of my module, and accessible files is src/js/lib/my/ ?如何指定我的模块的根目录和可访问文件是src/js/lib/my/

I would like to use as follows from an outside project:我想从外部项目中使用以下内容:

var thing = require('my/thing'),
    that = require('my/that');

I saw the "files" property in package.json, is this the right way to go?我在 package.json 中看到了"files"属性,这是正确的方法吗?

UPDATE 2020 2020 年更新

The issue suggesting mainDir is now closed.提示 mainDir 的问题现已关闭。 Instead there is a new field called exports which can be used almost like es import maps to map a folder to an export alias:取而代之的是一个名为exports的新字段,它几乎可以像es import maps 一样用于将文件夹映射到导出别名:

// ./node_modules/es-module-package/package.json
{
  "exports": {
    "./my/": "./src/js/lib/my/"
  }
}
import thing from 'es-module-package/my/thing.js';
// Loads ./node_modules/es-module-package/src/js/lib/my/thing.js

As suggested in the issue linked in the original answer below it may be possible to map the root to a folder to access import thing from pkg/thing.js as so: 正如下面原始答案中链接的问题中所建议的,可以将根映射到文件夹以import thing from pkg/thing.js访问import thing from pkg/thing.js如下所示:

{
  "type": "module",
  "main": "./dist/index.js",
  "exports": {
    "./": "./src/js/lib/my/"
  }
}

Original Answer原答案

For a native solution, see this node issue https://github.com/nodejs/node/issues/14970对于本机解决方案,请参阅此节点问题https://github.com/nodejs/node/issues/14970

The feature request suggests a mainDir field in the package.json next to main.功能请求建议 package.json 中 main 旁边的mainDir字段。

The more people that vote, the faster/more likely it will be implemented投票的人越多,实施的速度就越快/更有可能

As the doc says:正如文档所说:

The main field is a module ID that is the primary entry point to your program. main 字段是一个模块 ID,它是程序的主要入口点。

So you'll have something like "main": "src/js/lib/my/app.js" in your package.json file.所以你的 package.json 文件中会有类似"main": "src/js/lib/my/app.js"

I would suggest you to create an app.js file and module.exports your different children.我建议你创建一个app.js文件和module.exports你不同的孩子。 For example:例如:

 module.exports.thing = require('./thing');
 module.exports.that = require('./that');

And use them like this:并像这样使用它们:

var mylib = require('mylib')
  , thing = mylib.thing
  , that = mylib.that;

package.json is mainly a file used by npm to install and manage dependencies. package.json主要是npm用来安装和管理依赖的文件。

the require construct does not care a lot about package.json so you will not be able to use it to subvert the way require works and make it believe that packages are not where the require loading scheme expects them. require构造并不关心package.json因此您将无法使用它来颠覆require工作方式,并使其相信包不在require加载方案所期望的位置。

See the documentation on https://nodejs.org/api/modules.html and the loading scheme here: https://nodejs.org/api/modules.html#modules_all_together请参阅https://nodejs.org/api/modules.html上的文档和此处的加载方案: https : //nodejs.org/api/modules.html#modules_all_together

you could maybe use the technique that the documentation calls 'Loading from the global folders' and define the NODE_PATH environment variable.您可以使用文档中称为“从全局文件夹加载”的技术并定义NODE_PATH环境变量。

but I advise you to stick to a more standard way : - put your modules in a node_modules directory - or start your module hierarchy in the same directory where your app.js or index.js is located但我建议您坚持使用更标准的方式: - 将模块放在 node_modules 目录中 - 或者在 app.js 或 index.js 所在的同一目录中启动模块层次结构

Now this is ugly workaround and it does pollute the root of your package.现在这是一个丑陋的解决方法,它确实污染了你的包的根。 But until Jordan's answer works, this feels like the way to achieve what you ask.但在乔丹的答案奏效之前,这感觉就像是实现你所要求的方式。

Just add a file in the root of your package for each of the modules you want to export using the require with slash notation.只需使用带斜杠符号的require 为要导出的每个模块在包的根目录中添加一个文件。 Such file will have the same name as the module being exported and it will simply reexport it.此类文件将与要导出的模块具有相同的名称,并且只会重新导出它。

.
├── package.json
├── thing.js       <--
├── that.js        <--
├── src
|   ├── js
|   └────── lib
|   └───────── my
|   └───────────── thing.js
|   └───────────── that.js

For example file ./thing.js will contain:例如文件./thing.js将包含:

module.exports = require('./src/js/lib/my/thing');

And so you could require it as:因此,您可以将其要求为:

const thing = require('mypackage/thing');

Also as stated in the bug about adding mainDir property into package.json you can just temporarily copy your sources and the package.json file into one directory and publish from there.同样如关于将mainDir属性添加到package.json错误所述,您可以将源和 package.json 文件临时复制到一个目录中并从那里发布。

Another possibility is to use ECMAScript modules (ES modules), particularly the package exports field in your package.json file.另一种可能性是使用 ECMAScript 模块(ES 模块),特别是package.json文件中的包导出字段。

Given a package.json file with this config:给定具有此配置的package.json文件:

{
  "name": "my",
  "exports": {
    "./": "./src/js/lib/my/"
  }
}

You should be able to import modules from the library like:您应该能够从库中导入模块,例如:

import thing from 'my/thing'
import that from 'my/that'

This is enabled by default since node 13.0.0 , but was behind the --experimental-exports flag from 12.13.0 .自节点13.0.0起默认启用此功能,但位于--experimental-exports标志12.13.0

Note, that the ES Module spec is in the Stability:1 - Experimental stage and subject to change.请注意,ES 模块规范处于稳定性:1 - 实验阶段,可能会发生变化。 I have no idea the extent to which this might be compatible with CommonJS modules.我不知道这在多大程度上与 CommonJS 模块兼容。

Simply publish /install /link the folder intended to be the root只需发布 /install /link 打算成为根的文件夹

The natural way to achieve that, according to the npm approach, is to publish the folder which is to be the root.根据 npm 方法,实现这一目标的自然方法是发布将成为根目录的文件夹。 There are several ways to do that, depends on the final environment you want to work with:有几种方法可以做到这一点,具体取决于您要使用的最终环境:

  1. npm publish <folder> from your package repo to an npm registry and then install your package in other project as you install other packages. npm 将 <folder>从包存储库发布到 npm 注册表,然后在安装其他包时将包安装到其他项目中。 In your case it would be npm publish src/js/lib/my .在您的情况下,它将是npm publish src/js/lib/my
  2. npm install <folder> in some other project if you want to use your package only locally.如果您只想在本地使用您的包,请在其他项目中使用npm install <folder> In your case you go to the other project and run npm install relative/path/to/src/js/lib/my在您的情况下,您转到另一个项目并运行npm install relative/path/to/src/js/lib/my
  3. npm link your folder locally to node_modules in other project in case you'd like to have the changes in your original package reflected instantly in other project. npm 将您的文件夹本地链接到其他项目中的node_modules ,以防您希望原始包中的更改立即反映在其他项目中。 In your case you first cd src/js/lib/my and run npm link and then go to the other project and run npm link my .在您的情况下,您首先cd src/js/lib/my并运行npm link然后转到另一个项目并运行npm link my

Prerequisite : in any case above, prior to the publish/install/link, you have to put in your my folder at least a proper package.json file.先决条件:在上述任何情况下,在发布/安装/链接之前,您必须在my文件夹中至少放置一个适当的package.json文件。 In your case, you have to have the package name defined in the package.json file as "name": "my" .在您的情况下,您必须将 package.json 文件中的包名称定义为"name": "my" Typically you'll want there also some other files like README.md or LICENSE.通常,您还需要其他一些文件,例如 README.md 或 LICENSE。

Remarks to methods 2 & 3对方法 2 和 3 的备注

Typically there are problems with package dependencies when you use the package installed this way.当您使用以这种方式安装的软件包时,通常会出现软件包依赖性问题。 To avoid it, first pack the package with npm pack dist and then install the package in the target project from the packed tarball, ie npm install path/to/package-tarball.tgz .为了避免它,首先使用npm pack dist包包,然后从打包的 tarball 中将包安装到目标项目中,即npm install path/to/package-tarball.tgz

Automation example自动化示例

You can automate the publishing process using the prepare script , combined with build script and "private": true field put in the package.json located in the root directory of your package repo.您可以使用prepare script自动化发布过程,结合build script 和"private": true字段放在位于包存储库根目录的 package.json 中。 Here is an example with the dist folder as a package root:下面是一个将dist文件夹作为包根目录的示例:

  "private": true,
  "scripts": {
    "build": "rm -rf dist && webpack --mode=production && cat ./package.json | grep -v '\"private\":' > dist/package.json",
    "prepare": "npm run build"
  },

This way you won't publish the root folder ( "private": true ).这样你就不会发布根文件夹( "private": true )。 And when you hit npm publish dist the automatically invoked prepare script will trigger dist folder cleanup ( rm -rf dist ), package build ( webpack --mode=production ) and copy of the package.jsonto the dist folder without the field "private": true ( cat ./package.json | grep -v private > dist/package.json ).当您点击npm publish dist ,自动调用的prepare脚本将触发 dist 文件夹清理( rm -rf dist )、包构建( webpack --mode=production )并将 package.json 复制到没有“private”字段的 dist 文件夹: true ( cat ./package.json | grep -v private > dist/package.json )。

In webpack, you can specify resolve.alias like this:在的WebPack,您可以指定resolve.alias是这样的:

{
  resolve: {
    alias: {
      'my': 'my/src'
    }
  }
}

or you can specify directions option in package.json或者您可以在 package.json 中指定directions选项

{
  directions: {
    'lib': 'src/lib'
  }
}

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

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