阅读 3108

【npm publish package】发布流程

之前在和小伙伴做一些项目学习的时候经常会写一些重复的代码,然后复制粘贴到下一个项目中使用,比如之前写了 localStoragesessionStorage 等 API 的函数封装实现。假设项目需要使用这些封装好的 API 就要自己再复制粘贴一份,假设如果发现其中有可改进或者修改的地方,那么就需要自己再将这些修改后的文件覆盖到每一个使用过的项目中。

这样的方式实在是太费时费力了,还不好管理。后来就想着经常使用的 npm package 是不是也可以将自己封装好包的也放在上面进行管理呢?而且还有版本号可以选择不同的版本,也解决了需要使用不同实现方式版本的问题,如果有修复更新还可以同步……

优点很多我就不一一描述场景了。

缺点?也有。如果考虑面向大众,那么就要开始长期维护代码。如果不考虑只是自己使用(也不在公司项目中使用)那么就没什么缺点。

好的,废话不多说了,下面就开始介绍流程。

01 - 注册一个 npmjs 账号

如果要使用 npm publish package 的服务就需要先拥有一个 npmjs 账号。

注册地址:www.npmjs.com

这个简单,也不多说了,只要记得账号密码就行。

02 - 初始化包项目

首先建立一个文件夹用于存放包项目,进入该文件夹,npm 命令以当前路径为基准。

初始化改文件夹,即 npm package 配置

npm init // 初始化 npm 配置
// 过程是以问答式 CLI 方式进行
// Q1:package name: (文件夹名字) | 默认会以文件夹名字命名,当然也可以自定义包名,但需要遵守 npm 命名规范
// Q2:version: (1.0.0) | 版本号,默认是 1.0.0,具体版本号规则,可参考《语义化版本 2.0.0》
// Q3:description: | 包描述,用于描述这个包的主要功能以及用途
// Q4:entry point: (index.js) | 入口文件,即从那个文件开始执行
// Q5:test command: | 测试命令,用于包测试的命令,可以后续补充关于测试包的编写
// Q6:git repository: | 项目的 git 存储库地址
// Q7:keywords: | 描述包的关键字,用于在 npmjs 上查询关键字
// Q8:author: | 作者名字,可以使用 npmjs 名称、npmjs 注册邮箱、github 注册邮箱
// Q9:license: (ISC) | 开源协议,默认 ISC
// Q10:输出 package.js 内容并询问 Is this OK? (yes) 默认为 yes,回车后生成文件
复制代码

至此,初始化 npm 配置步骤完成,但是并非为最终 package.js 文件内容。

03 - 编写代码

我在参考了一些开源项目的源码以及 npm module 里的信息后。

发现至少需要三个文件夹:dist | src | types

  • dist 包编译后最终产出文件
  • src 源码文件
  • types 类型支持文件

入口问题

在开发阶段 package.js 中的 main 配置是指向包的执行文件 (index.js) 。而我在开源项目的源码以及 npm module 里发现 main 的配置并非指向 src/index.js 而是指向 dist/index.js

04 - package.js 改造

如果要将包变得与众多开源 npm module 一样的话,那么就需要对 package.js 进行改造了。

package.js 中需要更改/添加以下配置信息

  • main 变更以 dist/ 为入口的 index.js 文件
  • module 以 dist/ 为入口的功能模块文件
  • unpkg 以 dist/ 为入口的 index.js 文件,非官方字段用于 cdn 服务
  • jsdelivr 与 unpkg 配置相同,非官方字段用于 cdn 服务
  • typings 类型支持文件 types/index.d.ts(大部分 npm 包使用 TypeScript 开发)
  • files 配置所需文件列表 [ "src/*.js", "dist/*.js", "types/*.d.ts" ]

如果需要进行测试运行代码的话就需要编写代码通过配置 test command 来进行代码的运行和测试了。

05 - 模块化标准

目前我看到的使用模块化标准的主要分为2个流派,一个是 ES6 一个是 TypeScript。构建使用的模块化打包工具中 rollup 是使用最多的,一部分使用了 gulp

这里我也是选择了使用 TypeScript 来进行编写,所以会以 TypeScript + rollup 为例。

Rollup 所需包

  • rollup rollup 核心功能
  • @rollup/plugin-buble Convert ES2015 with buble. 将 ES6+ 代码编译成 ES2015 标准
  • @rollup/plugin-replace 编译过程中动态替换代码中的内容
  • @rollup/plugin-commonjs commonjs 模块标准支持
  • @rollup/plugin-node-resolve 编译过程中帮助 rollup 查找外部的模块并支持合并
  • rollup-plugin-flow-no-whitespace 编译过程中 将 flow 静态类型检查进行忽略
  • rollup-plugin-typescript2 将 TypeScript 转换成为 ES6+ 标准

不再维护的包

  • rollup-plugin-buble
  • rollup-plugin-replace
  • rollup-plugin-commonjs
  • rollup-plugin-node-resolve

额外使用的包

  • @babel/core // babel 的核心包
  • @babel/plugin-syntax-dynamic-import // babel 异步动态 import
  • terser // 代码的压缩混淆
  • typescript // 如果使用了 TypeScript

Rollup 的使用

Rollup 的 options

{
  input: { // 输入配置
    input: resolve('src/index.js'),
    plugins: [] // 使用的插件列表
  },
  output: { // 输出配置
    file: resolve('dist/web-storage.js'), // 构建文件生成路径
    format: 'umd', // 构建模块标准
    name: 'WebStorage', // 导出命名
    env: 'development' || 'production', // 根据控制台命令环境判断,如无需则不写
    transpile: false || true, // 透明的?目前没看到文档解释 <- X | 自定义字段,用于判断是否需要 buble 插件参与编译构建
  }
}
复制代码

Rollup 使用了 Promise 封装了调用流程,后续操作都很方便的通过 then 的回调函数进行处理。

rollup
.rollup(input) // 输入配置 input
.then(bundle => bundle.generate(output)) // 输出配置 output,通过 generate 函数来生成源码的规格:cjs es min 等
.then(bundle => { console.dir(bundle) }) // generate 函数生成的源码字符串结果
复制代码

在拿到生成的源码字符串后使用 nodejs 的 fs.writeFile 函数来进行写入生成文件。

06 - 将包 publish 至 npm 上

要将包发布先要登录 npm

npm login // 登录命令
Username: // 输入注册时候的用户名
Password: // 密码
Email: (this IS public) // 注册时的邮箱
复制代码

登录完成后即可使用 publish 将 package 上传至 npm 了。

npm publish // publish 时会以 package.js 里 name 属性为包名
// 稍等一段时间,就可以通过 install 进行安装使用了。
npm i 包名
复制代码

如果包有更新代码,那么需要更新版本号,否则无法进行发布。

07 - 将包从 npm 上删除

// 需要先登录
npm unpublish 包名 // 即可将 npm 上的包删除
复制代码

error: cannot be republished until 24 hours have passed.

删除已在 npm 发布的同名包,需要在24小时后才能重新发布

最后

以上就是在从开发到配置再到发布的一系列流程了,其实在刚入手尝试的过程中还是踩了不少的坑,比如把一些不再维护的包和可替换的包都整理出来了。这个过程中使用了 TypeScript 来实现,也算是实战了一把,不过代码还是有可优化的地方。

目前也在不断的学习以及使用 TypeScript,难度倒是不算太大,主要还是习惯和熟练度的问题以及设计/解决思路的问题。

我自己封装好的 Web Storage API 已经发布到 npm publish 上了。

npm:cat-web-storage

github:cat-web-storage

目前还只是支持 Vue 项目。

  • 计划支持非 Vue 的普通 web 项目也可以使用(开发进行中)。
  • 计划把 indexedDB API 也集成封装进去(开发进行中)。
  • ReactJs、AngularJs 有很好的 npm 包了,暂时不考虑支持。
  • npm 包名:cat-web-storage

版权声明:

本文版权属于作者 林小帅,未经授权不得转载及二次修改。

转载或合作请在下方留言及联系方式。

文章分类
前端
文章标签