库与npm

  1. 什么是库
  • 库是一组可重用的代码集合
  • 提供特定功能的API或组件
  • 可以被项目引入和使用
  • 通常解决特定领域的问题
  1. 库与pnpm的关系 :
  • pnpm是包管理器,用于:
    • 安装和管理这些库的依赖
    • 维护依赖版本
    • 处理依赖之间的关系
    • 优化存储空间(通过硬链接)
  1. pnpm的工作方式 :
  • 当执行 pnpm install 时:
    • 读取 package.json 中的依赖配置
    • 从 npm 仓库下载所需的库如
    • 使用硬链接优化存储
    • 生成 pnpm-lock.yaml 锁定版本
  1. 依赖类型 :
  • dependencies:项目运行必需的库
  • devDependencies:开发时需要的库

发布npm包

准备工作

  • 安装最新版的node.js和npm ,验证
  • 注册npm账号
  • 使用官方npm源npm config set registry https://registry.npmjs.org/
    准备工作

初始化文件夹

创建项目文件夹

运行npm init -y 生成package.jaon文件

npm init与npm init -y

  • npm init是一个交互式命令
    执行后会逐项询问用户关于项目的配置信息,如项目名称、版本号、描述、入口文件、测试命令等
    用户可以手动输入或修改这些字段的值。
    最后根据用户的输入生成 package.json 文件
  • npm init -y是非交互式的快捷方式
    直接使用默认值生成 package.json 文件,无需用户确认或输入
    如果你希望快速初始化项目并接受默认配置,使用 npm init -y
    如果你想自定义项目的初始配置,使用 npm init 并逐步输入所需信息
    准备工作

package.json 文件关键字段说明

  1. 字段说明
  • name:包名,npm 发布时的唯一标识
    全局唯一,不能和已有npm包重名,用小写字母、数字、短横线(-)
  • version:包的版本号,遵循语义化版本规范(如1.0.0)
    格式:主版本号.次版本号.修订号(如 1.0.0
  • main:入口文件路径(默认为index.js)
    指定包的入口文件(即 require/import 这个包时加载的文件)
    当别人 require(‘my-canvas-tool’) 时,实际加载的是 src/index.js
  • description:包的描述,对包的简要描述,npm 官网、搜索时会显示
  • keywords:关键字数组,帮助别人通过关键词搜索到你的包。
  • license:开源协议,包的许可证类型,决定别人如何使用你的代码
    “MIT”(MIT 是一种宽松的开源协议,允许自由使用、修改和分发)
  • author:包的作者信息。可以写名字、邮箱等
  • dependencies:生产依赖,包运行时需要的依赖
    开发依赖,只在开发和测试时需要,发布包时不会被包含进最终包中
    其他字段(我没写)
    repository:代码仓库地址(如 GitHub)。
    bugs:问题反馈地址。
    homepage:项目主页。
    files:发布到 npm 时包含的文件列表。
    engines:指定支持的 Node 版本等
  1. 我的packaje.json文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    {
    "name": "my-canvas-tool",
    "version": "1.0.0",
    "description": "一个简单的 Canvas 工具库,支持初始化和清空画布。",
    "main": "src/index.js",
    "scripts": {
    "test": "jest"
    },
    "keywords": [
    "canvas",
    "tool",
    "draw"
    ],
    "author": "melon-nie",
    "license": "MIT",
    "devDependencies": {
    "mocha": "^10.0.0",
    "jsdom": "^22.0.0",
    "jest": "^30.0.4"
    }

    }

编写代码和测试文件

  1. 代码结构
    1
    2
    3
    4
    5
    6
    7
    8
    my-canvas-tool/
    ├── src/
    │ └── index.js (核心代码)
    ├── test/
    │ └── test.js (测试文件)
    ├── .npmignore (排除发布的文件)
    ├── README.md (使用说明)
    └── package.json
  2. 代码示例(canvas 工具画圆)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class CanvasTool {
    constructor(canvas) {
    if (!(canvas instanceof HTMLCanvasElement)) {
    throw new Error('参数必须为 HTMLCanvasElement');
    }
    this.canvas = canvas;
    this.ctx = canvas.getContext('2d');
    }

    clear() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
    }

    module.exports = CanvasTool;
  3. 测试文件(使用 Jest,AI生成)
    安装jestnpm install --save-dev jest
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    // test/test.js
    const assert = require('assert');
    const { JSDOM } = require('jsdom');
    const CanvasTool = require('../src/index');

    // 注入 HTMLCanvasElement 到全局,兼容 Node.js 测试环境
    const { window } = new JSDOM('<!DOCTYPE html><html><body></body></html>');
    global.HTMLCanvasElement = window.HTMLCanvasElement;
    global.document = window.document;

    describe('CanvasTool', () => {
    let canvas, ctxMock, tool;

    beforeEach(() => {
    // 创建 mock canvas,原型指向 HTMLCanvasElement 以通过 instanceof 检查
    canvas = Object.create(global.HTMLCanvasElement.prototype);
    canvas.width = 100;
    canvas.height = 100;
    canvas.getContext = jest.fn();
    // 创建 mock 2d context
    ctxMock = {
    fillStyle: '',
    fillRect: jest.fn(),
    getImageData: jest.fn(() => ({ data: new Array(400).fill(0) })),
    clearRect: jest.fn()
    };
    canvas.getContext.mockReturnValue(ctxMock);
    tool = new CanvasTool(canvas);
    });

    test('should initialize with a canvas element', () => {
    expect(tool.canvas).toBe(canvas);
    expect(tool.ctx).toBe(ctxMock);
    });

    test('should clear the canvas', () => {
    tool.ctx.fillStyle = 'red';
    tool.ctx.fillRect(0, 0, 10, 10);
    tool.clear();
    expect(tool.ctx.clearRect).toHaveBeenCalledWith(0, 0, 100, 100);
    });
    });

    // mock HTMLCanvasElement 以通过构造函数类型检查
    global.HTMLCanvasElement = function() {};
    global.HTMLCanvasElement.prototype = Object.create(Object.prototype);
    global.HTMLCanvasElement.prototype.constructor = global.HTMLCanvasElement;
  4. 配置测试脚本
    1
    2
    3
    "scripts": {
    "test": "jest"
    }

发布前准备

用jest进行测试

Jest 是一个流行的 JavaScript 测试框架,特点是:
零配置即可上手
支持断言、mock、快照等功能
适合测试 Node.js、前端、React 等项目
测试:npm test
准备工作

编写README.md

包含以下内容:安装方法;使用示例;API 文档;贡献指南;开源协议

配置.npmignore

排除不需要发布的文件:

1
2
3
4
node_modules/
test/
.git/
.DS_Store

发布npm包

npm login
npm publish

若包名已存在,需修改package.json中的name字段
每次发布新版本时,修改package.json中的version字段(遵循语义化版本控制),并重新运行npm publish
24 小时内可撤销发布npm unpublish <包名>@<版本号> --force

发布npm包
发布npm包

如何使用
在想使用它的项目根目录下运行(包名是 my-canvas-tool):
npm install my-canvas-tool