目录
前言
一、准备工作
[1.1 开发环境搭建](#1.1 开发环境搭建)
[1.1.1 环境安装](#1.1.1 环境安装)
[1.1.2 配置问题](#1.1.2 配置问题)
[1.2 账号注册](#1.2 账号注册)
[1.2.1 账号注册(两种方式)](#1.2.1 账号注册(两种方式))
[1.2.2 登录验证](#1.2.2 登录验证)
[1.2.3 个人设置](#1.2.3 个人设置)
[1.2.4 安全配置](#1.2.4 安全配置)
[1.3 初始配置](#1.3 初始配置)
[1.3.1 初始项目目录](#1.3.1 初始项目目录)
[1.3.2 关键字段详解](#1.3.2 关键字段详解)
[1.3.3 手动完善](#1.3.3 手动完善)
二、核心内容
[2.1 核心功能](#2.1 核心功能)
[2.1.1 核心文件](#2.1.1 核心文件)
[2.1.2 封装代码](#2.1.2 封装代码)
[2.1.2 代码编写注意事项](#2.1.2 代码编写注意事项)
[2.2 说明文件](#2.2 说明文件)
[2.3 环境要求](#2.3 环境要求)
[2.4 使用示例](#2.4 使用示例)
[场景 1:JavaScript](#场景 1:JavaScript)
[场景 2:Vue 2](#场景 2:Vue 2)
[场景 3:Vue 3](#场景 3:Vue 3)
[2.5 文档说明](#2.5 文档说明)
[2.5.1 核心函数](#2.5.1 核心函数)
[2.5.2 回调函数](#2.5.2 回调函数)
[2.5.3 状态说明](#2.5.3 状态说明)
[2.6 注意事项](#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
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
bashnpm 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
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 地址),示例:"homepage": "https://github.com/NCSmile/websocket-encaps#readme"
作用:在 npm 包页面显示 "Homepage" 链接,方便用户查看详细文档。
二、核心内容
npm 包核心内容开发与多场景适配:完成准备工作后,进入核心开发环节,需编写高质量代码、完善文档,并适配不同使用场景(如原生 JS、Vue2),确保包的可用性与易用性。
2.1 核心功能
核心功能代码编写(以 WebSocket 封装为例):以本文案例中的 "WebSocket 封装工具包" 为例,详细拆解核心代码的编写逻辑与注意事项,确保代码健壮性与可复用性。
2.1.1 核心文件
核心文件结构设计:推荐的项目文件结构(简洁清晰,避免冗余):
bash
websocket-encaps/
├── websocket.js # 核心功能代码(入口文件)
├── package.json # 包配置文件
├── README.md # 使用说明文档
├── LICENSE # 开源许可证(可选)
└── .npmignore # 排除无需发布的文件(可选)
最后两个文件是可选文件,可手动创建,也可通过命令创建。
2.1.2 封装代码
WebSocket 封装代码解析:以下是websocket.js
的完整代码,包含连接初始化、自动重连、消息发送 / 接收等核心能力,并标注关键逻辑与注意事项:
javascript
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
javascript
# 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)
javascript
// 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
javascript
<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: {
// 初始化WebSocket
initWebSocket() {
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)
javascript
<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 包发布与更新的命令总结 ,按流程排序,每条命令都附带简短注释,涵盖了首次发布 和后续更新两种场景:
首次发布:
bash
# 1. 初始化 package.json 文件
npm init -y # 自动生成 package.json
# 2. 登录 npm 账号
npm login # 使用 npm 账号登录,输入用户名、密码、邮箱
# 3. 检查即将发布的内容
npm pack # 生成本地 tar 包,检查发布文件是否正确
# 4. 发布包
npm publish --access public # 首次发布作用域包需要 --access public
包的更新:
bash
# 1. 修改代码后,更新版本号
npm version patch # 小修复,例如 1.0.0 -> 1.0.1
# 也可用 npm version minor / major
# 2. 检查发布内容
npm pack # 打包检查,确保文件正确
# 3. 发布新版本
npm publish # 发布更新后的版本
验证结果:
bash
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
