【问题标题】:Root directory in package.jsonpackage.json 中的根目录
【发布时间】:2015-07-29 22:20:18
【问题描述】:

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

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

如果我有这样的结构:

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

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

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

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

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

【问题讨论】:

    标签: javascript node.js npm package.json


    【解决方案1】:

    正如doc 所说:

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

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

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

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

    并像这样使用它们:

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

    【讨论】:

    • 我的包是一个已经存在的库,我不能改变结构。我只需要 NPMify 我的库。
    • 为什么向package.json 添加条目不会改变库,但添加 index.js 是?这应该是公认的答案。
    【解决方案2】:

    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 所在的同一目录中启动您的模块层次结构

    【讨论】:

    • 这是一个我想发布的模块
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 请在 Internet 上的文档中找到可用的位置。我从未见过方向或任何参考。
    • @mibbit 谷歌搜索有帮助。第一个结果是webpack docs: Resolve。绝对惊人的答案。在第三次尝试修复此问题后,终于遇到了这个问题! :)
    • package.json 文档中不存在方向
    • 我不知道directions 来自哪里,但现在我们有exportsnodejs.org/api/esm.html#esm_package_exports
    【解决方案4】:

    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
    

    As suggested 在下面原始答案中链接的问题中,可以将根映射到文件夹以访问import thing from pkg/thing.js,如下所示:

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

    原答案

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

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

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

    【讨论】:

    【解决方案5】:

    现在这是一个丑陋的解决方法,它确实污染了你的包的根。但在Jordan's answer 工作之前,这感觉就像实现您所要求的那样。

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

    .
    ├── 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');
    

    同样如bug about adding mainDir property into package.json 中所述,您可以暂时将您的源代码和 package.json 文件复制到一个目录并从那里发布。

    【讨论】:

      【解决方案6】:

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

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

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

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

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

      自节点 13.0.0 起默认启用此功能,但位于 12.13.0--experimental-exports 标志后面。

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

      【讨论】:

        【解决方案7】:

        只需发布 /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 link 您的文件夹本地到其他项目中的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 中。下面是一个将 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 &gt; dist/package.json)。

        【讨论】:

          猜你喜欢
          • 2017-08-18
          • 1970-01-01
          • 2015-04-29
          • 2014-06-02
          • 2018-06-06
          • 2019-04-21
          • 1970-01-01
          • 2018-10-28
          • 2016-11-07
          相关资源
          最近更新 更多