分享我的副业项目:一个接近纯前端实现的在线工具站

69 阅读4分钟

作为一个想做独立开发的程序员,我花了半个多个月时间打造了一个在线工具箱。50+ 工具,近乎纯前端实现,懒加载按需加载,一站解决各种需求。

先看效果

image.png

image.png

image.png

image.png

image.png

为什么做这个

平时工作中经常需要用到各种小工具:压缩图片、合并PDF、生成二维码、格式化JSON……

每次都要打开不同的网站,有的还要注册登录,有的满屏广告。

干脆自己做一个,把常用工具都集成进来,顺便练练手。

技术架构

核心技术栈

  • React 18 + TypeScript - 类型安全,开发体验好
  • Vite 7 - 快,真的快
  • Zustand - 轻量状态管理,比 Redux 简单太多
  • antd-mobile - 移动端 UI 组件

插件化架构

整个项目采用插件化设计,每个工具都是独立的插件模块:

// 插件注册表 - 统一管理所有工具
const registry: Record<string, PluginLoader> = {
  // 图片工具
  'image-compress': () => import('./ImageCompress'),
  'image-crop': () => import('./ImageCrop'),
  // PDF 工具
  'pdf-merge': () => import('./PdfMerge'),
  'pdf-split': () => import('./PdfSplit'),
  // AI 工具
  'ai-creative-studio': () => import('./AiCreativeStudio'),
  // ... 50+ 插件
};

// 懒加载获取插件组件
export function getPluginComponent(id: string) {
  const loader = registry[id];
  if (!loader) return null;
  return lazy(loader);
}

好处:

  • 按需加载,首屏只加载用到的工具
  • 新增工具只需要加一行注册代码
  • 每个工具独立开发、独立测试

插件商店

后端维护插件元数据(名称、图标、分类、描述),前端通过 API 获取:

interface PluginMeta {
  id: string;
  name: string;
  description: string;
  icon: string;
  categoryId: string;  // 所属分类
  tags: string[];
  downloadCount: number;
  avgRating: number;
  // ...
}

目前有十几个分类:图片工具、PDF工具、AI工具、开发工具、效率工具、娱乐工具……

用户可以在商店里浏览、搜索、安装工具到自己的桌面。

亮点功能介绍

1. AI 创意工坊

这是我花时间最多的一个工具,基于 Gemini API 实现的 AI 绘图:

绘图 | 小红书 | 提示词库

功能:

  • 多轮对话绘图,可以不断修改调整
  • 支持上传参考图
  • 内置表情包制作模式(一键生成 4x6 表情包)
  • 图片切片工具,方便导出
  • 小红书封面生成
  • 提示词库,收集好用的 prompt

技术实现:

  • 流式输出,边生成边显示
  • IndexedDB 存储会话历史
  • 支持多个 API 渠道切换

2. 桌宠系统

基于 oh-my-live2d 实现的桌面宠物,可以自定义:

// 模型分类
export const MODEL_CATEGORIES: ModelCategory[] = [
  { id: 'azurlane', name: '碧蓝航线', models: [...] },
  { id: 'genshin', name: '原神', models: [...] },
  // ...
];
  • 多个模型分类可选
  • 支持自定义模型 URL
  • 可调整大小、位置
  • 拖拽到桌面任意位置

3. 纯前端 PDF 处理

不需要上传到服务器,所有处理都在浏览器完成:

  • pdf-lib - PDF 合并、拆分、加水印、页面重排
  • pdfjs-dist - PDF 预览、提取图片
// PDF 合并示例
import { PDFDocument } from 'pdf-lib';

async function mergePDFs(files: File[]) {
  const mergedPdf = await PDFDocument.create();
  
  for (const file of files) {
    const bytes = await file.arrayBuffer();
    const pdf = await PDFDocument.load(bytes);
    const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
    pages.forEach(page => mergedPdf.addPage(page));
  }
  
  return await mergedPdf.save();
}

4. 虚拟钢琴

用 Tone.js 实现的在线钢琴,支持 MIDI 文件播放:

  • 键盘/鼠标演奏
  • 导入 MIDI 文件自动演奏
  • 内置几十首经典曲目

移动端适配

工具站同时支持 PC 和移动端,主要通过:

  1. 响应式布局 - CSS Media Query + useResponsive Hook
  2. antd-mobile - 移动端优先的组件库
  3. 触摸优化 - 手势操作、触摸反馈
// 响应式 Hook
export function useResponsive() {
  const [isPC, setIsPC] = useState(window.innerWidth >= 768);
  
  useEffect(() => {
    const handler = () => setIsPC(window.innerWidth >= 768);
    window.addEventListener('resize', handler);
    return () => window.removeEventListener('resize', handler);
  }, []);
  
  return { isPC, isMobile: !isPC };
}

遇到的坑

1. 大文件内存问题

处理大 PDF 或大图片时,容易内存溢出。解决方案:

  • 分片处理
  • 及时释放 ArrayBuffer
  • 使用 Web Worker 处理耗时任务

2. Live2D 定位冲突

oh-my-live2d 默认使用 fixed 定位,和我的自由桌面布局冲突。花了不少时间用 CSS 覆盖:

.live2dContainer :global(.oml2d-wrapper) {
  position: relative !important;
  left: 0 !important;
}

3. 移动端键盘遮挡

输入框被软键盘遮挡,用 visualViewport API 解决。

未来规划

  1. 持续收集和开发各种前端能实现的工具 - 目标是一站解决各种需求
  2. 优化性能 - 更细粒度的代码分割
  3. 更多 AI 能力 - 接入更多模型

最后

在线体验: 玩机996

有什么想要的工具也可以评论区告诉我,说不定下个版本就加上了 😄


一个想做独立开发的程序员,欢迎关注交流。