NodeJS 8 ,从 0 到 1:npm 包发布与更新全流程指南( 含多场景适配与踩坑总结 )

目录

前言
一、准备工作
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 -vnpm -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:网页注册

    1. 访问:https://www.npmjs.com/signup,输入用户名(唯一,后续不可修改)、邮箱(需验证)、密码(建议包含大小写 + 数字 + 特殊符号)。
    2. 注册后,登录注册邮箱,点击 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:设置头像

    1. 本地上传:在 “Avatar” 区域点击 “Change Avatar”,选择本地图片(推荐尺寸 200x200px,格式 PNG/JPG,大小≤1MB),裁剪后保存。
    2. 关联 Gravatar:若页面显示 “Change your Gravatar”,点击后跳转至Gravatar 官网,使用与 npm 账号相同的邮箱登录,上传或修改头像后,npm 会自动同步(同步延迟约 5 分钟)。
    • 注意:Gravatar 是 “全球通用头像服务”,一次设置可同步至所有支持 Gravatar 的平台,无需在每个平台重复上传。
1.2.4 安全配置

账号安全配置(可选但推荐):为避免账号被盗,建议开启 “二次验证(2FA)”:

  1. 在 “Profile Settings” 页面下滑至 “Two-Factor Authentication”,点击 “Enable 2FA”。
  2. 按提示下载 Authenticator 应用(如 Google Authenticator),扫描二维码绑定账号,后续登录或发布包时需输入应用生成的动态验证码。

1.3 初始配置

项目初始化与 package.json 配置:项目初始化的核心是生成package.json文件 —— 它是 npm 包的 “身份说明书”,记录包名、版本、入口文件等关键信息,直接影响包的发布与使用。

1.3.1 初始项目目录
  1. 新建项目文件夹(如websocket-encaps,建议与包名一致),通过终端进入该目录:

    bash

    # Windows示例
    cd G:\1. My_file🔒\2 FrontEnd\Code\WebSocket
    # macOS/Linux示例
    cd ~/FrontEnd/Code/WebSocket
    
  2. 执行初始化命令,按提示填写信息:

    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包的入口文件(用户requireimport时加载的文件)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_modulestest目录、日志文件等无需发布的内容,减小包体积。
  • homepage:包的主页(如 GitHub 仓库的 README 地址),示例:
    "homepage": "https://github.com/NCSmile/websocket-encaps#readme"
    
    作用:在 npm 包页面显示 “Homepage” 链接,方便用户查看详细文档。


二、核心内容

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 代码编写注意事项
  1. 兼容性处理

    • 检查typeof WebSocket === 'undefined',兼容不支持 WebSocket 的浏览器(如 IE8 及以下)。
    • 消息解析时用try-catch包裹JSON.parse,避免非 JSON 格式消息导致代码崩溃。
  2. 资源释放

    • 关闭连接时清除重连定时器(clearInterval(reconnectTimer)),避免内存泄漏。
    • 初始化新连接前关闭旧连接(socket.close()),避免重复创建连接。
  3. 依赖说明
    代码依赖js-cookie,需在 README 中明确告知用户 “安装包时需额外安装js-cookie”(npm install websocket-encaps js-cookie),避免用户引入时报错 “Cannot find module 'js-cookie'”。

  4. 参数容错
    initDataonMessage等参数设置默认值(如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 环境要求

  1. Node.js:≥14.x(若用于 Node.js 环境)
  2. 浏览器:支持 ES6 + 与 WebSocket API(Chrome ≥43、Firefox ≥11、Edge ≥12)
  3. 框架: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 状态码说明

状态码含义场景说明
0CONNECTING连接正在建立,此时调用socketSend会提示 “连接未就绪”。
1OPEN连接已就绪,可正常发送 / 接收消息。
2CLOSING连接正在关闭,此时发送消息会失败。
3CLOSED连接已关闭,需重新调用connectSocket初始化连接(自动重连会自动处理)。

2.6 注意事项

  1. Token 配置:本包默认从 Cookie 读取 Admin-Token。若 Token 键名不同,可修改 websocket.js 中的 TokenKey 常量,或在 getUserToken 函数中自定义获取逻辑。
  2. Token 传递方式:WebSocket 不支持自定义请求头,若服务端需通过 Header 验证 Token,建议改用 URL 参数子协议 携带,并在 initSocket 函数中配置对应方式。
  3. 跨域处理:浏览器中 WebSocket 需服务器在握手阶段配置跨域策略(如 Access-Control-Allow-Origin)。推荐使用 wss:// 协议,以降低跨域限制风险。
  4. 大文件传输:传输大文件时应分片发送,避免单条消息过大导致断连。建议改用二进制格式(Blob/ArrayBuffer),并在 socketSend 中取消 JSON.stringify
  5. 多组件与环境适配:多组件共用时,建议将 connectSocketcloseSocket 封装至全局状态管理(如 Vuex/Pinia)。Node.js 环境需安装 ws 包,并通过 global.WebSocket = require('ws') 兼容。


三、文件更新

包文件的更新:当我们已经发布了一个 npm 包,并且在后续开发过程中需要修改其中的代码或修复 bug 时,就需要对包文件进行更新和重新发布。更新流程相对简单,但一定要严格按照步骤来操作,以确保版本管理清晰,并避免对使用你包的用户造成影响。

以下是标准的 npm 包更新流程:

更新步骤:

更新 npm 包主要分为三个步骤:更新版本号 → 打包检查 → 发布新版本
完整流程如下:

第一步:更新版本号

首先对已有的代码文件进行修改,例如在 myLib.js 中增加新的方法或修复错误。
修改完成后,务必进行本地测试,确保更新后的代码可以正常运行。

然后使用以下命令快速更新版本号:

npm version patch

版本号说明(语义化版本 SemVer):

  1. patch:修复 bug 或小改动,例如 1.0.0 → 1.0.1

  2. minor:新增功能且向下兼容,例如 1.0.0 → 1.1.0

  3. major:存在重大不兼容更新,例如 1.0.0 → 2.0.0

执行 npm version patch 后,npm 会自动完成以下操作:

  1. 更新 package.json 中的版本号。

  2. 创建一个对应版本的 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 包标记为 “公共包”,允许所有人访问和安装。

  1. 免费 npm 用户可以发布 公开的 scope 包(必须加 --access public),但不能发布私有 scope 包;
  2. 付费用户(如 npm Pro、Teams)可以发布私有 scope 包,也可以发布公开 scope 包(加 --access public);
  3. 无论是普通包还是公开的 scope 包,安装和使用方式完全一致,用户无需额外学习成本。

具体区别:

普通包package-name命名,需全局唯一,默认公开,适合通用工具;scope 包以**@owner/package-name命名,仅需在@owner**下唯一,默认私有(免费用户需加 --access public 发布为公开),更适合避免命名冲突、明确归属(个人/组织)或需要私有包的场景,两者使用方式一致。

第四步:验证更新结果

发布完成后,验证更新是否成功:

  1. 查看最新版本信息:

    npm view websocket-encaps

    //或者

    npm info

  2. 在其他项目中安装并测试:

    npm install websocket-encaps

  3. 验证代码是否运行正常

npm view 和 npm info 是完全等价的命令,含义和功能一模一样,都是用于查询 npm 仓库中某个包的详细信息(如版本、作者、依赖、发布时间、描述等)。

小结:更新 npm 包的核心流程可以概括为三步:

  1. 更新版本号npm version patch

  2. 打包检查npm pack

  3. 发布新版本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 包名      # 安装最新版本测试

流程总结:

  1. 首次发布:初始化 → 登录 → 打包检查 → 首次发布
  2. 文件更新:修改代码 → 更新版本号 → 打包检查 → 发布新版本 → 验证结果

整体排序(包括同步到GitHub仓库):

首次发布(按流程):

  1. npm config get registry
    查看当前 npm 镜像源,确保发布时使用官方源(https://registry.npmjs.org/

  2. npm config set registry https://registry.npmjs.org/
    若当前不是官方源,切换到官方源(避免发布失败)

  3. npm login
    登录 npm 账号(输入用户名、密码、邮箱验证码,确保账号已验证邮箱)

  4. npm init
    初始化项目生成package.json(首次发布前执行,配置包名、入口等信息)

  5. npm version 1.0.0
    首次发布时手动设置初始版本(或直接在package.json中配置)

  6. npm pack
    打包生成.tgz文件,预览即将发布的内容(检查核心文件是否包含,无冗余)

  7. npm publish
    首次发布包到 npm 官网(成功后终端显示+ 包名@版本号

  8. git add . && git commit -m "feat: 初始版本发布"
    提交代码到本地 Git 仓库(与 npm 包内容同步)

  9. git tag v1.0.0 && git push origin v1.0.0
    打版本标签并推送到 GitHub(便于版本回溯和多平台同步)

更新文件(按流程):

  1. npm version patch
    修复 Bug 时更新补丁版本(如 1.0.0 → 1.0.1,语义化版本:小改动)

  2. npm version minor
    新增功能时更新次版本(如 1.0.1 → 1.1.0,语义化版本:兼容改动)

  3. npm version major
    破坏性变更时更新主版本(如 1.1.0 → 2.0.0,语义化版本:不兼容改动)

  4. npm pack
    打包预览更新内容(确认修改已生效,无错误文件)

  5. npm publish
    发布更新后的版本到 npm(覆盖旧版本,用户可通过npm update获取)

  6. git push origin main && git push origin --tags
    推送更新后的代码和版本标签到 GitHub(保持 npm 与 GitHub 代码同步)

黄色背景部分,博主认为最为重要,具体情况,按照实际需求操作。


五、本文总结

本文总结了 npm 包从 0 到 1 的开发、发布、更新全流程,包括发布前切换 npm 官方源、开发更新时的语义化版本管理、与 GitHub 的多平台同步;同时涵盖了包名重复、版本冲突等高频问题的规避要点,帮助我们高效完成 npm 包的全生命周期维护。

通过本文,我们完整梳理了 npm 包发布与更新的全流程,从初次发布到后续维护,都给出了详细的步骤与注意事项:

  1. 初次发布

    • 使用 npm init 初始化项目。

    • npm login 登录 npm 账号。

    • npm pack 检查发布文件。

    • npm publish --access public 首次发布包。

  2. 后续更新

    • 修改代码后,通过 npm version patch 更新版本号,保持语义化版本管理。

    • 使用 npm pack 确认打包内容正确。

    • npm publish 发布新版本。

  3. 验证与维护

    • 通过 npm view 包名 查看版本信息。

    • 在项目中使用 npm install 包名 测试最新版本。

    • 持续优化并维护文档和更新日志,保证包的长期可用性。

npm 包发布三步走:更新版本号 → 打包检查 → 发布上线。严格执行流程,才能确保版本清晰、更新安全、用户体验良好。


六、更多操作

更多node、npm问题,请看

NodeJS(npm)https://blog.csdn.net/weixin_65793170/category_12590408.html

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

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

相关文章

BERT中文预训练模型介绍

bert-base-chinese 是由谷歌基于 BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;模型预训练得到的适用于中文任务的模型版本。以下从多个方面对其进行详细解释&#xff1a; 模型概述 BERT 是一种基于 Transformer 架构的预训练语言模型…

Archon01-项目部署

Archon01-项目部署当前已经参考B站视频针对代码进行修改&#xff0c;可直接使用BigModel智谱的GLM-4.5替换openAI进行使用&#xff0c;部署环境&#xff08;Python3.12-slim环境&#xff09;1-核心知识点关键字&#xff1a; Docker Supabase Archon BigModel Python1&#xff0…

HarmonyOS时间戳完全指南:DevEco Studio中的时间处理与实战应用

时间戳是现代应用开发中不可或缺的基础功能&#xff0c;无论是日志记录、数据同步、缓存管理还是状态追踪都离不开时间戳的支持。本文将深入探讨在DevEco Studio中如何处理和使用时间戳&#xff0c;并提供丰富的实战示例。一、时间戳基础概念什么是时间戳&#xff1f;时间戳&am…

论文笔记:On the Biology of a Large Language Model

《关于大型语言模型的生物学》&#xff08;On the Biology of a Large Language Model&#xff09;的文章&#xff0c;深入探究了 Anthropic 公司 Claude 3.5 Haiku 模型的内部工作机制。研究人员将理解语言模型比作生物学研究&#xff0c;旨在揭示其复杂行为背后的“神经回路”…

TCP/IP、HTTP 和 HTTPS简介

我们来系统地介绍一下 TCP/IP、HTTP 和 HTTPS。它们之间的关系可以概括为&#xff1a;​​HTTP 和 HTTPS 是运行在 TCP/IP 基础网络架构之上的具体应用协议​​。为了更直观地理解它们之间的关系&#xff0c;我们可以参考下面的网络分层模型&#xff1a;flowchart TDsubgraph A…

【30】C#实战篇——获取路径下的文件名(不包含路径和扩展名),文件名由连续的数字编号+连续的字母编号组成,并分离出文件名数字部分和英文部分

文章目录1 要求2 分析 与 实现1 要求 写一个函数&#xff0c;获取路径下的文件名&#xff08;不包含路径和扩展名&#xff09;&#xff0c;并分离出文件名fileName &#xff0c;文件名编号SN&#xff0c;文件名前缀WMT &#xff1b; 输入文件路径&#xff0c;解析出不带"…

EasyExcel部署Docker缺少字体报错

报文 java.lang.NullPointerException: nullat sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)at sun.awt.FontConfiguration.init(FontConfiguration.java:107)at sun.awt.…

从“收款工具”到“智能中枢”:AI如何重构POS系统的技术架构与商业价值?

引⾔:从交易终端到智能中枢的⼗字路⼝ 在现代商业的繁忙图景中 ,销售点( Point of Sale, POS) 系统⻓期以来被视为交易流程的终点 ——⼀个简单完成收款、打印票据的⼯具。然⽽ ,这⼀认知正在被迅速颠覆。 随着数字经济的深 化 ,POS系统已演变为连接顾客、 商品与服务的…

unity以战斗截图并加上微信二维码分享

开发游戏时&#xff0c;会遇到战斗结算&#xff0c;成就等奖励界面&#xff0c;鼓励玩家分享到朋友圈&#xff0c;这时通常会在图片上加上一些内容&#xff0c;比如游戏Logo&#xff0c;二维码下载等内容。现在分享一下我制作游戏分享图片的过程。第一步首先截图&#xff0c;截…

新手向:实现验证码程序

本文将从零开始&#xff0c;通过一个简单的验证码程序。即使你没有任何编程基础&#xff0c;也能跟着这篇文章一步步学习。第一章&#xff1a;Java开发环境搭建1.1 安装JDK要开始Java编程&#xff0c;首先需要安装Java开发工具包(JDK)。JDK是Java开发的核心环境&#xff0c;包含…

使用Flask实现接口回调地址

使用Flask实现接口回调地址 一、接口回调的基本概念 接口回调&#xff08;Callback&#xff09;是一种异步通信机制&#xff0c;当某个事件发生时&#xff08;如支付完成、任务结束&#xff09;&#xff0c;服务提供方会主动调用预先配置的URL&#xff08;即回调地址&#xff0…

vue2+jessibuca播放h265视频

文档地址&#xff1a;http://jessibuca.monibuca.com/api.html#background 1,文件放在public中 2,在html中引入 3&#xff0c;子组件 <template><div :id"container id"></div> </template><script> export default {props: [url,…

Behavioral Fingerprinting of Large Language Models

Behavioral Fingerprinting of Large Language Models Authors: Zehua Pei, Hui-Ling Zhen, Ying Zhang, Zhiyuan Yang, Xing Li, Xianzhi Yu, Mingxuan Yuan, Bei Yu Deep-Dive Summary: 行为指纹识别大型语言模型 摘要 当前的大型语言模型&#xff08;LLMs&#xff09;基…

某互联网大厂的面试go语言从基础到实战的经验和总结

### 一面 #### 1. **实习项目**- 可以简要描述你的项目经历&#xff0c;最好是与职位相关的项目。如果是与技术栈相关的项目&#xff0c;比如 Go、C、Golang 或 Python&#xff0c;重点讲述项目中的技术细节和你如何解决问题。#### 2. **Go学习多久**- 说明你学习 Go 语言的时间…

掌握Java控制流:编程决策的艺术

控制流语句是用来 控制程序执行顺序 的关键工具&#xff0c;它们允许你根据不同的条件执行不同的代码块&#xff0c;或者重复执行某段代码。这使得程序能够根据输入和情况做出智能的决策&#xff0c;而不仅仅是线性的执行。1. 条件语句 (Conditional Statements)条件语句允许你…

Docker 安装 MySQL 和 Redis 完整指南

前言 在开发环境中,使用 Docker 安装数据库服务是一种快速、便捷的方式。本文将详细介绍如何在 macOS 上使用 Docker 安装 MySQL 和 Redis,并解决国内网络访问 Docker Hub 的问题。 环境准备 macOS 系统 Docker Desktop 已安装 网络连接 配置 Docker 国内镜像源 方法一:通…

Spring Boot---自动配置原理和自定义Starter

1.自动配置原理2.自定义starter①dmybatis-spring-boot-autoconfigure步骤一&#xff1a;先创建项目步骤二&#xff1a;导入响应的依赖步骤三&#xff1a;创建自动配置的配置类步骤四&#xff1a;创建配置文件项目结构②dmybatis-spring-boot-starter步骤一&#xff1a;先创建项…

【后端】MySQL 常用 SQL 语句大全

整理一份 MySQL 常用 SQL 语句大全&#xff0c;从基础操作到进阶查询&#xff0c;都涵盖。方便日常开发和学习参考。1. 数据库操作-- 查看所有数据库 SHOW DATABASES;-- 创建数据库 CREATE DATABASE db_name;-- 删除数据库 DROP DATABASE db_name;-- 使用数据库 USE db_name;--…

[iOS] 单例模式的深究

文章目录前言一、什么是单例模式二、单例模式的优缺点优点缺点三、模式介绍1.懒汉模式&#xff08;GCD & 互斥锁&#xff09;GCD 写法互斥锁写法&#xff08;双重检查锁&#xff09;2.饿汉模式总结懒汉式 互斥锁&#xff08;Mutex&#xff09;**懒汉式 GCD (dispatch_onc…

解决Discord.py中的/help命令问题

在使用Discord.py开发机器人时,常常会遇到一些常见的问题,比如命令找不到或者命令功能不符合预期。本文将详细探讨如何解决在使用@bot.slash_command定义/help命令时遇到的问题,并提供一个完整的实例来展示如何正确设置这个命令。 问题描述 当你在Discord机器人中输入/hel…