delkonの网站开发日志
现在编写TS和Python这种比较依赖第三方库的语言的时候很少使用“古法编程”了,因为学习每个第三方库都需要一定的时间成本,使用Agent可以直接省去这方面的成本。现在自己更多的是在给Agent指引要实现的功能,然后Agent实现并测试功能,之后在实际部署过程发现问题之后再将问题告诉Agent进行修改,这样循环来对代码库进行改进
但是,在使用上述流程进行网页开发的过程中,也逐渐暴露出了一些问题
首先,也是最主要的问题在于:随着项目体量的不断增加,代码风格的不一致性变得越来越明显。由于 Agent 的上下文是有限的,每次重新开启一个新的 Agent 来参与网页搭建时,往往会生成风格略有差异的代码。在项目规模较小时,这种差异影响不大;但随着代码量的增长,这种风格上的割裂会不断累积,最终导致整体代码库的可维护性显著下降
针对这一问题,更合理的做法是在项目初期就对功能边界进行清晰划分。同时,应当设计一套统一的技能(skill),在每次启用新 Agent 时强制其遵循一致的代码风格与架构约定,从而保证整体项目的一致性
除此之外,还存在一些自身的心理层面的问题。Agent 在知识覆盖和问题定位上的能力往往优于人类开发者,无论是查找资料还是定位错误,都更加高效和精准。在进入一个全新技术方向时,也可以借助 Agent 快速搭建原型进行验证。然而,这种便利性在一定程度上削弱了自身对基础能力的锻炼。原本在学习一门新语言或框架时,需要亲自完成的项目初始化和基础结构搭建过程被弱化,从而导致对底层机制的理解不够深入。同时,一些代码中细微但巧妙的实现细节,也变得越来越容易被忽视
此外,虽然 Agent 生成的代码通常能够在功能上正常运行,但在某些情况下会忽略算法复杂度等关键问题,从而为后续的性能隐患埋下风险
现在本人想到的方法就是学习Agent的开发和调试的思路,被Agent反向训练成为其最为适配的Prompter。不过有些时候等于是这篇记录Agent吐出Token的过程真的非常煎熬....Agent的开发日志的博客诞生了,会一直更新方便后面等自己对前端更加了解时看看可不可以挑Agent的毛病,但进入正题之前,让我们先对前端的技术栈有一个大致的勾勒
前端概念梳理
这篇前端概念梳理主要参考peacesheep的博客内容,我们可以将前端理解为一条自下而上的技术栈链路:运行环境 → 模块与依赖 → 打包/构建链 → UI 框架 → 交付与性能
前端体系的最底层是运行环境,通常可以分为浏览器环境与 Node.js 环境。浏览器环境主要面向用户侧,负责页面渲染、脚本执行、事件处理以及各类 Web API 的调用;而 Node.js 环境则主要面向开发侧,为前端工程化提供支撑,例如依赖管理、构建打包、开发服务器以及服务端渲染(SSR) 等能力,并且在现代全栈框架中进一步扩展出一定的后端执行能力
随着项目规模不断扩大,前端代码需要进行更清晰的模块化拆分。一个完整的前端页面通常可以拆分为 UI 组件模块、工具函数模块、API 请求模块、状态管理模块以及样式模块等。常见的模块化体系主要包括两类:一类是 CommonJS,通过 require 和 module.exports 实现模块的导入与导出;另一类是 ES Module(ESM),通过 import 和 export 完成模块组织。在实际开发中,开发者通常不仅会编写自己的业务模块,也会基于第三方库进行功能扩展,从而减少重复造轮子的成本,提高开发效率。常用的包管理工具包括 npm、yarn 和 pnpm
当项目开发到一定阶段后,通常需要在浏览器中预览和运行代码。然而,现代前端项目中的源码往往并不能被浏览器直接识别,因为其中通常包含 TS、JSX/TSX、Less/Sass 等浏览器无法原生解析的内容。因此,就需要借助打包与构建工具,将这些开发态代码转换为浏览器可执行的标准 JS 和 CSS,从而完成从“源码”到“运行时代码”的转换。除了基础的编译功能外,构建工具还承担着一系列重要的工程化职责,例如:打包(Bundling),即将多个模块整合为更适合部署的资源;转换(Transpile),即进行语法降级以兼容不同浏览器环境;优化(Optimization),如代码压缩、Tree Shaking、代码分割等;以及开发支持(DX),包括热更新(HMR)、开发服务器和错误提示等能力
再往上一层,就是开发者最熟悉的 UI 框架。例如 Vue、React、Angular 等,都可以归为这一层。它们主要解决的是页面如何描述、组件如何复用、状态如何管理以及交互逻辑如何组织等问题。本质上,UI 框架通过组件化和声明式开发的方式,帮助开发者更高效地构建复杂的前端应用,并提升代码的可维护性与复用性
当项目开发完成之后,前端工作并没有结束,而是进入了交付与性能优化阶段。在真实的生产环境中,仅仅生成“可以运行的构建产物”远远不够,还需要综合考虑一系列工程与运维层面的问题。例如,资源部署与托管需要考虑静态资源如何发布到 CDN、对象存储或服务器;性能优化需要关注首屏加载速度、缓存策略、懒加载以及资源压缩;兼容性需要处理不同浏览器和设备环境下的适配问题;安全性需要考虑 XSS、防篡改以及接口鉴权等风险;服务端能力则涉及是否需要 SSR、边缘渲染或后端接口支持;此外,还需要具备监控与日志能力,例如错误上报、性能监控和用户行为分析,并配合 CI/CD 流程完成自动化构建、测试与部署
总体来看,从运行环境、模块化组织与构建工具,到 UI 框架,再到最终的部署交付与性能保障,这些部分共同构成了一个完整的前端项目技术路线图,也就是一个相对完整的前端 Roadmap
开发日志
整体框架
- 网站在样式层面采用 UnoCSS,通过在 HTML 的
class属性中直接编写原子化样式,从而简化样式开发流程。本项目基于 Vite 构建,Vite配置UnoCSS方式可参考UnoCSS Vite协作教程 - 博客系统的核心功能由 VitePress 提供,其使用方法详见Vitepress官方文档
- 网站的评论、点赞以及浏览量等互动功能,基于 Waline 并通过 Vercel 部署实现,部署流程参考Vercel部署
博客页面
- 在
Chrome内核浏览器中,当祖先节点同时应用overflow: hidden与border-radius时,mask-image属性无法正确渲染,也就是说图片上的“图层蒙版”效果无法实现 - 给
VitePress自带的code-group功能扩展运行其中包裹的代码片段的按钮,还需要一些约定语法能够开启或取消运行按钮功能 - 根据VitePress中提供的接口,在
markdown展示页面中添加“上一页 / 下一页”导航以及目录大纲功能
/**
*
* 1. URL 参数透传派 (Vue, TS, C++):纯前端完成编码转换,新开窗口,零服务器成本。
* 2. 先传数据后跳派 (Go):解决 URL 长度限制,依赖目标平台 Share API 做中转。
* 3. OpenAPI 原地执行派 (Rust):直接调用底层执行引擎,在文档页内实现“即看即测”。
*
*/
// 支持将网页中的代码块一键跳转至在线 Playground,并自动携带代码内容
const EXTERNAL_PLAYGROUNDS: Record<string, string> = {
vue: 'https://play.vuejs.org/',
cpp: 'https://cpp.sh/',
go: 'https://goplay.tools/',
ts: 'https://www.typescriptlang.org/play/'
}
// Rust Playground 提供代码执行接口,可通过该 API 提交代码并获取运行结果
const RUST_EXECUTE_ENDPOINT = 'https://play.rust-lang.org/execute'
// Rust Playground execute API 返回结构
interface RustExecutionResponse {
success?: boolean
stdout?: string
stderr?: string
error?: string
}
// Go Playground 需要 share 之后拿到 ID 再进行跳转
const GO_SHARE_ENDPOINT = 'https://play.golang.org/share'动效页面
网站页面中的动画效果主要通过 animejs 实现,少部分较简单的动效则使用 CSS 动画完成。当前网站中已实现动效的页面包括:blogs 页面标题的逐字展示、about 页面的“一笔画”动画与图标球形点云效果、tags 页面的樱花碰撞效果,以及首页的樱花飘落与波浪双向摆动效果
在实现方式上,涉及 DOM 获取、元素位置计算或第三方动画实例初始化的 JS 动画逻辑,通常放在 onMounted 生命周期中执行。因为此时组件已经完成挂载,能够安全地访问页面元素并启动动画。相比之下,CSS 动画更适合处理结构简单、表现明确的动效,其实现方式更轻量、维护成本也更低,因此在合适的场景下通常优先采用;而对于时间轴控制更复杂、交互性更强或需要动态计算的动画效果,则仍然需要借助 JS 来完成
共享组件
共享组件主要包含了头部区域的导航功能、搜索功能,以及基于 oh-my-live2d 库的 Live2D 模型展示功能。Live2D 模型的初始化通常放在 onMounted 生命周期中进行,以确保相关 DOM 节点已经完成挂载,从而能够正确创建并加载模型实例。与此同时,在组件卸载时,需要在 onUnmounted 生命周期中对相关实例、事件监听或其他资源进行清理,以减少不必要的资源占用,并降低内存泄漏风险
网页开发常用命令
网页开发不仅仅是代码编写的过程,更是一个持续进行测试、验证与调试的过程。相比单纯实现页面功能,开发者往往需要在项目运行前后投入更多时间在调试与问题排查上。在实际的网页开发与调试过程中,一些常用的命令行工具几乎是不可或缺的。熟练掌握并灵活运用这些命令,将显著提升开发效率与问题定位能力。下面整理了开发中经常使用的一些命令
# `curl` 主要用于向服务器发送请求、抓取网页内容、测试接口,以及模拟前后端之间的数据交互过程
# 它支持多种协议,在开发中最常见的是 HTTP 和 HTTPS
# --------------------------- curl [选项] URL ---------------------------
curl https://baidu.com
# 向目标 URL 发送请求,并将服务器返回的内容输出到终端
curl -sS https://baidu.com
# `-s`:静默模式,不显示进度信息
# `-S`:静默模式下如果出错则显示错误信息
curl -I https://baidu.com
# `-I`:只获取响应头信息,不获取响应体内容
curl -o index.html https://baidu.com
# `-o`:将返回内容保存到指定文件中
curl -X POST https://httpbin.org/post \
-d "a=1"
# `-X`:指定请求方法
# `-d`:发送请求体数据
# 这里表示向后端发送 POST 请求并携带表单数据
curl -X POST https://httpbin.org/post \
-H "Content-Type: application/json" \
-d '{"a":1}'
# `-H`:添加请求头(header)
# 这里表示向后端发送 JSON 数据
curl -v https://baidu.com
# `-v`:显示详细的请求和响应过程,便于调试(verbose)
curl -L http://example.com
# `-L`:自动跟随重定向# `ping` 用于检测本机与目标主机之间的网络连通性
# 它通过发送 ICMP 数据包来判断目标主机是否可达,并显示数据包往返所需的时间,常用于网络连通性测试和延迟检测
# --------------------------- ping [选项] 主机地址 ---------------------------
ping baidu.com
# 检测本机与 baidu.com 之间的网络连通情况
ping -c 4 127.0.0.1
# `-c`:指定发送数据包的次数(count)
# 这里表示仅发送 4 个数据包后停止
ping -i 2 127.0.0.1
# `-i`:设置发送数据包的时间间隔(interval)
# 这里表示每隔 2 秒发送一次数据包
ping -s 100 127.0.0.1
# `-s`:指定发送数据包的大小(size)
# 这里表示发送 100 字节的数据包
ping -W 2 127.0.0.1
# `-W`:设置等待响应的超时时间(wait)
# 这里表示每次等待响应的时间为 2 秒
ping -t 64 127.0.0.1
# `-t`:设置 IP 数据包的 TTL(生存时间)
# 这里表示将 TTL 设置为 64
ping -4 baidu.com
# `-4`:强制使用 IPv4
ping -6 baidu.com
# `-6`:强制使用 IPv6# `traceroute` 用于追踪数据包从本机到目标主机所经过的网络路径
# 它能够逐跳显示沿途路由节点及其响应时间,常用于分析网络延迟、排查路由异常以及定位链路故障
# ----------------------- traceroute [选项] 主机地址 -----------------------
traceroute baidu.com
# 追踪从本机到 baidu.com 的完整路由路径
traceroute -n baidu.com
# `-n`:以数字形式显示 IP 地址,不进行域名解析,可加快显示速度
traceroute -m 20 baidu.com
# `-m`:设置最大跳数(max-hops)
# 这里表示最多追踪 20 跳
traceroute -q 1 baidu.com
# `-q`:指定每一跳发送的探测包数量
# 这里表示每一跳只发送 1 个探测包,输出更简洁
traceroute -w 2 baidu.com
# `-w`:设置等待响应的超时时间(wait)
# 这里表示每个探测包最多等待 2 秒
traceroute -f 3 baidu.com
# `-f`:设置从第几跳开始探测(from)
# 这里表示从第 3 跳开始追踪
traceroute -I baidu.com
# `-I`:使用 ICMP 回显请求方式进行探测(ICMP)
traceroute -T baidu.com
# `-T`:使用 TCP 方式进行探测(TCP)
traceroute -T -p 80 baidu.com
# `-p`:指定目标端口(port)
# 常与 `-T` 配合使用,这里表示探测目标主机的 80 端口
traceroute -4 baidu.com
# `-4`:强制使用 IPv4
traceroute -6 baidu.com
# `-6`:强制使用 IPv6# `netstat` 用于显示网络连接、路由表、接口状态以及端口监听情况
# 在网页开发和服务调试中,常用于检查端口是否被监听、服务是否启动、当前有哪些网络连接以及对应的进程信息
# ------------------------ netstat [选项] ------------------------
netstat
# 显示当前系统的网络连接信息
netstat -a
# `-a`:显示所有连接和监听端口(all)
# 包括正在建立、已建立以及处于监听状态的连接
netstat -t
# `-t`:仅显示 TCP 连接(tcp)
netstat -u
# `-u`:仅显示 UDP 连接(udp)
netstat -l
# `-l`:仅显示处于监听状态的端口(listen)
netstat -n
# `-n`:以数字形式显示地址和端口号(number)
# 不进行主机名和服务名解析,显示速度更快
netstat -p
# `-p`:显示与连接或端口对应的进程信息(process)
# 通常需要足够权限才能看到完整进程信息
netstat -r
# `-r`:显示内核路由表信息(route)
netstat -i
# `-i`:显示网络接口统计信息(interface/internet)
netstat -s
# `-s`:显示各网络协议的统计信息(statistics)
# 可用于观察 TCP、UDP、IP 等协议的收发情况
netstat -lt
# 显示所有正在监听的 TCP 端口
netstat -lu
# 显示所有正在监听的 UDP 端口
netstat -an
# 显示所有连接和监听端口,并以数字形式输出地址和端口号
netstat -lnt
# 显示所有正在监听的 TCP 端口,并以数字形式输出
# 常用于检查服务端口是否成功启动
netstat -lntp
# 显示所有正在监听的 TCP 端口,以及对应的进程信息
# 这是开发中非常常用的一条命令
netstat -antp
# 显示所有 TCP 连接及其对应的进程信息
# 可用于查看当前连接状态,例如 ESTABLISHED、LISTEN 等
netstat -an | grep 8080
# 配合 `grep` 筛选指定端口的信息
# 这里用于查看 8080 端口是否存在相关连接或监听状态
netstat -lntp | grep 3000
# 查看 3000 端口是否正在被监听,以及对应的进程是谁