目录
前言
一、准备工作
1.1 开发环境搭建
1.1.1 环境安装
1.1.2 配置问题
1.2 账号注册
1.2.1 账号注册(两种方式)
1.2.2 登录验证
1.2.3 个人设置
1.2.4 安全配置
1.3 初始配置
1.3.1 初始项目目录
1.3.2 关键字段详解
1.3.3 手动完善
二、核心内容
2.1 核心功能
2.1.1 核心文件
2.1.2 封装代码
2.1.2 代码编写注意事项
2.2 说明文件
2.3 环境要求
2.4 使用示例
场景 1:JavaScript
场景 2:Vue 2
场景 3:Vue 3
2.5 文档说明
2.5.1 核心函数
2.5.2 回调函数
2.5.3 状态说明
2.6 注意事项
三、文件更新
更新步骤:
第一步:更新版本号
第二步:打包检查
第三步:发布新版本
第四步:验证更新结果
四、命令总结
五、本文总结
六、更多操作
前言
在现代前端和 Node.js 开发中,npm(Node Package Manager)已经成为 JavaScript 生态系统中最重要的包管理工具之一。无论是开源项目还是公司内部的私有项目,npm 都扮演着至关重要的角色。
对于许多开发者而言,将自己的代码打包发布到 npm,不仅可以方便复用,还能让团队或社区更轻松地共享代码。然而,第一次尝试发布 npm 包时,常常会遇到一些问题,比如登录失败、registry 配置错误、包名冲突等。
本文将详细介绍从 零开始发布一个 npm 包 的完整流程,并深入分析常见问题,例如 Public registration is not allowed
报错的原因及解决方案。无论你是初次接触 npm 包发布的新手,还是想系统梳理流程的老手,都可以通过本文找到清晰的参考步骤,帮助你快速掌握 npm 包从 0 到 1 的落地能力。
一、准备工作
npm 包开发前的准备工作:在编写代码前,需完成环境搭建、账号配置与项目初始化,这是确保后续流程顺利的基础。
1.1 开发环境搭建
npm 包依赖 Node.js 运行环境(npm 随 Node.js 自带),需先完成环境配置与验证。
1.1.1 环境安装
安装 Node.js 与 npm
- 下载渠道:访问Node.js 官网,根据操作系统(Windows/macOS/Linux)选择 LTS 版本(长期支持版,稳定性更高)下载安装。
- 版本要求:建议 Node.js 版本≥14.x,npm 版本≥6.x(可通过
node -v
和npm -v
命令验证安装结果)。
示例:bash
# 验证Node.js版本 node -v # 输出 v18.17.0(示例版本)# 验证npm版本 npm -v # 输出 9.6.7(示例版本)
1.1.2 配置问题
镜像源配置(避坑关键):
国内开发者常因网络问题使用第三方镜像源(如淘宝镜像https://registry.npmmirror.com
)加速依赖下载,但登录 npm 与发布包时必须切换回官方源,否则会出现 “Public registration is not allowed”“登录失败” 等报错。
- 查看当前镜像源:
bash
npm config get registry
- 临时切换官方源(发布时使用):
bash
npm config set registry https://registry.npmjs.org/
- 发布后恢复镜像源(可选,不影响后续开发):
bash
npm config set registry https://registry.npmmirror.com
1.2 账号注册
npm 账号注册与配置:npm 包的发布与管理依赖独立的 npm 账号,需完成注册、邮箱验证与个人信息配置(含头像设置)。
1.2.1 账号注册(两种方式)
npm 账号支持 “网页注册” 与 “CLI 注册”,若网页注册页面(https://www.npmjs.com/signup
)解析失败,可通过 CLI 方式注册。
-
方式 1:网页注册
- 访问:https://www.npmjs.com/signup,输入用户名(唯一,后续不可修改)、邮箱(需验证)、密码(建议包含大小写 + 数字 + 特殊符号)。
- 注册后,登录注册邮箱,点击 npm 发送的验证链接完成激活(未验证邮箱无法登录与发布包)。
-
方式 2:CLI 注册(网络异常时备选)
在终端执行以下命令,按提示输入信息,无需访问网页:bash
npm adduser # 依次输入:npm用户名 → 邮箱 → 密码 → 邮箱验证码(若触发)
1.2.2 登录验证
账号登录验证:注册并激活后,需在本地终端登录 npm 账号,确保后续发布权限:
bash
# 执行登录命令
npm login
# 输入信息:
# Username: 你的npm用户名
# Password: 你的npm密码(输入时不显示,输完按回车)
# Email: (this IS public) 你的注册邮箱
# Enter one-time password from your authenticator app: 若开启2FA,输入动态验证码
登录成功验证:执行npm whoami
,若输出你的 npm 用户名,说明登录成功;若提示 “Not logged in”,需重新检查账号密码或邮箱验证状态。
1.2.3 个人设置
个人信息与头像设置:npm 头像支持 “本地上传” 或 “关联 Gravatar”,后者可实现跨平台头像同步(如 GitHub、Stack Overflow)。
-
步骤 1:进入个人资料设置
登录 npm 官网(https://www.npmjs.com/),点击右上角 “头像图标”(默认显示首字母),选择 “Profile Settings”。 -
步骤 2:设置头像
- 本地上传:在 “Avatar” 区域点击 “Change Avatar”,选择本地图片(推荐尺寸 200x200px,格式 PNG/JPG,大小≤1MB),裁剪后保存。
- 关联 Gravatar:若页面显示 “Change your Gravatar”,点击后跳转至Gravatar 官网,使用与 npm 账号相同的邮箱登录,上传或修改头像后,npm 会自动同步(同步延迟约 5 分钟)。
- 注意:Gravatar 是 “全球通用头像服务”,一次设置可同步至所有支持 Gravatar 的平台,无需在每个平台重复上传。
1.2.4 安全配置
账号安全配置(可选但推荐):为避免账号被盗,建议开启 “二次验证(2FA)”:
- 在 “Profile Settings” 页面下滑至 “Two-Factor Authentication”,点击 “Enable 2FA”。
- 按提示下载 Authenticator 应用(如 Google Authenticator),扫描二维码绑定账号,后续登录或发布包时需输入应用生成的动态验证码。
1.3 初始配置
项目初始化与 package.json 配置:项目初始化的核心是生成package.json
文件 —— 它是 npm 包的 “身份说明书”,记录包名、版本、入口文件等关键信息,直接影响包的发布与使用。
1.3.1 初始项目目录
- 新建项目文件夹(如
websocket-encaps
,建议与包名一致),通过终端进入该目录:bash
# Windows示例 cd G:\1. My_file🔒\2 FrontEnd\Code\WebSocket # macOS/Linux示例 cd ~/FrontEnd/Code/WebSocket
- 执行初始化命令,按提示填写信息:
bash
npm init
1.3.2 关键字段详解
package.json 关键字段详解(避坑重点):npm init
过程中需填写多个字段,部分字段有严格规则,错误配置会导致发布失败或用户无法使用,以下是核心字段的含义与填写规范:
字段名 | 含义与作用 | 填写规范与注意事项 |
---|---|---|
name | 包名(npm 上唯一标识,用户通过该名称安装) | 1. 不可包含大写字母(报错 “Sorry, name can no longer contain capital letters”); 2. 不可与 npm 现有包重名(发布前需在 npm 官网搜索确认); 3. 若为私有包,建议加作用域(如 @你的用户名/websocket-encaps );示例: websocket-encaps (正确)、WebSocket-Encaps (错误)。 |
version | 版本号(遵循语义化版本规范,影响用户更新判断) | 1. 格式:major.minor.patch (主版本。次版本。补丁版本);2. 首次发布建议填 1.0.0 ;3. 不可手动修改后重复发布(需通过 npm version 更新);示例:修复 Bug 用 1.0.1 ,新增功能用1.1.0 ,破坏性变更用2.0.0 。 |
description | 包的功能描述(显示在 npm 搜索结果与包详情页) | 简洁明了,包含核心能力,便于用户快速理解;示例:“一个支持自动重连、消息封装的 WebSocket 工具包”。 |
main | 包的入口文件(用户require 或import 时加载的文件) | 1. 路径需正确(相对于package.json 的位置);2. 若核心文件为 websocket.js ,直接填websocket.js ;若在src 目录下,填src/websocket.js ;错误示例:填 ./websocket.js (虽能生效,但不符合规范)、填index.js (但实际入口是websocket.js ,导致用户引入失败)。 |
scripts | 自定义脚本(如测试、构建) | 常用脚本:"test": "node websocket.js" (执行测试)、"build": "babel src -d dist" (构建 ES5 代码);注意:若脚本为空,可直接按回车留空,后续可手动修改。 |
keywords | 搜索关键词(提升 npm 搜索排名,帮助用户找到包) | 1. 用英文逗号分隔,避免中文(npm 搜索优先识别英文); 2. 包含核心能力词,如 ["websocket", "autoreconnect", "message-encapsulation", "socket-client"] ;错误示例:填 "websocket","websocket-encaps" (多余引号,会导致关键词带引号,影响搜索)。 |
author | 作者信息(可填姓名、邮箱或 GitHub 链接) | 格式推荐:“作者名 <邮箱> (GitHub链接)” ,示例:“NCSmile <ncsmile@example.com> (https://github.com/NCSmile)” ;注意:若填 GitHub 链接,需确保链接可访问。 |
license | 开源许可证(默认ISC ,与MIT 类似,均为宽松协议) | 无需修改默认值,若需指定MIT ,直接输入MIT 即可;建议在项目根目录添加LICENSE 文件(复制对应许可证文本),增强合规性。 |
repository | 代码仓库地址(如 GitHub,便于用户查看源码、贡献代码) | 格式:"repository": { "type": "git", "url": "git+https://github.com/NCSmile/websocket-encaps.git" } ;注意:需先在 GitHub 创建仓库,再填写该字段,后续发布后会在 npm 包页面显示 “Repository” 链接。 |
1.3.3 手动完善
手动完善 package.json(可选优化):初始化完成后,可手动编辑package.json
,添加以下优化字段:
files
:指定发布到 npm 的文件范围(避免冗余文件被打包),示例:
作用:排除"files": ["websocket.js","README.md","LICENSE" ]
node_modules
、test
目录、日志文件等无需发布的内容,减小包体积。homepage
:包的主页(如 GitHub 仓库的 README 地址),示例:
作用:在 npm 包页面显示 “Homepage” 链接,方便用户查看详细文档。"homepage": "https://github.com/NCSmile/websocket-encaps#readme"
二、核心内容
npm 包核心内容开发与多场景适配:完成准备工作后,进入核心开发环节,需编写高质量代码、完善文档,并适配不同使用场景(如原生 JS、Vue2),确保包的可用性与易用性。
2.1 核心功能
核心功能代码编写(以 WebSocket 封装为例):以本文案例中的 “WebSocket 封装工具包” 为例,详细拆解核心代码的编写逻辑与注意事项,确保代码健壮性与可复用性。
2.1.1 核心文件
核心文件结构设计:推荐的项目文件结构(简洁清晰,避免冗余):
websocket-encaps/
├── websocket.js # 核心功能代码(入口文件)
├── package.json # 包配置文件
├── README.md # 使用说明文档
├── LICENSE # 开源许可证(可选)
└── .npmignore # 排除无需发布的文件(可选)
最后两个文件是可选文件,可手动创建,也可通过命令创建。
2.1.2 封装代码
WebSocket 封装代码解析:以下是websocket.js
的完整代码,包含连接初始化、自动重连、消息发送 / 接收等核心能力,并标注关键逻辑与注意事项:
javascript
/*** WebSocket封装工具包* 功能:自动重连、消息JSON解析、Token携带、状态监听* 依赖:js-cookie(用于获取用户Token,需用户项目安装)*/// 1. 定义全局变量(存储Socket实例与回调函数)
let socket = null; // Socket实例
let handleMessage = null; // 消息接收回调(用户自定义)
let handleErr = null; // 错误处理回调(用户自定义)
let reconnectTimer = null; // 重连定时器(避免频繁重连)
const RECONNECT_INTERVAL = 3000; // 重连间隔(3秒,可配置)// 2. 引入依赖(需提示用户安装js-cookie)
// 注意:若用户项目未安装,需在README中说明“npm install js-cookie”
import Cookies from 'js-cookie';
const TokenKey = 'Admin-Token'; // Token的Cookie键名(需与用户项目一致)
const getUserToken = () => Cookies.get(TokenKey) || ''; // 获取Token(兼容无Token场景)/*** 3. 初始化WebSocket连接* @param {String} url - WebSocket服务器地址(如ws://localhost:8080)* @param {Object} initData - 初始化时发送的参数(如用户ID、业务类型)* @param {Boolean} autoReconnect - 是否自动重连(默认true)*/
export function initSocket(url, initData = {}, autoReconnect = true) {// 校验WebSocket支持性(兼容低版本浏览器)if (typeof WebSocket === 'undefined') {console.error('WebSocket初始化失败:当前环境不支持WebSocket');handleErr?.('不支持WebSocket');return;}// 关闭已有连接(避免重复创建)if (socket) {socket.close(1000, '初始化新连接,关闭旧连接');socket = null;}// 4. 创建Socket实例(携带Token,支持两种传参方式)try {// 方式1:通过协议参数携带Token(适用于服务器从协议参数获取Token)const token = getUserToken();const socketUrl = token ? `${url}?token=${token}` : url;socket = new WebSocket(socketUrl);// 方式2:通过子协议携带Token(若服务器从子协议获取,需替换为以下代码)// socket = new WebSocket(url, [getUserToken()]);// 5. 监听Socket状态// 连接成功socket.onopen = (e) => {console.log('WebSocket连接成功', e);// 清除重连定时器(连接成功后停止重连)if (reconnectTimer) clearInterval(reconnectTimer);// 发送初始化参数(若有)if (Object.keys(initData).length > 0) {socketSend(initData);}};// 接收消息socket.onmessage = (e) => {try {// 解析JSON格式消息(兼容非JSON消息)const data = JSON.parse(e.data);handleMessage?.(data); // 触发用户回调} catch (err) {console.warn('WebSocket消息解析失败(非JSON格式)', e.data);handleMessage?.(e.data); // 直接传递原始消息}};// 连接错误socket.onerror = (e) => {console.error('WebSocket连接错误', e);handleErr?.('连接错误,请检查服务器地址或网络');// 触发自动重连(若开启)if (autoReconnect) startReconnect(url, initData);};// 连接关闭socket.onclose = (e) => {console.log('WebSocket连接关闭', e);// 触发自动重连(若开启且关闭码非正常关闭)if (autoReconnect && e.code !== 1000) {startReconnect(url, initData);}};} catch (err) {console.error('WebSocket创建失败', err);handleErr?.('创建连接失败');}
}/*** 6. 自动重连逻辑(避免频繁重连,增加间隔控制)* @param {String} url - WebSocket服务器地址* @param {Object} initData - 初始化参数*/
function startReconnect(url, initData) {// 清除已有定时器(避免多个定时器同时运行)if (reconnectTimer) clearInterval(reconnectTimer);// 间隔3秒重连(可根据需求调整)reconnectTimer = setInterval(() => {console.log('WebSocket尝试重连...');initSocket(url, initData);}, RECONNECT_INTERVAL);
}/*** 7. 发送消息(确保连接处于就绪状态)* @param {Object} data - 发送的消息(需为JSON可序列化格式)*/
export function socketSend(data) {// 检查Socket状态:1为连接就绪if (socket?.readyState === 1) {try {socket.send(JSON.stringify(data)); // 序列化后发送} catch (err) {console.error('WebSocket消息发送失败', err);handleErr?.('消息发送失败');}} else if (socket?.readyState === 3) {// 状态3:连接已关闭console.error('WebSocket发送失败:连接已关闭');handleErr?.('连接已关闭,无法发送消息');} else {// 状态0:连接正在建立;状态2:连接正在关闭console.warn('WebSocket发送失败:连接未就绪', socket?.readyState);handleErr?.('连接未就绪,请稍后再试');}
}/*** 8. 对外暴露的连接函数(简化用户使用)* @param {String} url - WebSocket地址* @param {Object} initData - 初始化参数* @param {Function} onMessage - 消息接收回调* @param {Function} onError - 错误处理回调* @param {Boolean} autoReconnect - 是否自动重连*/
export function connectSocket(url, initData = {}, onMessage, onError, autoReconnect = true) {// 绑定用户回调(覆盖旧回调,避免多个组件共用时冲突)handleMessage = onMessage || null;handleErr = onError || null;// 初始化连接initSocket(url, initData, autoReconnect);
}/*** 9. 关闭WebSocket连接(手动触发)*/
export function closeSocket() {if (socket) {// 正常关闭(代码1000,原因“手动关闭”)socket.close(1000, '用户手动关闭连接');socket = null;}// 清除重连定时器if (reconnectTimer) {clearInterval(reconnectTimer);reconnectTimer = null;}
}// 10. 暴露Socket实例(方便用户获取原始状态,可选)
export function getSocketInstance() {return socket;
}
2.1.2 代码编写注意事项
-
兼容性处理:
- 检查
typeof WebSocket === 'undefined'
,兼容不支持 WebSocket 的浏览器(如 IE8 及以下)。 - 消息解析时用
try-catch
包裹JSON.parse
,避免非 JSON 格式消息导致代码崩溃。
- 检查
-
资源释放:
- 关闭连接时清除重连定时器(
clearInterval(reconnectTimer)
),避免内存泄漏。 - 初始化新连接前关闭旧连接(
socket.close()
),避免重复创建连接。
- 关闭连接时清除重连定时器(
-
依赖说明:
代码依赖js-cookie
,需在 README 中明确告知用户 “安装包时需额外安装js-cookie
”(npm install websocket-encaps js-cookie
),避免用户引入时报错 “Cannot find module 'js-cookie'”。 -
参数容错:
对initData
、onMessage
等参数设置默认值(如initData = {}
),避免用户未传参导致的undefined
错误。
2.2 说明文件
README.md 编写(决定包的易用性):README.md 是用户了解包的第一入口,需包含 “安装方法、使用示例、API 文档、注意事项” 等核心内容,格式需符合 Markdown 规范,确保在 npm 官网正确渲染。
模板示例
README.md 模板(以 WebSocket 封装包为例):markdown
# websocket-encaps一个轻量级、高可用的WebSocket封装工具包,支持自动重连、消息JSON解析、Token携带,适配原生JS、Vue、React等多场景。## 🌟 核心功能
- ✅ 自动重连:连接断开后按配置间隔重试,避免手动处理重连逻辑
- ✅ Token携带:支持从Cookie获取Token,通过URL参数或子协议传递给服务器
- ✅ 消息封装:自动序列化/反序列化JSON消息,兼容非JSON格式消息
- ✅ 状态监听:暴露连接、消息、错误、关闭等回调,便于业务处理
- ✅ 资源安全:手动关闭连接时自动清除定时器,避免内存泄漏## 📦 安装
### 1. 安装核心包与依赖
本包依赖`js-cookie`获取Token,需同时安装:
```bash
# npm安装
npm install websocket-encaps js-cookie --save# yarn安装(若用户使用yarn)
yarn add websocket-encaps js-cookie......
2.3 环境要求
- Node.js:≥14.x(若用于 Node.js 环境)
- 浏览器:支持 ES6 + 与 WebSocket API(Chrome ≥43、Firefox ≥11、Edge ≥12)
- 框架:Vue 2/3、React ≥16.x、Angular ≥8.x(均兼容)
2.4 使用示例
场景 1:JavaScript
原生 JavaScript(浏览器 / Node.js)
// 1. 引入包
const { connectSocket, socketSend, closeSocket } = require('websocket-encaps');// 2. 初始化连接
const wsUrl = 'ws://localhost:8080/websocket'; // 你的WebSocket服务器地址
connectSocket(wsUrl,{ userId: '123', businessType: 'chat' }, // 初始化时发送的参数(data) => {// 3. 处理收到的消息console.log('收到服务器消息:', data);// 业务逻辑:如弹窗提醒、更新页面数据if (data.type === 'notification') {alert(`收到通知:${data.content}`);}},(errMsg) => {// 4. 处理错误console.error('WebSocket错误:', errMsg);alert(`WebSocket错误:${errMsg}`);},true // 是否自动重连(默认true)
);// 5. 发送消息(例如点击按钮时触发)
document.getElementById('sendBtn').addEventListener('click', () => {socketSend({type: 'chat',content: 'Hello, WebSocket!',timestamp: new Date().getTime()});
});// 6. 页面关闭前关闭连接(避免资源泄漏)
window.addEventListener('beforeunload', () => {closeSocket();
});
场景 2:Vue 2
<template><div class="websocket-demo"><button @click="sendChatMessage">发送聊天消息</button><div class="message-list"><div v-for="(msg, idx) in messageList" :key="idx">{{ new Date(msg.timestamp).toLocaleString() }}:{{ msg.content }}</div></div></div>
</template><script>
// 1. 引入包
import { connectSocket, socketSend, closeSocket } from 'websocket-encaps';
import Cookies from 'js-cookie'; // 若需自定义Token获取逻辑,可引入后重写export default {name: 'WebSocketDemo',data() {return {messageList: [], // 存储收到的消息wsUrl: 'ws://localhost:8080/websocket' // 服务器地址};},created() {// 2. 组件创建时初始化连接this.initWebSocket();},beforeDestroy() {// 3. 组件销毁前关闭连接(关键:避免内存泄漏)closeSocket();},methods: {// 初始化WebSocketinitWebSocket() {connectSocket(this.wsUrl,{ userId: Cookies.get('userId'), businessType: 'chat' }, // 初始化参数(携带用户ID)this.handleReceivedMessage, // 消息回调this.handleSocketError, // 错误回调true // 自动重连);},// 处理收到的消息handleReceivedMessage(data) {console.log('Vue2收到消息:', data);// 将消息添加到列表(响应式更新视图)this.messageList.push(data);// 业务逻辑:如使用Element UI的消息提示if (this.$message && data.type === 'notification') {this.$message.success(`通知:${data.content}`);}},// 处理错误handleSocketError(errMsg) {console.error('Vue2 WebSocket错误:', errMsg);this.$message?.error(`WebSocket错误:${errMsg}`);},// 发送聊天消息sendChatMessage() {const message = {type: 'chat',content: `Vue2发送的消息:${new Date().toLocaleString()}`,timestamp: new Date().getTime()};socketSend(message);}}
};
</script><style scoped>
.websocket-demo {padding: 20px;
}
button {padding: 8px 16px;margin-bottom: 15px;cursor: pointer;background: #409eff;color: #fff;border: none;border-radius: 4px;
}
.message-list {border: 1px solid #e6e6e6;padding: 10px;height: 300px;overflow-y: auto;
}
.message-list div {margin-bottom: 8px;line-height: 1.5;
}
</style>
场景 3:Vue 3
Vue 3(Composition API)
<template><div class="websocket-demo"><button @click="sendChatMessage">发送消息</button><div v-for="(msg, idx) in messageList" :key="idx">{{ msg.timestamp }}:{{ msg.content }}</div></div>
</template><script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { connectSocket, socketSend, closeSocket } from 'websocket-encaps';
import Cookies from 'js-cookie';// 响应式变量:存储消息列表
const messageList = ref([]);
const wsUrl = 'ws://localhost:8080/websocket';// 初始化连接(组件挂载时)
onMounted(() => {connectSocket(wsUrl,{ userId: Cookies.get('userId') },handleReceivedMessage,handleSocketError);
});// 关闭连接(组件卸载时)
onUnmounted(() => {closeSocket();
});// 处理收到的消息
const handleReceivedMessage = (data) => {messageList.value.push(data);console.log('Vue3收到消息:', data);
};// 处理错误
const handleSocketError = (errMsg) => {console.error('Vue3 WebSocket错误:', errMsg);// 若使用Element Plus,可调用ElMessage// ElMessage.error(`WebSocket错误:${errMsg}`);
};// 发送消息
const sendChatMessage = () => {socketSend({type: 'chat',content: `Vue3消息:${new Date().toLocaleString()}`,timestamp: new Date().getTime()});
};
</script>
2.5 文档说明
2.5.1 核心函数
函数名 | 作用 | 参数说明 |
---|---|---|
connectSocket | 初始化 WebSocket 连接 | - url :必填,WebSocket 服务器地址(如ws://localhost:8080 );- initData :可选,初始化时发送的参数(默认{} );- onMessage :可选,消息接收回调(参数为解析后的消息);- onError :可选,错误处理回调(参数为错误描述);- autoReconnect :可选,是否自动重连(默认true )。 |
socketSend | 发送消息到服务器 | - data :必填,发送的消息(需为 JSON 可序列化格式,如对象、数组)。 |
closeSocket | 手动关闭 WebSocket 连接 | 无参数。 |
getSocketInstance | 获取原始 WebSocket 实例 | 无参数,返回WebSocket 实例(可用于自定义状态监听)。 |
2.5.2 回调函数
onMessage(data)
:收到服务器消息时触发,data
为解析后的 JSON 对象(若消息非 JSON 格式,为原始字符串)。onError(errMsg)
:连接错误、发送失败等场景触发,errMsg
为错误描述字符串(如 “连接已关闭,无法发送消息”)。
2.5.3 状态说明
WebSocket 状态码说明
状态码 | 含义 | 场景说明 |
---|---|---|
0 | CONNECTING | 连接正在建立,此时调用socketSend 会提示 “连接未就绪”。 |
1 | OPEN | 连接已就绪,可正常发送 / 接收消息。 |
2 | CLOSING | 连接正在关闭,此时发送消息会失败。 |
3 | CLOSED | 连接已关闭,需重新调用connectSocket 初始化连接(自动重连会自动处理)。 |
2.6 注意事项
- Token 配置:本包默认从 Cookie 读取 Admin-Token。若 Token 键名不同,可修改
websocket.js
中的 TokenKey 常量,或在 getUserToken 函数中自定义获取逻辑。 - Token 传递方式:WebSocket 不支持自定义请求头,若服务端需通过 Header 验证 Token,建议改用 URL 参数 或 子协议 携带,并在 initSocket 函数中配置对应方式。
- 跨域处理:浏览器中 WebSocket 需服务器在握手阶段配置跨域策略(如 Access-Control-Allow-Origin)。推荐使用 wss:// 协议,以降低跨域限制风险。
- 大文件传输:传输大文件时应分片发送,避免单条消息过大导致断连。建议改用二进制格式(Blob/ArrayBuffer),并在 socketSend 中取消 JSON.stringify。
- 多组件与环境适配:多组件共用时,建议将 connectSocket 和 closeSocket 封装至全局状态管理(如 Vuex/Pinia)。Node.js 环境需安装 ws 包,并通过
global.WebSocket = require('ws')
兼容。
三、文件更新
包文件的更新:当我们已经发布了一个 npm 包,并且在后续开发过程中需要修改其中的代码或修复 bug 时,就需要对包文件进行更新和重新发布。更新流程相对简单,但一定要严格按照步骤来操作,以确保版本管理清晰,并避免对使用你包的用户造成影响。
以下是标准的 npm 包更新流程:
更新步骤:
更新 npm 包主要分为三个步骤:更新版本号 → 打包检查 → 发布新版本。
完整流程如下:
第一步:更新版本号
首先对已有的代码文件进行修改,例如在 myLib.js
中增加新的方法或修复错误。
修改完成后,务必进行本地测试,确保更新后的代码可以正常运行。
然后使用以下命令快速更新版本号:
npm version patch
版本号说明(语义化版本 SemVer):
patch
:修复 bug 或小改动,例如1.0.0 → 1.0.1
minor
:新增功能且向下兼容,例如1.0.0 → 1.1.0
major
:存在重大不兼容更新,例如1.0.0 → 2.0.0
执行 npm version patch
后,npm 会自动完成以下操作:
-
更新
package.json
中的版本号。 -
创建一个对应版本的 Git 提交和标签(如果项目在 Git 管理中)。
第二步:打包检查
在发布之前,可以先打包生成一个本地 .tgz
文件,检查即将发布的内容:
npm pack
执行后会生成类似 my-npm-package-1.0.1.tgz
的压缩包文件。
可以手动解压该文件,确认包含的代码和文件是否正确,避免发布冗余或错误文件。
建议:
使用 .npmignore
文件来控制哪些文件需要被排除在发布包之外,例如测试代码、日志文件等。
第三步:发布新版本
确认打包无误后,执行以下命令将新版本发布到 npm:
npm publish
注意事项:
如果是首次发布作用域包(scoped package),需要加上 --access public
:
npm publish --access public
--access public
的核心作用是:强制将 scope 包标记为 “公共包”,允许所有人访问和安装。
- 免费 npm 用户可以发布 公开的 scope 包(必须加
--access public
),但不能发布私有 scope 包;- 付费用户(如 npm Pro、Teams)可以发布私有 scope 包,也可以发布公开 scope 包(加
--access public
);- 无论是普通包还是公开的 scope 包,安装和使用方式完全一致,用户无需额外学习成本。
具体区别:
普通包以package-name命名,需全局唯一,默认公开,适合通用工具;scope 包以**@owner/package-name命名,仅需在@owner**下唯一,默认私有(免费用户需加 --access public 发布为公开),更适合避免命名冲突、明确归属(个人/组织)或需要私有包的场景,两者使用方式一致。
第四步:验证更新结果
发布完成后,验证更新是否成功:
-
查看最新版本信息:
npm view websocket-encaps
//或者
npm info
-
在其他项目中安装并测试:
npm install websocket-encaps
-
验证代码是否运行正常
npm view
和 npm info
是完全等价的命令,含义和功能一模一样,都是用于查询 npm 仓库中某个包的详细信息(如版本、作者、依赖、发布时间、描述等)。
小结:更新 npm 包的核心流程可以概括为三步:
更新版本号 →
npm version patch
打包检查 →
npm pack
发布新版本 →
npm publish
只要严格按照这三步执行,就能保证 npm 包的版本管理清晰、稳定,并方便用户快速升级到最新版本。
四、命令总结
下面是 npm 包发布与更新的命令总结,按流程排序,每条命令都附带简短注释,涵盖了首次发布和后续更新两种场景:
首次发布:
# 1. 初始化 package.json 文件
npm init -y # 自动生成 package.json# 2. 登录 npm 账号
npm login # 使用 npm 账号登录,输入用户名、密码、邮箱# 3. 检查即将发布的内容
npm pack # 生成本地 tar 包,检查发布文件是否正确# 4. 发布包
npm publish --access public # 首次发布作用域包需要 --access public
包的更新:
# 1. 修改代码后,更新版本号
npm version patch # 小修复,例如 1.0.0 -> 1.0.1
# 也可用 npm version minor / major# 2. 检查发布内容
npm pack # 打包检查,确保文件正确# 3. 发布新版本
npm publish # 发布更新后的版本
验证结果:
npm view 包名 # 查看包的最新版本信息
npm install 包名 # 安装最新版本测试
流程总结:
- 首次发布:初始化 → 登录 → 打包检查 → 首次发布
- 文件更新:修改代码 → 更新版本号 → 打包检查 → 发布新版本 → 验证结果
整体排序(包括同步到GitHub仓库):
首次发布(按流程):
npm config get registry
查看当前 npm 镜像源,确保发布时使用官方源(https://registry.npmjs.org/
)
npm config set registry https://registry.npmjs.org/
若当前不是官方源,切换到官方源(避免发布失败)
npm login
登录 npm 账号(输入用户名、密码、邮箱验证码,确保账号已验证邮箱)
npm init
初始化项目生成package.json
(首次发布前执行,配置包名、入口等信息)
npm version 1.0.0
首次发布时手动设置初始版本(或直接在package.json
中配置)
npm pack
打包生成.tgz
文件,预览即将发布的内容(检查核心文件是否包含,无冗余)
npm publish
首次发布包到 npm 官网(成功后终端显示+ 包名@版本号
)
git add . && git commit -m "feat: 初始版本发布"
提交代码到本地 Git 仓库(与 npm 包内容同步)
git tag v1.0.0 && git push origin v1.0.0
打版本标签并推送到 GitHub(便于版本回溯和多平台同步)更新文件(按流程):
npm version patch
修复 Bug 时更新补丁版本(如 1.0.0 → 1.0.1,语义化版本:小改动)
npm version minor
新增功能时更新次版本(如 1.0.1 → 1.1.0,语义化版本:兼容改动)
npm version major
破坏性变更时更新主版本(如 1.1.0 → 2.0.0,语义化版本:不兼容改动)
npm pack
打包预览更新内容(确认修改已生效,无错误文件)
npm publish
发布更新后的版本到 npm(覆盖旧版本,用户可通过npm update
获取)
git push origin main && git push origin --tags
推送更新后的代码和版本标签到 GitHub(保持 npm 与 GitHub 代码同步)
黄色背景部分,博主认为最为重要,具体情况,按照实际需求操作。
五、本文总结
本文总结了 npm 包从 0 到 1 的开发、发布、更新全流程,包括发布前切换 npm 官方源、开发更新时的语义化版本管理、与 GitHub 的多平台同步;同时涵盖了包名重复、版本冲突等高频问题的规避要点,帮助我们高效完成 npm 包的全生命周期维护。
通过本文,我们完整梳理了 npm 包发布与更新的全流程,从初次发布到后续维护,都给出了详细的步骤与注意事项:
-
初次发布
-
使用
npm init
初始化项目。 -
npm login
登录 npm 账号。 -
npm pack
检查发布文件。 -
npm publish --access public
首次发布包。
-
-
后续更新
-
修改代码后,通过
npm version patch
更新版本号,保持语义化版本管理。 -
使用
npm pack
确认打包内容正确。 -
npm publish
发布新版本。
-
-
验证与维护
-
通过
npm view 包名
查看版本信息。 -
在项目中使用
npm install 包名
测试最新版本。 -
持续优化并维护文档和更新日志,保证包的长期可用性。
-
npm 包发布三步走:更新版本号 → 打包检查 → 发布上线。严格执行流程,才能确保版本清晰、更新安全、用户体验良好。
六、更多操作
更多node、npm问题,请看
NodeJS(npm)https://blog.csdn.net/weixin_65793170/category_12590408.html