npm发布js工具包

一、创建项目

  • 1、在github上创建一个项目,然后拉取至本地,进入项目目录
  • 2、执行 npm init 生成json文件
  • 3、创建 src/index.ts 入口文件和 src/isObject.ts 工具方法
· src/index.ts
export { default as isObject } from './isObject'
· src/isObject.ts
/*** @description 判断是否为对象* @param {*} variable* @returns {Boolean}*/
function isObject(variable: any): boolean {return Object.prototype.toString.call(variable) === '[object Object]'
}export default isObject

二、配置Rollup打包

  • 1、安装rollup和typescript npm install rollup typescript -D
  • 2、创建 tsconfig.json 配置文件:
{"compilerOptions": {"target": "es5" /* 编译目标 */,"module": "commonjs" /* 项目模块类型 */,"lib": ["ES2018", "DOM"],"allowJs": true /* 是否允许js代码 */,"checkJs": true /* 检查js代码错误 */,"declaration": true /* 自动创建声明文件(.d.ts) */,"declarationDir": "./lib/types" /* 声明文件目录 */,"sourceMap": true /* 自动生成sourcemap文件 */,"outDir": "lib" /* 编译输出目录 */,"rootDir": "./src" /* 项目源码根目录,用来控制编译输出的目录结构 */,"strict": true /* 启用严格模式 */},"include": ["src/*.ts"],"exclude": ["node_modules", "lib"],
}
  • 3、安装rollup插件
    · 处理路径 npm install @rollup/plugin-node-resolve -D
    · 支持ts npm install @rollup/plugin-typescript -D
    · 处理commonjs npm install @rollup/plugin-commonjs -D
    · 压缩umd规范的输出文件 npm install @rollup/plugin-terser -D
    · 重新打包代码清理 npm install rollup-plugin-delete -D
  • 4、创建 rollup.config.js 配置文件:
const resolve = require('@rollup/plugin-node-resolve') // 处理npm包的相关引入依赖
const typescript = require('@rollup/plugin-typescript')
const commonjs = require('@rollup/plugin-commonjs') // 将commonJS的语法转化成ES2015 Module
const terser = require('@rollup/plugin-terser') // 代码压缩
const del = require('rollup-plugin-delete')module.exports = [{input: './src/index.ts',output: [{dir: 'lib',format: 'cjs',entryFileNames: '[name].cjs.js',sourcemap: true, // 是否输出sourcemap},{dir: 'lib',format: 'esm',entryFileNames: '[name].esm.js',sourcemap: true, // 是否输出sourcemap},{dir: 'lib',format: 'umd',entryFileNames: '[name].umd.js',name: 'Umob', // umd模块名称,自动挂载至windowsourcemap: true,plugins: [terser()],},],plugins: [del({ targets: 'lib/*' }),resolve(),commonjs(),typescript({ module: 'ESNext' }),],},
]
  • 5、在package.json配置的scripts中增加构建脚本 "build": "rollup -c"
  • 6、执行 npm run build

三、手动发布

  • 1、完善配置文件
· .npmignore
src/
node_modules/
.babelrc
.gitignore
· package.json
{"name": "your project name","version": "0.0.1","description": "your project description","browser": "lib/index.esm.js", // umd规范"module": "lib/index.esm.js", // 使用esm时,会使用这个包"jsnext:main": "lib/index.esm.js",  // 社区规范"main": "lib/index.cjs.js", // 当使用commonjs规范时会使用这个包"types": "lib/types/index.d.ts", // ts类型文件"files": ["lib"], // 用于约定在发包的时候NPM 会发布包含的文件和文件夹。"scripts": {"build": "rollup -c",},"keywords": ["modules","stdlib","util"],"author": "Unknow","license": "MIT","devDependencies": {"@rollup/plugin-commonjs": "^25.0.0","@rollup/plugin-node-resolve": "^15.1.0","@rollup/plugin-terser": "^0.4.3","@rollup/plugin-typescript": "^11.1.1","rollup": "^3.23.0","rollup-plugin-delete": "^2.0.0","tslib": "^2.5.2","typescript": "~5.0.4"},"repository": {"type": "git","url": "https://github.com/xxx.git"}
}
  • 2、登陆npm账号(没有去官网注册一个) npm login
  • 3、查看是否登录成功 npm who am i
  • 4、将包推送至服务器 npm publish
  • 5、package中的name不可与他人重复,否则会提示权限问题。如果使用@[scope]/package的命名形式,[scope]需要填账户名称

四、安装jest单元测试

  • 1、安装 install jest ts-jest @types/jest jest-environment-jsdom -D
  • 2、根目录下新增配置文件:
· .jest.config.js
/** @type {import('ts-jest').JestConfigWithTsJest} */module.exports = {preset: 'ts-jest',testEnvironment: 'jsdom', clearMocks: true,collectCoverage: true,coverageDirectory: 'coverage',coverageProvider: 'v8',moduleFileExtensions: ["ts", "js"],// 配置测试环境uatestEnvironmentOptions: {userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',},
}

3、在 package.json 配置的scripts中增加测试脚本 "test": "jest"
4、编写单元测试:

· src/tests/isObject.test.ts
import { isObject } from '../index'describe('isObject: ', () => {it('Determine the type of number', async () => {expect(isObject(1)).toEqual(false)})it('Determine the type of string', async () => {expect(isObject('1')).toEqual(false)})it('Determine the type of boolean', async () => {expect(isObject(false)).toEqual(false)})it('Determine the type of array', async () => {expect(isObject([])).toEqual(false)})it('Determine the type of undefined', async () => {expect(isObject(undefined)).toEqual(false)})it('Determine the type of null', async () => {expect(isObject(null)).toEqual(false)})it('Determine the type of symbol', async () => {const symbol2 = Symbol('this is symbol')expect(isObject(symbol2)).toEqual(false)})it('Determine the type of empty object', async () => {expect(isObject({})).toEqual(true)})
})
  • 5、增加单文件单元测试命令,用于团队本地开发测试使用 "test:single": "node env-dependencies.js"
  • 6、在根目录下创建 env-dependencies.js.env.json 文件
· env-dependencies.js
const execSync = require('child_process').execSync
const pkg = require('./package.json')
const fs = require('fs')
const path = require('path')
const JSON_FILE_NAME = '.env.json'
const DEFAULT_TEST_FILE_NAME = 'isObject'
const filePath = path.join(__dirname, JSON_FILE_NAME) // 文件路径// 检查文件是否已存在
if (!fs.existsSync(filePath)) {const content = {TEST_FILE_NAME: DEFAULT_TEST_FILE_NAME,}const jsonContent = JSON.stringify(content, null, 4)try {fs.writeFileSync(filePath, jsonContent, 'utf8')} catch (err) {console.error('写入文件时发生错误:', err)}
}if (!pkg.envDependencies) {process.exit(0)
}let env = Object.assign({}, process.env)try {Object.assign(env, require('./' + JSON_FILE_NAME))
} catch (err) {console.log('Could not read or parse JSON_FILE_NAME.')
}if (typeof pkg.envDependencies.params === 'undefined') {console.log('pkg.envDependencies.params not found or empty. Passing.')process.exit(0)
}if (!Array.isArray(pkg.envDependencies.params) ||!(pkg.envDependencies.params.every(item => typeof item === 'string'))
) {throw new Error('pkg.envDependencies.params should have a signature of String[]')
}const parsed = pkg.envDependencies.params.map(item => item.replace(/${([0-9a-zA-Z_]*)}/g, (_, varName) => {if (typeof env[varName] === 'string') {return env[varName]} else {throw new Error('Could not read env variable ' + varName + ' in params ' + item)}
})).join(' ')try {execSync(parsed, { stdio: [0, 1, 2] })process.exit(0)
} catch (err) {}
· .env.json
{"TEST_FILE_NAME": "isObject"
}
· 在package.json中增加字段
"envDependencies": {"params": ["jest ./src/__tests__/${TEST_FILE_NAME}.test.ts --coverage --collectCoverageFrom=./src/${TEST_FILE_NAME}.ts"]
}
  • 7、配置 .gitignore.npmignore,忽略 .env.json 的提交
  • 8、运行 npm run test:single,可测试 .env.jsonTEST_FILE_NAME 字段配置的文件名

五、安装eslint

  • 1、安装 install eslint eslint-config-airbnb @typescript-eslint/eslint-plugin @typescript-eslint/parser -D
  • 2、新增配置文件:
· .eslintrc.js
module.exports = {root: true,env: {browser: true,node: true,},extends: ['airbnb','plugin:@typescript-eslint/recommended',],parser: '@typescript-eslint/parser',plugins: ['@typescript-eslint',],globals: {NodeJS: 'readonly',},settings: {'import/resolver': {node: {extensions: ['.js', '.ts']},},react: {version: '0.0.0',},},rules: {// 添加自定义规则'no-console': 2,'no-debugger': 2,},
}
  • 3、增加lint命令 "lint": "eslint --ext .ts src/"
  • 4、运行 npm run lint
  • 5、安装husky,在代码提交前自动执行eslint校验 npm install husky --save-dev
  • 6、启用git钩子 npx husky install
  • 7、向package.json文件设置prepare脚本 npm pkg set scripts.prepare="husky install"
  • 8、新增一个pre-commit钩子 npx husky add .husky/pre-commit "npm run lint"

六、自动化发布

  • 1、在npm中生成 Access Tokens
    在这里插入图片描述

  • 2、将token复制到github对应仓库的秘钥中
    在这里插入图片描述

  • 3、设置一个变量名 NPM_ACCESS_TOKEN,用于之后CI中通过 secrets.NPM_ACCESS_TOKEN 获取

  • 4、在根目录下创建 .github/workflows/node.js.yml 配置文件

name: Build CIon:push:branches: [ "main" ]jobs:build:runs-on: ubuntu-latestpermissions:contents: writestrategy:matrix:node-version: [16.20.0]steps:- name: 检出分支uses: actions/checkout@v3- name: 初始化缓存uses: actions/cache@v3id: cache-dependencieswith:path: node_moduleskey: ${{runner.OS}}-${{hashFiles(\'**/package-lock.json\')}}- name: Use Node.js ${{ matrix.node-version }}# 使用actions/setup-node插件uses: actions/setup-node@v3with:# node版本node-version: ${{ matrix.node-version }}cache: 'npm'- run: npm ci# 生成测试覆盖率- run: npm run test- run: npm run build- name: 上报测试覆盖率id: coverRateuses: coverallsapp/github-action@masterwith:github-token: ${{ secrets.GITHUB_TOKEN }}- name: 读取版本号id: versionuses: notiz-dev/github-action-json-property@releasewith:# 读取版本号path: './package.json'prop_path: 'version'- name: 打印版本号run: echo ${{steps.version.outputs.prop}}- name: 创建Releaseuses: softprops/action-gh-release@v1with:files: |./lib/index.umd.js./lib/index.esm.js./lib/index.cjs.jsname: v${{steps.version.outputs.prop}}tag_name: v${{steps.version.outputs.prop}}env:GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}- name: 发布NPM包run: |npm config set //registry.npmjs.org/:_authToken=$NPM_TOKENnpm publishenv:# 配置 npm access token 环境变量NPM_TOKEN: ${{secrets.NPM_ACCESS_TOKEN}}

七、为readme添加测试覆盖率badge

  • 1、进入coveralls官网,授权 github,https://coveralls.io/
  • 2、授权后点击左侧侧边栏的 ADD REPOS,将需要生成badge徽章的库设置为on
  • 3、在readme中添加连接即可查看 <img src='https://coveralls.io/repos/github/{用户名}/{仓库名}/badge.svg?branch=main' />

八、整体目录结构

- .github- workflows- xx.yml        # git Actions
- .husky_pre-commit          # git提交钩子
- src- __test__          # 单元测试- index.ts          # 入口文件- isObject.ts
- .env.json             # 环境变量配置
- .eslintignore
- .eslintrc.js
- .gitignore
- .npmignore
- env-dependencies.js   # 环境变量读取脚本
- jest.config.js
- package.json
- rollup.config.js
- tsconfig.json

九、完整package.json配置

{"name": "your project name","version": "0.0.1","description": "your project description","browser": "lib/index.esm.js","module": "lib/index.esm.js","jsnext:main": "lib/index.esm.js","main": "lib/index.cjs.js","types": "lib/types/index.d.ts","files": ["lib"],"scripts": {"lint": "eslint --ext .ts src/","build": "rollup -c","test": "jest","test:single": "node env-dependencies.js","prepare": "husky install"},"envDependencies": {"params": ["jest ./src/__tests__/${TEST_FILE_NAME}.test.ts --coverage --collectCoverageFrom=./src/${TEST_FILE_NAME}.ts"]},"keywords": ["modules", "stdlib", "util"],"author": "Unknow","license": "MIT","devDependencies": {"@rollup/plugin-commonjs": "^25.0.0","@rollup/plugin-node-resolve": "^15.1.0","@rollup/plugin-terser": "^0.4.3","@rollup/plugin-typescript": "^11.1.1","@types/jest": "^29.5.2","@typescript-eslint/eslint-plugin": "^5.59.9","@typescript-eslint/parser": "^5.59.9","babel-jest": "^29.5.0","eslint": "^8.42.0","eslint-config-airbnb": "^19.0.4","husky": "^8.0.3","jest": "^29.5.0","jest-environment-jsdom": "^29.5.0","rollup": "^3.23.0","rollup-plugin-delete": "^2.0.0","ts-jest": "^29.1.0","tslib": "^2.5.2","typescript": "~5.0.4"},"repository": {"type": "git","url": "https://github.com/xxx.git"}
}

References

[1] 使用Typescript和Rollup从零开发一个工具库

[2] 一篇文章教会你如何在npm上传自己的包

[3] husky工具介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/595960.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[C#]yolov8-onnx在winform部署手势识别模型

【官方框架地址】 https://github.com/ultralytics/ultralytics.git 【算法介绍】 YOLOv8 是一个 SOTA 模型&#xff0c;它建立在以前 YOLO 版本的成功基础上&#xff0c;并引入了新的功能和改进&#xff0c;以进一步提升性能和灵活性。具体创新包括一个新的骨干网络、一个新…

专题一:递推与递归

递归 例题 递归实现指数型枚举 从 1∼n这 n个整数中随机选取任意多个&#xff0c;输出所有可能的选择方案。 输入格式 输入一个整数 n。 输出格式 每行输出一种方案。 同一行内的数必须升序排列&#xff0c;相邻两个数用恰好 1 个空格隔开。 对于没有选任何数的方案&#xff0c…

抖店申请流程是什么?

我是电商珠珠 想要入驻抖店的人很多&#xff0c;但是知道流程的新手却没有几个。 从开店资料到入驻流程&#xff0c;我来具体的跟大家讲一讲。 第一个&#xff0c;新手开店资质 1、营业执照 营业执照是入驻门槛之一&#xff0c;营业执照类型分为两类&#xff0c;一类为企业…

鸿蒙4.0开发实战(ArkTS)-闹钟制作

闹钟功能要求 展示指针表盘或数字时间。添加、修改和删除闹钟。展示闹钟列表&#xff0c;并可打开和关闭单个闹钟。闹钟到设定的时间后弹出提醒。将闹钟的定时数据保存到轻量级数据库。 闹钟主界面 闹钟界面包括当前时间、闹钟列表、添加闹钟子组件&#xff0c;具体包括以下…

共享企业文件数据信息:实用方法与技巧分享

在当下快节奏的企业办公生活中&#xff0c;如何有效且高效的进行企业文件数据信息共享&#xff0c;保持企业竞争力&#xff0c;是许多企业团队面临的问题。 诚然&#xff0c;社交媒体工具的出现可以缓解企业信息共享协作的痛点。然而&#xff0c;多平台工具的交叉使用又使企业…

Zuul相关面试题及到案(2024)

1、什么是Zuul&#xff1f;它在微服务架构中有什么作用&#xff1f; Zuul是Netflix开源的一种提供API网关服务的应用程序&#xff0c;它在微服务架构中扮演着流量的前门角色。主要功能包括以下几点&#xff1a; 路由转发&#xff1a;Zuul网关将外部请求转发到具体的微服务实例…

斯坦福和 Meta学者发现Gemini在常识推理任务中有较强潜力;初学者GPT:Ai和LLM资源

&#x1f989; AI新闻 &#x1f680; 斯坦福和 Meta学者发现Gemini在常识推理任务中有较强潜力 摘要&#xff1a;斯坦福和Meta的学者发表论文为Gemini正名&#xff0c;他们发现之前对Gemini的评估并不能完全捕捉到其真正的常识推理潜力。他们设计了需要跨模态整合常识知识的任…

vue-mixins混入处理

定义 mixins&#xff08;混入&#xff09;&#xff1a;一种分发 Vue 组件中可复用功能的非常灵活的方式&#xff0c;mixins 是一个 js 对象&#xff0c;它可以包含我们组件script中的任意功能选项&#xff0c;如&#xff1a;data、components、methods、created、computed 等等…

MySQL 存储引擎和索引类型介绍

1. 引言 MySQL 是一个流行的关系型数据库管理系统&#xff0c;提供多种存储引擎以满足不同的业务需求。本文将介绍几种常见的 MySQL 存储引擎和索引类型比较&#xff0c;并给出相应的示例。 2. 存储引擎概述 2.1 InnoDB 存储引擎 InnoDB 是 MySQL 的默认存储引擎&#xff0…

多线程实践项目

前言 前面几篇文章分别学习了多线程的基本知识和线程池使用&#xff0c;这篇则为项目实践和整理。 项目参考 选择了两个项目github地址&#xff0c;如果不方便下载可以下面留言评论私发。 1.马士兵老师的juc&#xff0c;讲述了多线程的基本知识线程讲解 2.基本的线程演示&am…

学习JavaEE的日子 day08 方法的重载,递归,万年历

day08 1.方法的重载 >理解&#xff1a;方法与方法之间的关系> 条件&#xff1a;> 1.方法必须在同一个类中> 2.方法名必须一致> 3.参数列表的个数或者类型不一致> 4.与返回值无关> 好处&#xff1a;系统会根据具体实参类型自动匹配到对应的方法…

【vue】emit 的理解与使用

文章目录 介绍流程示例效果父组件子组件 介绍 $emit 是 Vue 组件实例中的一个方法&#xff0c;用来触发自定义事件&#xff0c;并向父组件传递信息它接受两个参数&#xff1a;事件名称和可选参数this.$emit(事件名称, 参数);流程 示例 效果 触发前 触发后 父组件 父组件使…

FBL刷写

刷写 1、刷写需求的理解2、刷写流程2.1、预编程阶段&#xff1a;保证在编程阶段的动作能够正常操作&#xff0c;控制器给响应。整车功能不会出现问题 刷写某一控制器时&#xff0c;避免其他控制器集DTC,85控制DTC&#xff1b; 28 通信控制.保证总线负载率不要过高&#xff08;下…

shell脚本实现九九乘法表

9*9乘法表 判断服务是否开启 1.查看80端口是否被监听 [rootlocalhost ~]# ss -an | grep 80 tcp LISTEN 0 128 *:80 *:* 2.查看80端口/httpd服务是否开启 [rootlocalhost ~]# n…

AndroidStudio导入jar包

目录 1. 转为Project模式 2. 将jar文件粘贴到app/libs文件夹中 3. 右键jar 包&#xff0c;点击Add As Library 在AndroidStudio中导入jar包&#xff08;jar文件&#xff09;。 1. 转为Project模式 2. 将jar文件粘贴到app/libs文件夹中 3. 右键jar 包&#xff0c;点击Add As…

109-Gradle构建工具的学习

Gradle构建工具的学习 Gradle 简介&#xff1a; Gradle 是一款Google 推出的基于 JVM、通用灵活的项目构建工具&#xff0c;支持 Maven&#xff0c;JCenter 多种第三方仓库&#xff0c;支持传递性依赖管理、废弃了繁杂的xml 文件&#xff0c;转而使用简洁的、支持多种语言&am…

jmeter使用心得(一)

jmeter作为接口测试的常用工具之一&#xff0c;在我们的测试中经常会用到&#xff0c;往期的文章中&#xff0c;我们也分享过jmeter的各种功能和用法&#xff0c;基本覆盖了方方面面&#xff0c;可以满足各种接口测试的需求。但实际测试中我们也会发现&#xff0c;jmeter这么强…

前置微小信号放大器有哪些经典应用场景

前置微小信号放大器是电子系统中的关键组件&#xff0c;用于放大输入信号的微小幅度&#xff0c;以提高信号与噪声比和系统的灵敏度。这些放大器在各种应用中发挥着关键作用&#xff0c;以下是前置微小信号放大器的一些经典应用场景&#xff1a; 通信系统&#xff1a; 前置微小…

CSS案例:flex、justify-content、align-items

黑马程序员JS学习时的一个案例&#xff0c;CSS有点不懂&#xff0c;单拎出来分析。 具体出处是某站视频中的数组篇讲解&#xff0c;&#xff08;点击链接跳转&#xff09; CSS案例 效果&代码1. 先分析最大的boxflex布局 justify-contentalign-items以 flex-end 为例 2. box…

公众号文章如何提高阅读量?媒介盒子教你几招

公众号作为微信运营的主要载体&#xff0c;做得好就能让品牌得到大量曝光&#xff0c;公众号文章作为长文案想要写好还需要一定的技术&#xff0c;今天媒介盒子就来和大家聊聊公众号文章怎么写才能提高阅读量&#xff1a; 一、 内容干货满足读者求知欲 只要你的文章实用性强&…