一文彻底搞懂package.json中的exports, main, module, type
package.json每天都会用到,但是你真的对里面的某些字段很了解吗,本文将带你了解其中经常使用的一些字段
repository/homepage
项目的仓库地址, 会显示在npm package右侧
{
"repository": {
"type": "git",
"url": "git+https://github.com/jerrywu001/sandpack-vue3.git"
},
"homepage": "https://sandpack-vue3.netlify.app",
}
main/module/types
{
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
}
- main
对应commonjs引入方式的程序入口文件
const { Sandpack } = require('sandpack-vue3);
- module
对应esmodule引入方式的程序入口文件
import { Sandpack } from 'sandpack-vue3';
- types
描述了程序中所有组件以及变量的类型定义
exports
介绍
exports定义了自定义导出规则,可以理解为路径映射
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./unstyled": {
"types": "./dist/unstyled.d.ts",
"import": "./dist/unstyled.mjs",
"require": "./dist/unstyled.js"
}
},
}
实战案例
测试了
vite
|@vue/cli
|nuxt3
|vitepress
,保证了解决方案的有效性。
import { Sandpack } from 'sandpack-vue3';
import { Sandpack as UnstyledPack } from 'sandpack-vue3/unstyled';
import 'sandpack-vue3/dist/styles.css';
以上的案例代码存在一些问题
-
build过程,无法识别'sandpack-vue3/dist/styles.css'路径
- 解决方案:
{ "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.js" }, "./unstyled": { "types": "./dist/unstyled.d.ts", "import": "./dist/unstyled.mjs", "require": "./dist/unstyled.js" }, + "./*": [ + "./*", + "./*.d.ts" + ] }, }
-
ts无法识别'sandpack-vue3/unstyled'路径
-
解决方案 (增加的两段内容,缺一不可!):
特别需要注意的是:dist目录下需要保证unstyled.d.ts存在,并且需要和exports中子路径名称一致,否则依然无法找到路径
{ "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.js" }, "./unstyled": { // <-需和dist下unstyled.d.ts文件名称一致 "types": "./dist/unstyled.d.ts", // 可以省略,但不建议 "import": "./dist/unstyled.mjs", "require": "./dist/unstyled.js" }, + "./*": [ + "./*", + "./*.d.ts" + ] }, + "typesVersions": { + "*": { + "*": [ + "./dist/*", + "./*" + ] + } }, }
-
type和exports/main/module的关系
首先我们需要理解type字段的含义:
当设置为“module”时,所在项目中(不包含node_modules)所有.js文件将被视为EsModule类型文件。
如果省略“type”字段或设置为“commonjs”,则项目中(不包含node_modules)所有.js文件都被视为CommonJS类型文件。
type: "module"
此时.js文件将被视为esmodule,并且我们需要将commonjs文件显示声明为.cjs
改造配置如下:
{
...,
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./unstyled": {
"types": "./dist/unstyled.d.ts", // 可以省略,但不建议
"import": "./dist/unstyled.js",
"require": "./dist/unstyled.cjs"
},
"./*": "./*"
},
...
}
type: "commonjs" 或不设置
此时.js将被视为commonjs,并且我们需要将esmodule文件显示声明为.mjs/.esm.js(实际上你声明成.xxx.js也可以,甚至.xxx也行,但不建议)
改造配置如下:
{
...,
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"./unstyled": {
"types": "./dist/unstyled.d.ts", // 可以省略,但不建议
"import": "./dist/unstyled.mjs",
"require": "./dist/unstyled.js"
},
"./*": "./*"
},
...
}
main/module 和 exports的关系
exports省略场景
如果没有子路径,比如m没有my-package/xxx
,只是简单的my-package
, 那配置可以简化为:
{
...,
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
...
}
exports不可省略场景
存在子路径,此时需要添加exports进行路径映射,并且export中的"."配置会具有较高优先级,所以"."对应的路径必须是真实存在的(这么一说,即使你在main/module中的路径写错了,也没关系,感兴趣的可以自行尝试一下)。
子路径不想放根目录下??
有时候我们有想把子路径文件放单独文件夹的想法,可行吗?答案是,可以的,但是我们必须保证dist根目录下xxx.d.ts
真实存在,除它之外的其他文件可以单独文件夹,举个🌰:
好了,文章到此结束,如对您有帮助,还请帮忙点个小🌟🌟,不甚感激~