从0到1开发水印组件npm包 -项目规划

23 阅读6分钟

第01章:项目规划

在开始编码之前,我们需要做好充分的规划。这一章将带你完成需求分析和技术选型。

📋 本章目标

  • ✅ 明确项目需求
  • ✅ 分析技术方案
  • ✅ 确定技术选型
  • ✅ 设计API接口

预计时间:15分钟


1. 需求分析

1.1 什么是水印?

水印(Watermark)是覆盖在内容上的半透明标记,用于:

  • 🔒 版权保护 - 标识内容所有者
  • 🛡️ 防止泄密 - 追踪信息来源
  • 📋 信息展示 - 显示用户信息、时间等

1.2 应用场景

┌─────────────────────────┐
│  📄 文档预览系统        │
│  - PDF查看器            │
│  - Word在线预览         │
│  - 合同管理系统         │
└─────────────────────────┘

┌─────────────────────────┐
│  🖼️ 图片/视频平台       │
│  - 图片网站             │
│  - 视频网站             │
│  - 设计作品展示         │
└─────────────────────────┘

┌─────────────────────────┐
│  🏢 企业管理系统        │
│  - OA系统               │
│  - ERP系统              │
│  - 数据大屏             │
└─────────────────────────┘

1.3 核心需求

需求优先级说明
显示水印P0必须能在页面显示水印
自定义内容P0可以自定义水印文字
自定义样式P1字体、颜色、大小等
防删除P1防止用户删除水印
性能优秀P1不影响页面性能
TypeScriptP1提供类型支持
易用性P2API简单易用
多框架支持P2支持React/Vue/原生JS

2. 技术方案对比

2.1 方案一:DOM实现

实现方式:

// 创建多个span元素拼成水印
for (let i = 0; i < 100; i++) {
  const span = document.createElement('span');
  span.textContent = '水印';
  span.style.position = 'absolute';
  container.appendChild(span);
}

优点:

  • ✅ 实现简单
  • ✅ 容易理解
  • ✅ 兼容性好

缺点:

  • ❌ 创建大量DOM节点(100+)
  • ❌ 性能开销大
  • ❌ 内存占用高
  • ❌ 首屏渲染慢

2.2 方案二:Canvas实现 ⭐推荐

实现方式:

// 用Canvas绘制一个水印单元
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.fillText('水印', x, y);

// 转换为图片,通过CSS背景重复
const base64 = canvas.toDataURL();
div.style.backgroundImage = `url(${base64})`;
div.style.backgroundRepeat = 'repeat';

优点:

  • ✅ 只创建1个DOM节点
  • ✅ 性能优秀
  • ✅ 内存占用低
  • ✅ 支持复杂图形

缺点:

  • ❌ 稍微复杂一点
  • ❌ 需要学习Canvas API

2.3 方案三:SVG实现

实现方式:

// 使用SVG绘制水印
const svg = `
  <svg>
    <text>水印</text>
  </svg>
`;
div.style.backgroundImage = `url(data:image/svg+xml,${svg})`;

优点:

  • ✅ 矢量图形,清晰
  • ✅ 文件小

缺点:

  • ❌ 复杂图形性能不如Canvas
  • ❌ 兼容性问题

2.4 最终选择

我们选择:Canvas方案

理由:

  1. 性能最优
  2. 功能最强
  3. 兼容性好
  4. 行业主流

3. 技术选型

3.1 核心技术栈

技术用途为什么选择
Canvas API绘制水印性能最好
MutationObserver防删除原生API,性能好
TypeScript类型系统提供类型提示
tsup打包工具零配置,速度快
pnpm/npm包管理器标准工具

3.2 为什么用TypeScript?

// ❌ JavaScript - 没有类型提示
const watermark = new Watermark({
  content: '水印',
  fontsize: 16  // 拼写错误!运行时才发现
});

// ✅ TypeScript - 编写时就发现错误
const watermark = new Watermark({
  content: '水印',
  fontsize: 16  // ❌ 编辑器直接提示错误
  fontSize: 16  // ✅ 正确
});

3.3 为什么用tsup?

传统方式(Webpack/Rollup):

// webpack.config.js - 100行配置
module.exports = {
  entry: './src/index.ts',
  output: { /* ... */ },
  module: { rules: [/* ... */] },
  plugins: [/* ... */],
  // 还有很多配置...
};

tsup方式:

{
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts"
  }
}

一行搞定!✨


4. API设计

4.1 设计原则

  1. 简单易用 - 最少配置即可使用
  2. 灵活强大 - 支持高度自定义
  3. 类型安全 - TypeScript全面支持
  4. 符合直觉 - API命名清晰

4.2 API设计

基础使用
// 1. 创建实例
const watermark = new Watermark({
  content: '机密文档'
});

// 2. 显示水印
watermark.create();

// 3. 更新水印
watermark.update({ content: '新内容' });

// 4. 移除水印
watermark.remove();

// 5. 销毁实例
watermark.destroy();
配置选项
interface WatermarkOptions {
  // 必填
  content: string;              // 水印内容
  
  // 可选 - 样式
  fontSize?: number;            // 字体大小,默认14
  color?: string;               // 颜色,默认rgba(0,0,0,0.15)
  fontFamily?: string;          // 字体,默认Arial
  rotate?: number;              // 旋转角度,默认-20
  opacity?: number;             // 透明度,默认1
  
  // 可选 - 布局
  width?: number;               // 宽度,默认200
  height?: number;              // 高度,默认150
  gap?: { x: number; y: number }; // 间距
  
  // 可选 - 高级
  zIndex?: number;              // 层级,默认999999
  container?: HTMLElement;      // 容器,默认body
  observe?: boolean;            // 防删除,默认true
}

4.3 使用示例

// 最简单的使用
new Watermark({ content: '水印' }).create();

// 自定义样式
new Watermark({
  content: '机密文档',
  fontSize: 20,
  color: 'rgba(255, 0, 0, 0.2)',
  rotate: -30
}).create();

// 多行文本
new Watermark({
  content: '机密文档\n请勿外传\n2025-10-21'
}).create();

// 局部水印
const container = document.getElementById('app');
new Watermark({
  content: '局部水印',
  container: container
}).create();

5. 项目结构

5.1 目录规划

watermark-package/
├── src/                    # 源代码
│   ├── index.ts           # 入口文件
│   ├── types.ts           # 类型定义
│   └── watermark.ts       # 核心逻辑
├── examples/              # 使用示例
│   ├── basic.html         # HTML示例
│   └── react-demo.tsx     # React示例
├── dist/                  # 构建产物(自动生成)
│   ├── index.js           # CommonJS
│   ├── index.mjs          # ES Module
│   └── index.d.ts         # 类型定义
├── package.json           # npm配置
├── tsconfig.json          # TS配置
├── README.md              # 文档
└── LICENSE                # 开源协议

5.2 为什么这样组织?

src/              → 源代码,开发时编辑
├── index.ts     → 统一导出,清晰的API
├── types.ts     → 类型定义,便于维护和导出
└── watermark.ts → 核心逻辑,单一职责

examples/         → 使用示例,方便测试和展示
dist/             → 构建产物,发布到npm

6. 开发计划

6.1 开发步骤

1步:环境准备 (15分钟)
  → 安装Node.js、npm
  → 创建项目目录
  → 初始化package.json2步:学习基础 (2-3小时)
  → Canvas API
  → TypeScript基础
  → MutationObserver

第3步:核心开发 (4-6小时)
  → 实现Canvas绘制
  → 实现DOM操作
  → 实现防删除
  → 完善功能

第4步:工程化 (2-3小时)
  → 配置TypeScript
  → 配置打包工具
  → 编写文档

第5步:测试优化 (2-3小时)
  → 本地测试
  → 性能优化
  → 编写示例

第6步:发布 (1-2小时)
  → npm发布
  → 版本管理

6.2 时间规划

阶段时间累计
准备阶段30分钟0.5小时
学习阶段2-3小时3.5小时
开发阶段4-6小时9.5小时
工程化2-3小时12.5小时
测试优化2-3小时15.5小时
发布维护1-2小时17.5小时

总计:17-18小时(分3-5天完成)


7. 成功标准

7.1 功能完成度

  • 能够显示水印
  • 支持自定义样式
  • 支持防删除
  • 支持动态更新
  • 支持TypeScript
  • 性能优秀

7.2 质量标准

  • 代码规范
  • 类型完整
  • 文档齐全
  • 示例丰富
  • 测试通过

7.3 发布标准

  • 可以成功构建
  • 可以本地测试
  • 可以发布到npm
  • 可以被其他项目使用

8. 本章总结

你学到了什么?

✅ 水印的应用场景和需求
✅ DOM vs Canvas vs SVG三种方案对比
✅ 为什么选择Canvas + TypeScript
✅ 如何设计简洁易用的API
✅ 项目目录结构规划
✅ 完整的开发计划

下一步

现在你已经完成了项目规划,接下来我们要准备开发环境。


📝 本章检查清单

完成以下检查:

  • 理解了水印的应用场景
  • 知道为什么选择Canvas方案
  • 了解了API的设计思路
  • 清楚项目的目录结构
  • 明确了开发步骤和时间

全部完成?继续下一章02-环境准备


💡 思考题

  1. 除了Canvas,你能想到其他实现水印的方法吗?
  2. 如果要实现图片水印,应该怎么做?
  3. 水印能100%防止被删除吗?为什么?

带着这些问题,继续学习!🚀