我做了差不多八个月的 ArtCraft 最近终于上线了。它不是一个多复杂的产品——就是一套给插画师、摄影师、木工作家、皮具手艺人用的作品集站点工具。作者们可以像维护个人主页一样展示作品把尺寸、材质、制作过程、定制询单这些信息统一管理起来全程不用碰代码也不用懂数据库。这个项目最初的缘起就是因为我身边太多创作者面对要不要做个官网这个问题时陷入两难用现成建站工具功能倒是全但模板味太重改起来处处受限找外包做则又贵又难维护。ArtCraft 想解决的恰恰是这个问题。这篇文章我打算把项目的决策过程、技术选型的取舍、视觉和交互怎么打磨、性能上一度被大图折磨的优化方案以及上线后踩过的运维坑一次性写清楚。如果你也在做一个以内容展示为核心的小型 Web 产品或者只是单纯想给自己的作品搭个线上空间这里面应该有不少可以直接拿走用的东西。1. 从想给作品找个家说起ArtCraft 到底解决了什么问题1.1 散落在社交平台上的作品缺的不是流量而是档案我观察到一个挺有意思的现象现在大多数创作者并不是没有曝光渠道恰恰相反他们的作品散落在好几个社交平台上每发一次动态都能拿到一些流量。但问题在于这些平台本质上都是信息流产品算法一旦觉得某条内容不火了它就会被淹没在时间线里连带着作品背后的完整脉络一起消失。有一位做木作的作者曾经跟我抱怨过一件事他想向客户说明一把椅子的演进过程——从草图、开料、榫卯、打磨到上蜡一共十几张过程图。在社交平台上一口气发完读者刷过去只会留一句真好看。可如果有人真想下单定制他想看的恰恰是这些过程他需要确认这个人的作品是靠什么方法做出来的工艺到底到不到位。这类内容散落在各条帖子里既难检索也没法系统呈现。这就是 ArtCraft 最初的核心洞察创作者需要的不是又一个信息流账号而是一个以作品为主角的、可以长期维护的作品档案。这个档案要能完整展示单件作品记录它背后的工艺、材质、尺寸和故事同时还能承载定制询单这类真实业务需求。1.2 市面上的建站与作品集方案为什么都不够顺手在动手写代码之前我把市面上常见的几类方案都过了一遍也帮几位朋友实际搭过。分类下来大概是这么几种方案类型典型特点核心痛点通用建站平台拖拽编辑、模板丰富模板千篇一律自定义样式受限订阅费用持续上涨博客系统文字内容为主生态成熟对图片类作品展示不够友好发布流程偏重作品集专用平台以设计师/摄影师为目标展示效果好偏平面设计圈对木作、陶艺这类手工品类支持不足询单功能缺失静态站点生成器灵活、速度快、可完全掌控非技术用户维护不直观每次发布都要重新构建无头内容管理系统内容与展示完全解耦灵活性强学习成本高前后端分离后小团队维护负担重我用这五种方案分别模拟过同一类用户的上手流程。比如一位做皮具的朋友她的核心诉求是每周要更新两三件新作品、每件作品要放五六张图、要标注皮料和尺寸、要能收到定制询问。我试着用建站平台搭光是改一个作品详情页的版式就花了一个多小时用静态站点生成器则更难因为发布新作品意味着要处理 Git、构建、部署一套链路对她的场景完全不现实。这些体验让我坚定了自己做的思路。市面上的方案不是不好而是它们都在追求功能覆盖却忽略了一个更本质的需求对一个内容创作者来说作品库应该像一本可以随时翻阅的相册而不是一台需要持续维护的服务器。1.3 ArtCraft 的产品定位与首批需求清单综合调研之后我给 ArtCraft 立了三条产品原则作品优先、极简交互、作者可维护。所谓作品优先是指页面上一张图就是一整个世界文案、菜单、装饰元素都要为图让路极简交互是指用户进来之后浏览是唯一的核心动作不需要注册、不需要登录、不需要被引导去点赞收藏作者可维护则是指所有更新动作都应该在浏览器里完成上传图片、填信息、调排序十分钟内搞定。第一批需求清单是这样整理的作品首页墙以网格形式展示全部作品支持按分类过滤作品详情页展示多图、作品属性、创作过程和定制按钮关于作者页一段介绍加联系方式信息密度低询单系统访客可以针对某一件作品发起定制咨询作者在后台收到提醒管理后台支持作品新增、编辑、上下架、排序、分类和标签维护基础 SEO每个作品有独立标题和描述能被搜索引擎收录这份清单刻意砍掉了很多常见功能比如用户系统、评论、点赞、数据统计。原因是第一版只想验证一件事一个安静的作品展示空间到底能不能满足创作者的真实需求。事实证明这个判断基本是对的。后面陆续有作者反馈想要收藏功能但都被我放到二期再议——先把最核心的浏览和询单体验打磨透比堆功能重要得多。2. 技术选型的取舍逻辑为什么是这套组合拳2.1 最终技术栈一览ArtCraft 的技术栈并不新潮但每一层的选择都有明确理由。最终跑在线上的是这么一套组合层次选型选择理由前端框架React 18 Vite 5组件化思维清晰生态成熟Vite 开发体验好样式方案TailwindCSS 3原子化类名配合设计令牌能精确控制版式细节后端服务Node.js Express轻量、易维护与前端同为 JS 语言栈数据库SQLite首发零运维、单文件备份初期够用且无额外成本部署环境Docker Nginx构建产物可复现反向代理统一处理静态资源与转发这个组合乍一看保守但对我这类小团队偏个人项目的情况来说稳定和可控永远是第一位的。我不需要一个庞大的微服务架构来支撑每周几百次访问我需要的是任何凌晨三点出现的 bug 都能被快速定位和修复的能力。2.2 为什么没选静态站点生成器方案做内容型网站很多人第一反应是静态站点生成器理由无非是速度快、SEO 好。我确实认真考虑过这条路也做了一个小型 Demo 做对比。结论是如果站点作者是开发者本人静态生成器几乎是完美答案如果作者是普通创作者它就是一场灾难。问题出在发布链路。静态站点把内容、模板、构建、部署串成一条链作者要发一篇新作品得在本地或者在线编辑器中写内容触发重新构建再把产物传到服务器。过程中任何一步出错比如图片路径写错、Markdown 格式不对都会导致发布失败。我还遇到过更微妙的情况——更新一张作品封面图后构建顺利通过但因为文件名没变CDN 缓存里还是旧图作者在后台兴冲冲确认发布前台却纹丝不动体验非常割裂。相比之下ArtCraft 采用动态渲染加缓存层的做法作者在后台提交作品数据库写入后前台即可见。对访问端来说有 CDN 和合理的缓存策略兜底响应速度并没有比纯静态方案差多少。更重要的是后台与前台共用一套数据模型作者所见即所得技术上的复杂度反而更低了。2.3 数据层从 SQLite 起步的底气与出路数据层是我当时纠结最多的部分。几位同伴都劝我直接上托管型 PostgreSQL理由是迟早要面对并发和扩展性问题。我的判断则是以 ArtCraft 首发的访问量级SQLite 完全撑得住而且能让部署和运维工作减少一大半。SQLite 的优势在这里尤其明显不需要单独维护数据库服务数据就是磁盘上的一个文件备份等于复制文件。开启 WAL 模式后读写在大多数场景下也不会互相阻塞。实际压测时单实例 SQLite 在几百个并发读请求下依旧稳定这对一个作品展示类站点来说已经绰绰有余。我当然知道 SQLite 有天花板——写并发高、多实例部署时需要额外方案。所以在一开始我就做了两层隔离所有数据库操作都收敛在一个数据访问模块里视图层绝不直接碰 SQL同时后端接口全部设计成无状态的哪天数据量上来了直接切换连接层到 PostgreSQL改动面能限制在很小的范围内。这种先轻装上阵再平滑升级的策略是我做小项目一贯的套路——不为还没发生的瓶颈提前买单但为它留好退路。3. 让作品成为主角视觉与交互的打磨过程3.1 版式三原则留白、克制、以作品定调做 ArtCraft 的视觉设计时我给自己定的第一条规矩是先想想什么不该做。作品集页面最怕的是设计感过剩——各种玻璃拟态、渐变边框、滚动动画全都堆上去结果用户第一眼看到的不是作品而是网页本身。这种喧宾夺主的页面就算单个元素再精致整体也是失败的。ArtCraft 最后落到三个原则第一大面积留白尤其是作品顶部和两侧给每个作品足够呼吸空间第二动效极度克制hover 只有轻微的同比例缩放和标题浮现整个页面没有一处为了炫技而存在的动画第三色彩以中性色为底暖灰背景、深灰文字、纯白卡片作品本身的颜色就是页面最大的色彩来源。这几个原则听起来简单但在实际执行中很容易走偏。比如最初版我用了深色背景配高饱和强调色视觉冲击力很强但把不同色系的作品放上去一测很多插画和陶艺作品直接被背景吞掉了。后来我把背景改成接近纸张的浅暖灰色作品反而从页面上自己跳了出来。这是很朴素的美术常识但做产品时往往容易被忽略。3.2 网格系统与图片裁切策略作品墙的核心难点在于不同作者上传的图片比例差异极大有竖构图插画、横构图照片、甚至方形木作图。如果沿用等分网格就得强行裁切很多作品会被切掉关键构图如果完全自适应高度又会导致页面参差不齐滚动时视觉节奏混乱。我采用的方案是两步走第一步用 CSS Grid 实现类似瀑布流的版式每列宽度相同但行高自适应这样每张图都能保持原始比例第二步在缩略图生成阶段统一做智能裁切确保在列表页即使经过裁切核心主体也不会丢失。这张表是我实际用下来的规格图片类型目标宽度格式质量设置使用场景列表缩略图600pxWebP82作品墙与分类页详情预览图1200pxWebP86作品详情页首屏原始大图原尺寸原格式不压缩点击放大后查看细节这套网格在移动端的表现也符合预期手机屏幕宽度较小时Grid 自动切换为单列竖构图作品完整展示横构图作品则限制最大高度并支持点击展开全图。相比传统的一刀切裁成正方形方案这种处理对作者更友好——他们上传的图片能被最大程度地尊重。3.3 详情页的沉浸式浏览体验作品详情页是 ArtCraft 信息密度最高的页面同时也是最容易做砸的地方。常规做法是把表格信息列成一排——名称、作者、材料、尺寸、年份再配一张大图和一段说明文字。我最初是这样实现的后来拿给一位陶艺作者试用她一句话点醒了我我关心的是你这件东西是怎么从泥巴变成成品的你光给我一张正面照有什么用于是我把详情页的交互重心从展示成品转向展示过程。顶部是大幅成品图往下依次排列过程图照片之间用轻量文字串联工序。用户还可以用键盘左右键在过程图之间切换手机上则通过横向滑动浏览。这样一个能力不复杂的交互带来的阅读深度远超预期——询单转化率明显高于单纯放成品图的页面因为访客真正看懂了作品背后的功夫信任感自然就建立了。关于暗色模式我收到了不少建议最终还是在第二版加入了支持开关但默认仍是浅色。原因在于作品集场景下浅色背景对作品色彩的还原度更公平暗色模式更适合作者夜间整理后台时使用。主题切换没有使用复杂的 CSS 变量系统只维护了少量语义色令牌切换逻辑不会蔓延到样式文件的各个角落。4. 大图加载的攻防战性能优化的完整清单4.1 根因视觉要求与加载速度的天然冲突ArtCraft 从立项之初就注定要面对一对矛盾视觉效果要求图要大、要清晰、要还原质感而网页加载速度要求图要小、要少、要按需加载。尤其是手工艺类作品皮料纹理、木纹细节、釉面光泽本身就是作品价值的组成部分过度压缩会让展示效果荡然无存。我第一次做性能审计时数据非常难看一个首页包含 20 件作品平均每张原图 3MB 以上页面总重量逼近 60MB首屏完全加载耗时超过 8 秒。移动端用户基本等不到首屏渲染完就划走了。这个结果倒逼我做了一次系统性的图片优化也是整个项目里收益最大的一轮迭代。4.2 分层图片策略的落地前面提到的三级图片规格表在实施时最关键的一点是上传即处理。作者在后台拖入一张原图后端程序会同步生成缩略图、预览图和保留原图三个版本并用统一的命名规则存放。这样前端在任何场景下都不需要加载原图除非用户主动点击查看细节。处理管线里有一个细节值得多说两句WebP 的编码质量并不是越高越好。我实测过一组木作品质量参数从 90 降到 80 时文件体积减少约 40%肉眼几乎看不出差异再从 80 降到 70体积减少明显但画面已经出现轻微噪点。最终我按缩略图和预览图分别采用 82 和 86属于视觉观感和文件体积之间的平衡点。4.3 懒加载、响应式图片与缓存头配置图片分层解决的是每张图应该多大的问题懒加载解决的是哪些图现在应该加载的问题。ArtCraft 使用了浏览器原生loadinglazy搭配小段 IntersectionObserver 逻辑做兜底。前者实现简单、兼容性好后者负责处理边界情况——比如早期浏览器对原生懒加载支持不到位或者某些图片使用了背景图方式加载。响应式方面我在img标签上接入了srcset和sizes让浏览器根据视口宽度自动挑选最合适的图片版本。例如列表缩略图 600px 版本在手机端足够清晰在桌面端则自动切换为 900px 的增强版本。缓存头配置也是关键一环给图片资源设置了较长缓存时间同时通过给文件名追加内容哈希来保证更新后能强制刷新避免出现旧图被缓存的问题。4.4 优化前后实测数据对比做完整套优化后我没有急着上线而是用同样的网络环境重新跑了一遍性能测试。这一轮的结果差异非常大指标优化前优化后首页总传输体积约 58MB约 4.2MB首屏加载时间8.2s1.6s图片请求数量6012白屏时间2.8s0.6s移动端的结果同样明显特别是弱网模拟下首页从几乎不可用变成了勉强可用再配合预加载首屏关键图体验上已经能接受。这轮优化让我意识到很多性能问题的根源不是某个单点的失误而是整个处理链路里没有形成闭环——上传、存储、分发、展示各管各的数据路径上全是浪费。5. 给非技术创作者设计的内容管理后台5.1 10分钟学会的设计目标ArtCraft 管理后台的产品目标是一个从来没有用过 CMS 的作者第一次打开后台能在 10 分钟内独立完成一件作品的发布全流程。这件事的难度远比看起来大因为后台天然是功能密集型的——表单、列表、状态、排序、删除每一样都要给足明确入口又不能把界面挤成一团。我设计的切入点是用作品说话而不是用功能说话。后台首页不做各种统计图表而是直接用卡片显示最近发布的六件作品每张卡片右下角有三个点悬停展开编辑、上下架、删除操作。新作品发布按钮固定在页面右下角全程点击次数不超过三次。这套方案没有引入任何新手引导动画因为好的交互设计不应该需要解释。实际操作中作者填写一件作品的流程被压缩成了五个字段标题、分类、标签、封面图、详情内容。详情区支持简单的富文本和拖拽排序图片其余信息如尺寸、材质、年份都用可选字段处理不填也不影响发布。5.2 批量上传与 EXIF 隐私清理批量上传是我在做用户访谈时被反复提到的一个高频需求。很多作者手上动辄几百张作品图一张一张传实在劝退。后台实现了多文件拖拽上传并在上传过程中就进行分层规格的预处理。作者看到的是进度条和预览看不到的是程序已经在后台完成了格式转换、尺寸缩放和文件名生成。EXIF 信息清理是容易被忽略但极其重要的细节。手机拍摄的照片默认会写入 GPS 坐标、拍摄时间、设备型号等信息。直接把这些原图上传不仅可能导致隐私泄露还会让页面出现与作品无关的元数据。ArtCraft 在上传管线中添加了 EXIF 剥离步骤确保存到服务器的每一张图都只保留图像数据本身这个处理对经常在工作室之外拍素材的作者尤其必要。5.3 数据模型与询问单逻辑ArtCraft 的数据模型刻意保持简洁数据库里实际就是几张核心表在支撑所有功能works作品主表存标题、分类、描述、发布时间、上架状态images图片表存各规格文件的路径和排序tags标签表作者可自由创建和维护inquiries询单表记录访客针对某件作品发来的定制咨询询单功能的实现虽然简单但产品意义不小。访客在作品详情页点击咨询定制只需要填写联系方式和个人一句话需求提交后作者会在后台收到一条新记录同时同步一封邮件通知。这里我没有做站内 IM 功能因为对大多数手艺人来说线下微信或电话沟通的效率远高于站内聊天询单系统的价值在于收集意向而不是取代沟通工具。5.4 几个容易忽略的边界情况后台开发过程中我踩过几个有意思的边界问题写出来给大家避避坑一是超大文件上传。部分作者的原始照片可能到 10MB 甚至更大直接走常规上传接口很容易超时。我加了前端压缩预处理超过 5MB 的图片先在前端降采样一遍再上传既保住细节又减小传输压力。二是重复提交防护。上传过程中网络抖动导致作者点了两三次提交按钮后端如果没有幂等处理数据库中就会多出好几条完全一样的记录。我在前端做了按钮置灰后端再用上传会话 ID 做去重校验双保险才彻底解决。三是删除操作的心理门槛。做作品集后台最怕作者误删重要作品又没法找回。我给删除流程设置了两个阶段先是移入回收站回收站里停留 7 天到期才真正清理。这本质上是个极简的软删除机制成本几乎为零但给作者的安全感提升是实打实的。6. 部署上线后的运维实战与踩坑记录6.1 构建与部署链路里的三个坑ArtCraft 采用 Docker 作为最终交付形态构建镜像推送到服务器再跑起来。原本以为这会是整条链路里最顺滑的一环结果连环踩了三个坑。第一个坑是镜像体积失控。第一次构建出来的后端镜像足足有 1.2GB里面包含了一整套开发依赖和缓存文件。后来改成多阶段构建开发阶段安装全量依赖运行阶段只复制产物和必要文件镜像体积直接瘦身到 180MB。这个差距在带宽有限的服务器上影响巨大推送镜像的时间从十几分钟下降到了两分钟以内。第二个坑是 Nginx 配置的 SPA 回退。前端的单页应用在直接访问某个作品详情链接时会报 404原因是后端只认index.html这一个入口。找到需要在 Nginx 里配置try_files规则把所有非静态资源请求都回退到入口文件。这个坑几乎是所有前后端分离项目的必经之路配置好了之后还要注意 API 转发规则不能与静态资源规则混在一起。第三个坑是静态资源的缓存策略。上线后有一段时间后台更新了作品数据前台看到的却是旧内容原因是我给整个静态目录都设置了很长的缓存时间连页面本身也被缓存了。后来我按资源类型拆分图片和带哈希名字的静态文件走长缓存HTML 入口走短缓存数据接口走协商缓存三层策略各司其职才算真正解决了更新与缓存之间的矛盾。6.2 上线初期遇见的性能与兼容问题ArtCraft 上线后的前两周出现了一个比较隐蔽的性能问题SQLite 在 WAL 模式下大量只读请求按理说是能并行处理的但监控数据显示偶尔会出现接口响应时间飙升到 3 秒的情况。排查后发现是后端默认的数据库连接复用不当每个请求都创建了新的连接导致连接频繁切换反而比复用连接更慢。修复方案很简单——连接池化加读写拆分只读接口走复用连接写入接口单独处理响应时间很快恢复到百毫秒级别。兼容性问题则主要出现在老版本的移动浏览器上。例如部分 Android WebView 对现代 CSS Grid 的gap属性支持不完整导致作品墙的列间距错乱。我没有选择放弃 Grid而是用margin配合supports做降级处理老浏览器仍能正常渲染只是间距的表现略不同。对作品集类网站来说布局的视觉一致性很重要但保证内容可读性永远是第一位的。6.3 日常运维备份、日志与告警小型项目最忌讳的就是东西跑起来就不管了。ArtCraft 的日常运维我尽量做了一些自动化确保自己不用天天盯控制台。数据备份采用双保险每天凌晨通过定时任务把 SQLite 数据库文件复制到备份目录同时每周打包所有图片资源一并归档。由于 SQLite 本身就是单文件备份流程简单到只有几行脚本但这件事必须坚持做而且还要定期做一次恢复演练确保备份真的可用而不只是磁盘上躺着几个文件而已。日志方面我把访问日志与错误日志分开处理。访问日志不需要长期保留只做近 30 天的滚动覆盖错误日志则按天存档配合简单的错误告警——当接口 5xx 比例超过阈值时会收到一条通知。这套机制并不精妙但对一个人维护的全栈项目来说它足够让我在第一时间感知异常并在问题扩大之前介入处理。整个 ArtCraft 从想法到上线最让我意外的不是技术难点的攻克而是运营层面的反馈。上线两周后有一位做陶艺的作者在后台留言说这是她用过唯一一个不会让她觉得自己像个操作机器的作者。这句话比任何技术指标的优化都让我踏实。对我来说内容型产品的技术挑战从来不在于堆多少新技术而在于每个技术决策最终有没有让创作者更舒服地表达自己。如果你也在做类似的作品集产品我建议你把技术选型和性能优化都往后放一放先去陪真正的用户走一遍完整流程那些你以为是重点的技术问题多半会变得没那么重要。