最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • package.json 之 Node.js 相关字段

    正文概述 掘金(B2D1)   2021-01-03   348

    前言

    这阵子在工作中参与了业务的抽象,计划打造通用组件并发布成 npm 包便于后续项目的共建,自热而然,学习到了一些关于 package.json 之前没有接触到的知识点。

    在此,介绍一些在 package.json 中被 Node.js 所使用的字段,以下所使用的 Nodejs 版本均为 v14.14.0.

    • name - 定义了以 package 形式导入时的名称,同时它决定了它在 npm 源上的唯一名称。
    • type - 规定 package 下的 .js 文件被 Node.js 以 CommonJS Modules 或 ECMAScript Modules 加载。
    • exports - 设置 package 的导出。
    • main - 规定加载 package 时的默认入口文件。

    name

    {
      "name": "package-name"
    }
    

    "name" 字段定义你的 package 名称,当你将 package 发布到 npm 源上,牢记 name 需要满足 规范 。

    当你下载的 package 位于 node_modules 时,你就可以使用以下方式导入:

    const pkg = require("package-name");
    // import pkg from 'package-name';
    

    type

    在 js 的世界中,存在着两种影响力最大的模块规范,它们是 CommonJS Modules 以及 ECMAScript Modules,好在 Nodejs 自从 v12 起就全部支持了,.js .cjs 文件默认以 CommonJS Modules 执行,.mjs 则默认以 ECMAScript Modules 执行。

    "type" 字段的出现让我们更好得决定 .js 文件被哪种模块规范执行,它的值有两个,分别是 "module""commonjs"

    {
      "type": "commonjs"
    }
    

    当你设置为 "commonjs" 时,那些以该 package.json 作为最近的父级配置文件的 .js .cjs 文件默认以 CommonJS Modules 执行,如果你想执行 ECMAScript Modules,就必须将后缀名改为 .mjs

    {
      "type": "module"
    }
    

    同理,当你设置为 "module" 时,那些以该 package.json 作为最近的父级配置文件的 .js .mjs 文件默认以 ECMAScript Modules 执行,如果你想执行 CommonJS Modules,就必须将后缀名改为 .cjs

    exports

    "exports" 字段允许你通过引用自己的 package name(Self-referencing a package using its name)来定义 package 的入口文件,举个例子:

    // package.json
    {
      "name": "pkg",
      "exports": {
        ".": "./main.mjs",
        "./foo": "./foo.js"
      }
    }
    

    以上可以被解读为:

      "exports": {
        "pkg": "pkg/main.mjs",
        "pkg/foo": "pkg/foo.js"
      }
    
    import { something } from "pkg"; // from "pkg/main.mjs"
    
    const { something } = require("pkg/foo"); // require("pkg/foo.js")
    

    它从 Node.js v12 开始被支持,并作为 "main"(具体介绍请看下一节) 字段的替代方案。

    他最大的一个特性就是 条件导出(Conditional Exports),当该 package 被导入时,能够判断被导入时的模块环境,从而执行不同的文件,简而言之就是,我们如果使用 import 命令,入口会加载 ECMAScript Modules 文件,如果使用 require 命令,入口则加载 CommonJS Modules 文件。

    我们来一探究竟,具体目录结构如下:

    ├── mod
    │   ├── mod.js
    │   ├── mod.cjs
    │   ├── package.json
    │── app.js
    └── app.mjs
    

    mod 作为一个本地的 package,它的 package.json 定义如下:

    {
      "name": "mod",
      "main": "index.js",
      "type": "module",
      "exports": {
        "require": "./mod.cjs",
        "import": "./mod.js"
      }
    }
    

    并且他提供了实现相同功能的两个脚本文件,以应对不同的模块环境:

    // mod.cjs
    exports.name = "cjs";
    
    // mod.js
    export const name = "mjs";
    

    调用该模块的文件如下:

    // app.js
    const { name } = require("mod");
    
    console.log(name);
    
    // app.mjs
    import { name } from "mod";
    
    console.log(name);
    

    这一切还不够,因为 mod 现在作为一个本地 package,它既不是从 npm 上 download 下来,也不处于 node_modules 目录中,无法通过 package name 的形式导入。

    办法总是有的,借助于 package link,我们可以实现本地 package 的关联,而不用正式发布到 npm 源上。

    先在 ./mod 目录下执行 yarn link

    success Registered "mod".
    info You can now run `yarn link "mod"` in the projects where you want to use this package and it will be used instead.
    

    然后在项目根目录下,执行 yarn link "mod"

    success Using linked package for "mod".
    

    最后,验证我们的 "exports" 字段是否起作用了:

    $ node app.js
    $ cjs
    $ node app.mjs
    $ mjs
    

    结果证实,在不同的模块环境中,执行了不同的脚本文件。

    注意,对于所有在 "exports" 中定义的路径都必须是绝对路径。即 ./ 的形式。

    main

    {
      "main": "./main.js"
    }
    

    "main" 字段定义了导入 package 目录时使用的入口文件,举个例子:

    const pkg = require("package-name");
    

    由于 node_modules 的查找机制,会被解析成以下路径:

    const pkg = require("./node_modules/package-name");
    

    这里只导入了一个目录,他不是一个具体模块,但是借助 main 即入口文件,文件路径最终被解析为:

    const pkg = require("./node_modules/package-name/main.js");
    

    注意,当一个 package 同时拥有 "exports""main" 字段时,在被以 package name 方式导入时,exports 的优先级较高。

    本文参考资料:
    Modules: Packages


    起源地下载网 » package.json 之 Node.js 相关字段

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元