80

我的问题涉及我希望作为 NPM 模块发布的现有库。该库已在使用中,目前require通过本地文件系统进行。

如何指定模块文件的根目录?

如果我有这样的结构:

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

如何指定我的模块的根目录和可访问文件是src/js/lib/my/

我想从外部项目中使用如下:

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

"files"在 package.json 中看到了该属性,这是正确的方法吗?

4

7 回答 7

38

2020 年更新

建议 mainDir 的问题现已关闭。取而代之的是一个名为的新字段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

正如下面原始答案中链接的问题中所建议的那样,可以将根映射到要访问的文件夹,import thing from pkg/thing.js如下所示:

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

原始答案

对于本机解决方案,请参阅此节点问题https://github.com/nodejs/node/issues/14970

功能请求mainDir在 main 旁边的 package.json 中建议一个字段。

投票的人越多,实施的速度/可能性就越大

于 2018-01-29T10:01:30.053 回答
8

正如文档所说:

主要字段是模块 ID,它是程序的主要入口点。

所以你会"main": "src/js/lib/my/app.js"在你的 package.json 文件中有类似的东西。

我建议你创建一个app.js文件和module.exports你不同的孩子。例如:

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

并像这样使用它们:

var mylib = require('mylib')
  , thing = mylib.thing
  , that = mylib.that;
于 2015-05-18T12:14:13.583 回答
6

package.json主要是用来npm安装和管理依赖的文件。

require构造不太关心,package.json因此您将无法使用它来颠覆工作方式require并使其相信包不在require加载方案所期望的位置。

请参阅https://nodejs.org/api/modules.html上的文档和此处的加载方案:https ://nodejs.org/api/modules.html#modules_all_together

您也许可以使用文档称为“从全局文件夹加载”的技术并定义NODE_PATH环境变量。

但我建议您坚持使用更标准的方式: - 将模块放在 node_modules 目录中 - 或在 app.js 或 index.js 所在的同一目录中启动模块层次结构

于 2015-05-18T12:22:31.717 回答
4

现在这是一个丑陋的解决方法,它确实污染了你的包的根。但在乔丹的回答奏效之前,这感觉就像是实现你所要求的方式。

只需在包的根目录中为要导出的每个模块添加一个文件,使用带有斜杠表示法的 require。这样的文件将与正在导出的模块具有相同的名称,并且它将简单地重新导出它。

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

例如文件./thing.js将包含:

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

所以你可以要求它:

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

此外,正如关于向您添加mainDir属性package.json的错误中所述,您可以暂时将您的源代码和 package.json 文件复制到一个目录中并从那里发布。

于 2018-04-18T17:43:38.060 回答
2

另一种可能性是使用 ECMAScript 模块(ES 模块),尤其是package.json文件中的包导出字段。

给定一个带有此配置的package.json文件:

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

您应该能够从库中导入模块,例如:

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

自 node 以来默认启用此功能13.0.0,但位于--experimental-exportsfrom 的标志后面12.13.0

请注意,ES 模块规范处于Stability:1 - 实验阶段,可能会发生变化。我不知道这可能与 CommonJS 模块兼容的程度。

于 2019-08-29T14:11:12.983 回答
0

只需发布 /install /link 打算成为根目录的文件夹

根据 npm 方法,实现这一目标的自然方法是发布作为根的文件夹。有几种方法可以做到这一点,具体取决于您要使用的最终环境:

  1. npm publish <folder>从你的包 repo 到一个 npm 注册表,然后在你安装其他包时将你的包安装到其他项目中。在你的情况下,它会是npm publish src/js/lib/my.
  2. 如果您只想在本地使用您的包,请在其他项目中安装 npm install <folder> 。在您的情况下,您转到另一个项目并运行npm install relative/path/to/src/js/lib/my
  3. npm 将您的文件夹本地链接到node_modules其他项目中,以防您希望原始包中的更改立即反映在其他项目中。在您的情况下,您首先cd src/js/lib/my运行npm link,然后转到另一个项目并运行npm link my.

先决条件:在上述任何情况下,在发布/安装/链接之前,您必须在您的my文件夹中至少放入一个适当的package.json文件。在您的情况下,您必须将 package.json 文件中的包名称定义为"name": "my". 通常,您还需要一些其他文件,例如 README.md 或 LICENSE。

对方法 2 和 3 的备注

当您使用以这种方式安装的包时,通常会出现包依赖关系的问题。为避免这种情况,请先将包打包,npm pack dist然后将包从打包的 tarball 中安装到目标项目中,即npm install path/to/package-tarball.tgz.

自动化示例

prepare您可以使用script自动化发布过程,结合build脚本和"private": true放在 package.json 中的字段,该 package.json 位于包 repo 的根目录中。这是一个将dist文件夹作为包根目录的示例:

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

这样您就不会发布根文件夹 ( "private": true)。当您点击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)。

于 2020-10-05T17:21:08.350 回答
-1

在 webpack 中,你可以resolve.alias这样指定:

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

directions或者您可以在 package.json中指定选项

{
  directions: {
    'lib': 'src/lib'
  }
}
于 2017-12-09T04:18:31.523 回答