本文是系列文章, 作者一个橙子pro,本系列文章大纲如下。转载或者商业修改必须注明文章出处
一、申请npm账号、个人包和组织包区别
二、了解 package.json 相关配置
三、 了解 tsconfig.json 相关配置
四、 api-extractor 学习
五、npm
包制作完整教程,我的第一个npm包
本文涉及知识较多,建议认真阅读前面的文章。
我们打开任意一个项目的node_modules
文件夹
这里.bin
是一些可执行文件,npm run xxx
之所以能运行,是这里面的bin文件发挥了作用。.cache
是一个缓存文件夹,通常是打包工具为了提高项目再次启动的效率创建的。vite 搭建的项目还可以看到 .vite
文件夹,这个是.vite
是它的缓存。有时候在包升级或者降级时,发现并没有更新,可能就是这里的缓存出了问题,删除缓存,重新启动即可。而无需删除整个node_modules
文件夹。
这个项目包含了dist
,是vue
官方打包文件
LICENSE
是证书文件
README.md
是文档说明
package.json
是配置文件
这几个项目通常是一个npm
包当中必须存在的一些配置。
点开他的package.json
, 如下配置
"main": "dist/vue.runtime.common.js",
"module": "dist/vue.runtime.esm.js",
"name": "vue",
"typings": "types/index.d.ts", // typings 有时写成 types
可以看得到分别导出了commonjs
,es
,ts类型
这几个配置。当我们在一个项目当中执行import { xxx } from "vue"
的时候,实际上是从package.json
文件当中找到他的name
这个属性,这里 from “vue”
这个vue
就是配置文件当中的名字。
在制作包之前,强烈建议将前几部分的文章巩固一下。
这里以制作组织安装包为例,由于普通安装包和组织包在外观上只有包名上的区别。所以学会制作组织包,就等于学会了制作一般的安装包。
找个合适的文件夹,我这里取名叫做npm-pkg-by-vite
。
在文件夹打开cmd
命令行输入npm init --yes
用 vscode
打开当前文件夹,可以看到package.json
文件如下,按如下描述,对这个包进行一定的修改。
{
"name": "npm-pkg-by-vite",
"version": "1.0.0", // 暂且修改为0.0.0
"description": "", // 修改为自己合适的描述
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "", // 修改为自己的名字
"license": "ISC"
}
申请一个git
仓库,我这里github
为例。用途在这篇文章《【制作npm包2】了解 package.json 相关配置》进行了详细描述
初始化仓库
cmd
输入命令npm init --scope=v3p
,这里的v3p
是我申请的组织的名称,这里需要更换成自己申请的名字。@组织/npm-pkg-by-vite
的字样,如果需要修改,输入自定义名字就可以了。无需修改,直接回车键。1.0.0
,看心情,我这里直接回车即可我的第一个npm包
git
分支,我这里输入https://github.com/vue3plugin/npm-pkg-by-vite
一个橙子pro
MIT
package.json
文件查看,这里,在main
下方加一个type
参数{
"name": "@v3p/npm-pkg-by-vite",
"version": "1.0.0",
"description": "我的第一个npm包",
"main": "index.js",
"type": "module", // 修改为module,我们的目标包文件使用`ts`语法。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "一个橙子pro",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/vue3plugin/npm-pkg-by-vite.git"
},
"bugs": {
"url": "https://github.com/vue3plugin/npm-pkg-by-vite/issues"
},
"homepage": "https://github.com/vue3plugin/npm-pkg-by-vite#readme"
}
vite
这个打包工具,同时插件需要打包.vue
的文件。直接上命令npm i vite vue vue-tsc typescript tslib howtools @vitejs/plugin-vue @types/node @tsconfig/node18 @microsoft/api-extractor -D
创建tsconfig.json
以及tsconfig.types.json
文件。将第章节【制作npm包3】了解 tsconfig.json 相关配置中相关配置复制进去。
参照章节【制作npm包4】api-extractor 学习
cleanup.js
文件内容如下
// This file is executed from npm script with project root as cwd.
import fs from 'node:fs'
// 这个是我们在tsconfig.types.json设置的输出目录
fs.rmSync('dist/types', { recursive: true })
// 这个操作是把npm-pkg-by-vite.d.ts 换成 index.d.ts 便于package.json通用设置
fs.renameSync('dist/npm-pkg-by-vite.d.ts', 'dist/index.d.ts')
创建vite.config.ts
,将以下内容复制进去,vite更多配置参照官网。
import { defineConfig } from "vite";
import vue from '@vitejs/plugin-vue';
export default defineConfig({
build: {
lib: {
entry: "./src/index.ts", // 入口文件
fileName: (format) => `index.${format}.js`,
formats: ['es', "cjs"], // 打包同时支持`es`和`commonjs`
},
rollupOptions: {
external: ['vue'], // 这里表示不进行打包的文件
},
cssCodeSplit: false, // css 文件不分割
outDir: "dist", // 打包输出目录
minify: "esbuild", // 压缩模式
},
plugins: [
vue(), // 支持`.vue`文件
]
})
index.ts
文件,随意写入文件内容即可。创建demo
文件夹,写一个简单的vue
项目即可。scripts
设置如下"scripts": {
"dev:demo": "cd example && vite", // 运行demo
"build:demo": "cd example && vite build", // 创建demo
"build": "vite build", // 库打包
// 打包类型文件,vue-tsc 相当于 ts的 `tsc`命令,效果相同
"build-types": "vue-tsc -p ./tsconfig.types.json && api-extractor run -c api-extractor.json && node scripts/cleanup.js",
// 打包库文件和类型文件
"build-all": "npm run build && npm run build-types"
},
执行npm run build-all
,dist目录输出文件。
一个完整的npm
包至少包含,main
入口文件配置,dist
打包的文件包,README.md
文件。这样才能保证我们的项目发布到npm
之后可以被正常使用。
这个时候,用到前边章节的内容。在package.json
文件当中增加files
配置。
"files": [
"dist"
],
表示只有dist
文件夹上传到npm,其他的会忽略。这里不必担心的是,我们的开源证书、README.md文件、package.json 文件不会因为这个设置,而不进行上传。这个也是合理的,毕竟这些文件都是npm包必须的文件。
由于经过上述打包之后,我们生成了commonjs
、es
、ts类型
这几类文件,可以像vue
项目那样进行配置。
除了这几个配置,还好细细说下exports
这个配置。这个在前面章节有提及,还有一些细节需要在这里进行补充。有时我们打包之后的文件是需要分模块导出的,而不是全部直接导出。这里举个例子:
https://www.npmjs.com/package/howuse?activeTab=code
在这个文件夹当中看到很多的子包,从名称来看,每个子包都有自己的依赖,如果从index.js
直接导出,未免这个包会很重。如果只想使用pdf
这个包,无缘无故的把其他的项目也会打包到我们项目当中,对treeshaking
优化十分不利。
它的package.json
文件是这样配置的
"exports": {
"./axios": {
"import": "./axios/axios.es.js",
"require": "./axios/axios.cjs.js",
"types": "./axios/index.d.ts"
},
"./echarts": {
"import": "./echarts/echarts.es.js",
"require": "./echarts/echarts.cjs.js",
"types": "./echarts/index.d.ts"
},
// ...
},
那么在使用的时候,可以这样使用了import { xx } from 'howuse/echarts'
或者require('howuse/echarts')
,项目名加上子路径的名称,就可以直接识别到项目下面的文件目录了。这样以来,就比上边main
、module
、typings
这种散装的配置灵活不少。
【完结】