前端
PythonJava运维数据库
npm
npm
  • npm version
  • JS模块化
  • package.json
  • npm 缓存
由 GitBook 提供支持
在本页
  • files
  • main、module、browser
  • dependencies
  • engines
  • os
  • cpu
  • private
  • publishConfig
  • exports 字段
  • 设置子目录别名
  • main 的别名
  • 条件导出
  • CommonJS 模块加载 ES6 模块
  • ES6 模块加载 CommonJS 模块
  • 同时支持两种格式的模块

这有帮助吗?

package.json

files

可选的 files 字段,用来指定哪些文件是发布版本的一部分。文件模式遵循与 .gitignore 类似的语法,但相反:包含文件、目录或 glob 模式(*、**/* 等)将使文件在打包时包含在 tarball 中。省略该字段将使其默认为 ["*"],这意味着它将包括所有文件。

{
    "files": [
        "dist",
    ]
}

一些特殊的文件和目录也被包含或排除,无论他们是否存在于 files 字段中。

你还可以在包的根目录或者子目录中提供一个 .npmignore 文件,来排除那些你不想发布的文件。如果有 .gitignore 文件,而 .npmignore 文件不存在,则使用 .gitignore 文件。

"package.json#files" 字段包含的文件不能通过 .npmignore 或 .gitignore 文件排除。

始终包含的文件:

  • package.json

  • README

  • LICENSE/LICENCE

  • main 字段对应的文件

总是被忽略的文件:

  • .git

  • CVS

  • .svn

  • .hg

  • .lock-wscript

  • .wafpickle-N

  • .*.swp

  • .DS_Store

  • ._*

  • npm-debug.log

  • .npmrc

  • node_modules

  • config.gypi

  • *.orig

  • package-lock.json

main、module、browser

  • main : 定义了 npm 包的入口文件,browser 环境和 node 环境均可使用。如果未设置 main,则默认为包根目录下的 index.js

  • module : 定义 npm 包的 ESM 规范的入口文件,browser 环境和 node 环境均可使用

  • ·browser : 定义 npm 包在 browser 环境下的入口文件

dependencies

  • ~version:允许补丁级别的更改,如果没有,则允许次要级别的更改。

`~1.2.3` `>=1.2.3 <1.3.0-0`
`~1.2` `=>=1.2.0 <1.3.0-0`
`~1`:`>=1.0.0 <2.0.0-0`
`~0.2.3` `>=0.2.3 < 0.3.0-0`
`~0.2` `>=0.2.0 <0.3.0-0`
`~0` `>=0.0.0 <1.0.0-0`
  • ^version:允许不修改最左边的非零元素的更改 [major, minor, patch]元组。换句话说,这允许补丁和 版本 1.0.0 及以上的小更新,补丁更新 版本 0.X >=0.1.0,并且没有更新版本 0.0.X。

`^1.2.3` <==> `>=1.2.3 <2.0.0-0`
`^0.2.3` <==> `>=0.2.3 <0.3.0-0`
`^0.0.3` <==> `>=0.0.3 <0.0.4-0`

engines

engines 字段用来指定包的运行环境。

{
    "engines": {
        "node": ">=10.12.0",
        "npm": ">=6.9.0"
    }
}

除非用户设置了 engine-strict 配置标志,否则此字段仅是建议 ​​ 性的,并且只会在您的包作为依赖项安装时产生警告。

os

os 字段用来指定包将在哪些操作系统上运行。

{
    "os": [
        "darwin",
        "linux"
    ]
}

你也可以阻止包在某些操作系统上运行。

{
    "os": [
        "!darwin"
    ]
}

cpu

cpu 字段用来指定包将在哪些 CPU 架构上运行。

{
    "cpu": [
        "arm"
    ]
}

你也可以阻止包在某些 CPU 架构上运行。

{
    "cpu": [
        "!arm"
    ]
}

private

private 字段用来指定包是否为私有包。

{
    "private": true
}

如果一个包被标记为私有,那么它不能被发布到公共 npm 仓库。

publishConfig

这是一组将在发布时使用的配置值。如果您想设置标签、注册表或访问权限,它会特别方便,这样您就可以确保给定的包没有被标记为 "latest"、发布到全局公共注册表或默认情况下作用域模块是私有的。

exports 字段

在 package.json 中 exports 字端的优先级高于 main 字端。主要有以下作用。

设置子目录别名

在 package.json 文件的 exports 字端可以指定子目录或脚本的别名。

  1. 指定脚本别名

// ./node_modules/module-name/package.json
{
  "exports": {
    "./subdir": "./src/subdir.js"
  }
}

上面的代码指定,模块的 src/subdir.js 脚本可以作为 subdir 别名访问。

// ./node_modules/module-name/subdir/main.js
import { foo } from 'module-name/subdir';
  1. 指定脚本别名

// ./node_modules/module-name/package.json
{
  "exports": {
    "./subdir": "./src/subdir"
  }
}
// ./node_modules/module-name/subdir/main.js
import { foo } from 'module-name/subdir/main.js';

如果没有指定别名,就不能用“模块+脚本名”的方式访问。

// ./node_modules/module-name/subdir/main.js
// ❌ 报错
import { foo } from 'module-name/subdir/main.js';

// ✅ 不报错
import { foo } from './node_modules/module-name/subdir/main.js';

main 的别名

exports 字端的别名如果是 .,就代表模块的主入口,优先级高于 main 字端。

{
    "exports": {
        ".": "./dist/index.js"
    }
}

// 等同于
{
    "exports": "./dist/index.js"
}

exports 字端只有支持 ES6 的 Node.js 才支持,所以可以搭配 main 字端,来兼容旧版本的 Node.js。

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

条件导出

利用条件导出,可以为不同的环境指定不同的导出脚本。

{
    "exports": {
        "." {
            "import": "./dist/index.mjs",
            "require": "./dist/index.cjs",
            "default": "./dist/index.js"
        }
    }
}

// 简写如下
{
    "exports": {
        "import": "./dist/index.mjs",
        "require": "./dist/index.cjs",
        "default": "./dist/index.js"
    }
}

// ❌ 如果有其它别名,就不能采用这种简写,否则报错
{
    "exports": {
        "./subdir": "./src/subdir"
        "import": "./dist/index.mjs",
        "require": "./dist/index.cjs",
        "default": "./dist/index.js"
    }
}

上面的代码中,import 和 require 是针对 ES6 和 CommonJS 的导出脚本,default 指定其它情况下的入口(比如浏览器环境)。

CommonJS 模块加载 ES6 模块

CommonJS 的 require() 命令不能直接加载 ES6 模块,只能使用 import() 这个方法加载。

(async () => {
    await import('./my-module.mjs');
    // 或者
    await import('./my-module.js').then(module => {
        ...
    });
})();

CommonJS 在加载模块时,require() 命令是同步的,而 ES6 模块内部可以使用顶层 await 命令,导致无法被同步加载。

ES6 模块加载 CommonJS 模块

Es6 模块的 import 命令可以加载 CommonJS,但是只能整体加载,不能加载单一的输出项目。

// ✅ 正确
import main from 'commonjs-package';

// ❌ 报错
import { method } from 'commonjs-package';

因为 ES6 模块需要支持静态代码分析,而 CommonJS 模块的输出是一个对象,无法静态分析,所以只能整体加载。

如果想要在 ES6 模块中加载单一的输出项目,可以使用下述方法。

import * as pkg from 'commonjs-package';
const { method } = pkg;

同时支持两种格式的模块

  1. 如果一个模块是 ES6 模块,那么需要给出一个整体输出接口,例如 export default obj, 使得 CommonJS 可以用 import() 方法加载。

export const name = '张三';
export const age = 20;
export default {
  name,
  age,
};
import obj from './a.js'; // { name: '张三', age: 20 }
  1. 如果一个模块是 CommonJS 模块,那么可以加一个包装层来实现在 ES6 模块中使用。

import * as cjsModule form "../index.js"

export const name = cjsModule.name
export const age = cjsModule.age

上面代码先整体输入 CommonJS 模块,然后再根据需要输出具名接口。

你可以把这个文件的后缀名改为.mjs,或者将它放在一个子目录,再在这个子目录里面放一个单独的 package.json 文件,指明{ type: "module" }。

  1. 另一种做法就是在 package.json 文件中指定 exports 字段。指明两种格式各自的入口。

{
    "exports": {
        ".": {
            "import": "./index.js",
            "require": "./index.cjs"
        }
    }
}
上一页JS模块化下一页npm 缓存

最后更新于7个月前

这有帮助吗?

详细信息请参考

publishConfig