文章
用 Astro 做工业官网➔
我用 Astro 做了 LIANXIN 的工业机械官网,里面有产品目录、工厂展示,也接了 Directus 新闻和 AI 产品顾问。做这种网站,很多选择都落在同一个问题上:哪些内容应该直接送到用户面前,哪些功能等用到的时候再启动。 机器图片、参数表、介绍文字适合提前生成;新闻要能随时更新;轮播、咨询和视频又各有自己的交互。把这些边界拆清楚,后面的实现会顺很多。 官网现用的工厂主题海报。来源:LIANXIN 官网。 页面先到,交互按需启动 Astro 比较合我胃口的一点,是它允许我从 HTML 开始组织页面。产品介绍和图片这些内容先渲染出来,需要状态和事件的地方再接 React。装了 React 集成,也不用把整页都做成客户端应用。 本站导航用 client:load,页面加载时就激活;产品轮播用 client:visible,进入视口再加载和水合。两种方式都可以先输出 HTML,区别在于何时让组件在浏览器里运行。具体触发时机可以看 Astro 的客户端指令文档。 FAQ 更进一步,用了项目自己注册的 client:interaction。鼠标移入、触摸按下或键盘聚焦时开始加载。这里有个小坑:用户可能在加载结束前就点了按钮,所以指令会拦住这次点击,等组件就绪再补发。普通链接照常跳转。省 JavaScript 可以,别把第一次点击也省了。 新闻更新走另一条路。列表和详情按请求读取 Directus,首页的最新新闻则交给 server:defer。首页先返回主体和占位内容,新闻区块随后单独请求 HTML。这样 CMS 响应慢一些,也不会拖住整个首页。这部分需要服务端,我用 Node adapter 的 standalone 模式运行站点。 Astro 官方原理图,说明静态页面与动态区块如何分别取得内容。来源:Astro 5.0,© Astro;此图并非本站部署架构图。 产品页和 AI 共用一份资料 产品有不同系列,每个型号又有图片、参数和应用说明。如果这些东西散在页面里,改一项参数就得挨个找。我把产品整理成 TypeScript 数据,再让页面读取它。型号详情用同一份模板,通过 getStaticPaths() 生成路由。 这是详情页里的路径生成部分,省略了导入和页面模板。 export function getStaticPaths() { return products.map((product) => ({ params: { category: product.category, slug: product.slug, }, props: { product, category: getCategory(product.category), }, })); } 参数表读这份数据,页面里的 Product 结构化数据也读它。AI 产品知识同样从这里生成,避免官网改了规格,顾问还在背旧版本。数据模型里保留型号、分类、图片和规格这些明确字段,页面只负责把它们展示出来。 AI 后端是独立的 Cloudflare Worker。它根据问题里的型号、别名和当前页面检索资料,最多选六份交给 DeepSeek,再检查回答附带的来源 ID 是否属于这批资料。浏览器拿到的是回答和对应的站内链接,模型密钥留在 Worker。 这种检索方式规模小、规则直接,适合目前这批产品。它能约束资料来源,不能保证模型每句话都对,具体选型和报价仍要人工确认。另外,共用源文件不等于自动同步上线。产品资料改动后,主站和顾问 Worker 都需要重新构建部署,这个步骤不能漏。 图片讲构图,视频讲时机 工业设备本来就长,外面再套几层大边框,能看清的机器只会越来越小。产品图这里用 object-fit: contain,保留完整外形;标题、卖点和按钮放到旁边,让图片有足够的展示面积。轮播控制留在左右两侧,翻图时不用往下找。 IBM 80E 的展示图,机身轮廓完整保留。来源:LIANXIN 对应型号页。 首页海报则准备了横、竖两版,用 <picture> 按 max-aspect-ratio: 1/1 切换。选图依据是视口形状,竖屏平板也能得到竖版构图。首张海报优先加载,后面的图延迟加载。文案目前也在海报里,换来的排版控制更直接,代价是改文字和做多语言都要重新出图。 视频的处理更干脆。工厂介绍先展示封面,视频地址放进 data-src,点击播放时才赋给 src。访问者只是看看页面,就不用顺手下载一段几分钟的视频。 播放函数中的关键动作如下,省略了加载提示、超时和错误处理。 if (!video.hasAttribute("src")) { video.src = video.dataset.src!; } void video.play(); 这一块用原生 <video> 和一个自定义元素管理播放状态,就够用了。网络慢时显示加载提示,失败后给出重试按钮和原视频链接;离开组件时中止事件监听并暂停视频。用户至少能知道点下去之后发生了什么,也有办法继续操作。

用 Android 做疲劳检测➔
我做了一个 Android 疲劳提醒应用,用前置摄像头观察闭眼和张嘴,在手机上完成检测。模型接进来以后,真正需要想清楚的是后面的判断。眨一下眼就报警,提醒很快会变成噪声;摄像头看不清了还显示正常,又会让人误解系统的能力。 先把眼睛和嘴巴量出来 项目用的是 ML Kit Face Detection,模型随 APK 打包,安装后不用再等模型下载。它提供人脸轮廓、嘴部关键点和睁眼概率,疲劳规则由应用自己实现。这样检测和判定就能分开,调整持续时间不用动相机代码。 模型负责提取人脸信息,什么时候提醒,由后面的规则决定。插画来自 Google ML Kit 官方文档。 眼睛用 EAR,也就是眼睛的纵横比。从眼轮廓里选六个点,把两段上下眼睑距离相加,再除以两倍眼宽。计算式是 EAR =(上下一组眼睑距离 + 另一组眼睑距离)÷(2 × 眼宽)。闭眼时高度变小,EAR 通常也会下降。用比例可以减轻人脸远近带来的尺度变化,但侧脸、遮挡和关键点偏移仍然会影响结果。 Google ML Kit 的官方轮廓示例,点图可查看原图。眼睑和嘴唇的点要分清,本文的 MAR 量的是唇外沿。这是官方示例,不是本应用实测截图。图片来源。 嘴巴用 MAR。这个项目取上唇外上沿中心到下唇外下沿中心的距离,除以左右嘴角距离。公式看着简单,取点位置却不能含糊。量唇外沿和量嘴巴内部开口,算出来的数不会一样,网上找到一个阈值直接抄过来,很可能对不上。 眼部还保留了 ML Kit 的睁眼概率,与 EAR 做 OR 判断,任一路满足条件就进入对应计时。概率这一路要求左右眼的值都有效。这样能让两路信号各自参与,但也意味着单路误差就可能触发候选;它们来自同一个检测器,不能当成两套独立证据。嘴部单独判断,眼睛暂时不可用时,有效的 MAR 仍然可以参与检测。 一次越线,还不能算一个动作 单帧只知道这一刻眼睛有多窄、嘴张得有多大。要把眨眼、短暂张嘴和持续动作分开,还得加上时间。当前普通闭眼条件是 EAR ≤ 0.22,或两眼概率都有效时任一眼低于 0.35,持续 800 ms 后进入 WARNING。更强的闭眼条件是 0 < EAR < 0.17,或两眼概率都低于 0.35,持续 400 ms 就进入 DANGER,且优先级更高。 哈欠候选用的是双阈值。MAR 超过 0.40 才开始计时,开始后只要不低于 0.35 就继续,累计达到 800 ms 才提醒。假设数值在 0.41、0.39、0.42 之间晃,单一阈值会让计时反复归零。嘴还张着,计时器已经替你闭上了。 代码里的关键分支只有几行。下面节选自判定逻辑,省略了无效值检查和后续计时。 val yawning = mar != null && if (highMarStartMs == null) { mar > config.marYawnEnterThreshold // 0.40 } else { mar >= config.marYawnExitThreshold // 0.35 } 时间取相机帧的时间戳,不取模型回调完成的时刻。否则推理这次慢一点、下次快一点,也会混进动作时长。相邻有效观测间隔超过 1.5 秒时,未完成的计时清零,从当前帧重新开始。中间没有画面,系统就没有依据把两次张嘴拼成一次连续动作。这个间隔也是工程取舍,不能证明采样之间发生了什么。 看不清,就别继续报正常 判定器除了 NORMAL、WARNING 和 DANGER,还留了 DEGRADED。没有人脸、眼嘴信号全部无效,或检测到黑暗画面、相机异常时,就清除未完成计时,显示当前无法可靠检测的原因。NORMAL 也只表示当前有效信号没有达到提醒条件,不能解释成驾驶员一定清醒。 相机侧通过 acquireLatestImage() 取最新分析帧,当前会话已有推理任务时,新帧直接释放,避免越算越落后。停止检测或切到后台时,会话编号递增;旧任务即使晚点返回,也不能覆盖新的状态。重新开始检测后,同样要从新画面重新计时。 声音和振动只由 DANGER 触发,WARNING 只更新界面。危险告警做了约两秒冷却,并用不重放历史事件的 SharedFlow 发送;界面只在前台恢复状态下接收,暂停时停止提示。否则回到应用突然补响一声,提醒的就成了过去的自己。 目前这套实现仍是固定阈值的研究原型,没有个人校准。持续张嘴也可能来自说话,睁眼概率还有正脸角度限制。当前手机端只在模拟器上验证了安装、相机链路和前后台切换,真人识别、覆盖层精度与声音振动还需要目标手机实测。接下来更值得做的是用正常说话、短张嘴、自然哈欠和闭眼录像,在静止环境里检验误报与漏报;这套原型还不能当作经过道路验证的驾驶安全系统。

MediaPipe 手势识别的几个坑➔
这次用鲁班猫 3 做了个离线手势识别,系统是 Android 14。摄像头看到手就画出骨架,比个 OK,自动保存一张带骨架的截图。 模型直接用 Google 的 MediaPipe。它已经能找出手部的 21 个关键点,还带七种静态手势分类。自己要处理的是相机、画面坐标,以及识别结果怎么变成实际操作。 模型用现成的 Android 用 Kotlin 写,相机接 CameraX,识别接 MediaPipe Tasks。依赖用这几项。 def cameraxVersion = '1.4.2' implementation "androidx.camera:camera-core:$cameraxVersion" implementation "androidx.camera:camera-camera2:$cameraxVersion" implementation "androidx.camera:camera-lifecycle:$cameraxVersion" implementation 'com.google.mediapipe:tasks-vision:1.0.0' 把官方模型放进 app/src/main/assets,创建识别器时指定这个文件,运行模式设为 LIVE_STREAM,通过回调拿结果。官方 Android 示例已经有完整接法,照着看比从空白工程硬猜快。 模型跟着 APK 一起打包,推理在板子上完成,运行时只需要相机权限。 底图来自 MediaPipe 官方测试图片,这是本项目的板端测试输出。红点是关节点,蓝线标出拇指,其余连线用绿色。 相机别开两路 CameraX 常见的接法是 Preview 显示画面,ImageAnalysis 给模型送帧。但在我这块 RK3576 板子的固件上,两路一起开会卡住。 最后只保留一条 ImageAnalysis,预览和识别共用它。拿到 1920×1080 的图像后,处理行步幅,把最长边缩到 640 像素,再统一旋转和镜像,送进模型。 帧策略用 KEEP_ONLY_LATEST。处理不过来就丢旧帧,别让识别排队。当前代码还限制了至少 100 ms 才提交一帧,所以提交速率最高约每秒 10 帧,实际显示速度还得看推理回调。 ImageProxy 用完一定要 close,跳过帧和异常分支也一样。 缓冲区占着不放,相机后面就可能没帧了。 另外,板子上的 CAM0、Android 的 Camera ID 0 和 /dev/video0 要分别核对。这个项目同时检查物理 m00_ 模块、逻辑 ID 0 和当前固件的 FRONT 属性,条件不满足就停。这套映射只针对已经验证过的板子和固件。 骨架为什么会飘 这个问题得从坐标和时间两头查。 坐标上,模型给的是归一化关键点,预览用的却是 centerCrop。图片会先放大,再裁掉超出显示区域的部分。直接拿关键点乘屏幕宽高,当然对不上。 把关键点投到屏幕上,要和预览用同一个缩放比例和裁切偏移。下面的 x、y 是模型返回的归一化坐标,srcW、srcH 是模型输入图像的宽高。 scale = max(viewW / srcW, viewH / srcH) offsetX = (viewW - srcW * scale) / 2 offsetY = (viewH - srcH * scale) / 2 screenX = x * srcW * scale + offsetX screenY = y * srcH * scale + offsetY 这些除法要用浮点数。旋转和镜像也统一在推理前处理,别让预览和模型各算各的方向。 时间上,手已经移走了,上一帧的结果才回来。把旧骨架叠到新画面,多少有点灵魂出窍。 我的处理是从结果回调里取出对应的输入图片,和这次关键点一起更新到界面。画面和骨架必须属于同一帧。 代价是显示会等识别结果,预览流畅度也跟着受限。 还有一个容易漏的判断。分类结果是 None,只代表没认出支持的手势。只要关键点还在,骨架就继续画;没检测到手、结果过期或者切到后台时,再清掉。 OK 截图要防连拍 官方这七种分类没有 OK,我用现有关键点补了一层几何判断。拇指和食指指尖靠近,食指弯曲,另外三根手指伸直,才算匹配。 距离按掌部尺寸归一化,再结合关节角度判断。用固定像素距离的话,手往前伸一点,阈值就不合适了。这里用的是按输入宽高还原后的 2D 坐标,和画面里的骨架保持一致。 然后才是触发控制。视频每帧都可能认出 OK,你一直举着手,就一直存图,相册受不了这个。 判断 当前条件 确认手势 最近最多 5 帧中至少 4 帧强匹配,当前帧也满足,窗口持续至少 300 ms 触发后锁定 保持 OK 只拍一张 允许再拍 离开 OK 至少 600 ms,两次触发至少间隔 1.5 秒 触发条件严一点,保持条件宽一点,减少边界抖动。采样断开超过 400 ms,就清掉旧的观察窗口。这些是当前配置,实际触发时间还受帧率影响。 截图直接合成当前画面和同帧骨架,再用 MediaStore 存成 PNG。只画这两层,状态栏和提示框就不会混进去。编码和写盘放到独立线程,别堵着相机识别。 保存的是当前显示画面的合成图,输入已经缩小过,不能当成传感器原图。 这版配置的还是 Delegate.CPU。RK3576 有 NPU,但应用得接入 RKNN 才用得上。RKNN 的官方流程包括模型转换和运行时接入,前后处理也要重新对齐,光改一个配置没用。

自主进化的本地AI Agent-Hermes➔
Hermes Agent 是一款基于大语言模型的开源自主智能体工具。 只要配置好模型接口或本地环境,就能让 AI 自动编写与运行代码、调用工具、检索信息并完成多步骤复杂任务。 它是开源且免费的。 支持接入各类开源大模型以及主流商业模型 API。 具备强大的函数调用与自主任务规划能力。 支持本地部署与运行,数据和指令安全可控。 能够直接与系统终端环境及多种外部工具无缝协作。 使用方法 在本地环境中完成软件的安装与环境初始化。 配置对应的大模型 API 密钥或本地模型连接信息。 在命令行或交互界面中输入你想要执行的任务目标。 智能体会自主拆解步骤并按需调用系统工具执行。 查看执行过程与输出,等待任务自动完成。 官方链接: https://hermes-agent.nousresearch.com 进入官网即可查看详细文档与快速上手指南 满分10分 个人评分6.5分 因为功能依赖python 需要下载库 但是无法自定义国内镜像 不挂VPN得等个三四十分钟 如果没有VPN 更新和安装的过程会十分痛苦 没事 后面我会推一个好用的clash

鸟街上的孤岛➔
下午不知触动了哪根神经,突然想起小时候看过的一本小说,《鸟街上的孤岛》。 读那本书的时候,我不是在读别人的故事。我爬上了那栋废墟的绳梯,躲进三楼的储物柜;我穿过秘密通道,在犹太区和波兰区之间来回;我屏住呼吸躲德国兵,在空房子里翻找食物。那场冒险从头到尾是我自己的。这么多年过去,我还能记起那种心跳——又害怕,又兴奋,又觉得自己无所不能。一个孩子对冒险的全部渴望,那本书都给过了。 而比冒险更让我留恋的,是那里面爱情和友情的样子。 那段爱情几乎什么都没有发生,可恰恰因为什么都没有发生,反而什么都定下来了。它让我在很小的时候就认定:真正的感情是干净的、克制的、在乱世里也不改样的;是废墟里分一块面包,是朝不保夕还惦记着另一个人。友情的定性也一样——一只叫白雪的天竺鼠,几个靠得住的人。我后来对爱情和友情的全部标准,大概就是那时候照那本书定的模子,一直没换过。 后来我长大了,看了很多新闻,读了很多历史,对犹太民族渐渐有了一些不太好的看法。这话说出来不好听,可我得诚实。人到了某个年纪,心里会装下很多互相打架的东西。 奇怪的是,这并没有让我讨厌那本书。 那场冒险、那段爱情和友情,还好好地待在记忆里,还是那么亮。书里的真善美——勇敢、善良、爱、希望——至今还是我三观里最下面那层地基。我甚至偶尔会想:写下这些的人,本身就是个犹太幸存者;书里我遇见的那些人,也是犹太孩子。这让我有点别扭,可事实就是事实。大概人的心里,本来就该装得下这种别扭。 有时候我觉得,童年读过的书就像种子。它长出来的东西,不归后来那些乱七八糟的情绪管。鸟街七十八号那栋废墟,现在还立在我精神世界的某个角落,风吹不倒。

不接触SEO容易忽视的框架—Next.js与Nuxt.js➔
引言 在常规的React或Vue项目开发中,前端工程师主要致力于构建单页应用。这类应用在状态管理和局部刷新上表现优秀,开发体验好。但在涉及业务线增长,需要通过搜索引擎自然流量获客时,SPA会遇到技术瓶颈。为了解决这个问题,通常需要引入Next.js或Nuxt.js。 1、Next.js 和 Nuxt.js 是什么 Next.js和Nuxt.js分别是基于React和Vue构建的同构前端框架。 原生的React和Vue默认采用客户端渲染,即服务器仅返回一个包含基础结构的HTML文档,所有DOM节点的生成以及数据请求均交由浏览器下载并执行JavaScript来完成。 Next.js与Nuxt.js的核心特性在于提供了SSR服务端渲染和SSG静态站点生成能力。它们将页面的渲染逻辑前置到服务器端或打包构建阶段,直接向浏览器输出包含完整HTML结构的页面。 2、有什么用 这两个框架在工程化实践中的核心价值体现在两个方面: 第一是搜索引擎优化即SEO。主流搜索引擎的爬虫在抓取网页时,处理复杂且需要异步加载数据的JavaScript能力非常有限。传统的SPA在爬虫抓取时通常呈现为空白页面,导致内容无法被建立索引。引入服务端渲染后,爬虫可以直接读取到渲染好的结构化文本和链接,从而保障网页的收录效率和搜索排名。 第二是提升首屏加载速度。由于服务器直接返回完整的HTML内容,浏览器无需等待下载庞大的JS文件后再去执行渲染逻辑。对于网络环境受限或对首屏绘制时间等核心性能指标要求较高的C端产品,这种方案能大幅缩短用户的白屏等待时间。 3、为什么推荐 除了解决SEO与首屏性能问题,从工程效率的角度来看,这两个框架也具备较高的采用价值。 首先是路由设计的简化。两者均采用基于文件的路由系统。开发者只需在特定目录下按照规范创建文件,系统即可自动生成对应的路由,降低了维护中心化路由配置表的成本。 其次是具备轻量级后端能力。框架内部集成了API路由功能,开发者可以在同一个项目中编写简单的后端接口逻辑,直接进行数据库交互,非常适合全栈式微型项目的快速迭代。 最后是内置的自动化性能优化。框架底层集成了对图片、字体、外部脚本的构建与加载优化策略,开发者无需过多介入底层的Webpack或Vite配置,即可使项目达到较高的前端性能基线。 4、相比起Astro的优势和劣势 在内容型网站和SEO领域,近期Astro框架的关注度较高。与Astro相比,Next.js和Nuxt.js的优劣势较为明确,主要取决于业务场景。 Next.js与Nuxt.js的优势在于状态管理和复杂交互处理。如果业务包含高频的前端逻辑交互,例如SaaS系统后台、复杂的表单系统或在线协作工具,Next与Nuxt可以无缝复用React或Vue的完整生态,开发者在客户端与服务端之间的心智转换成本极低。 其劣势在于构建产物的体积依然偏重。即使采用SSR,Next和Nuxt最终仍需向客户端下发框架的运行时代码和状态数据,以完成页面的水合过程,这意味着整体的JS包体积很难做到极致精简。 Astro的架构设计不同,它默认采用群岛架构,核心理念是按需加载JavaScript。大部分静态页面会以纯HTML形式输出,仅在需要交互的局部组件上挂载JS。因此在构建博客、文档中心或营销落地页等重内容、轻交互的场景时,Astro的加载性能和打包体积往往优于Next和Nuxt。此外,Astro支持在同一个页面中混合使用React、Vue等不同框架的组件,提供了更高的选型自由度。 高交互且需要部分SEO的复杂Web应用更适合选择Next.js或Nuxt.js;而以静态阅读为主的内容型站点,现阶段使用Astro是更好的工程实践。

打破前端框架壁垒-前端新贵 Astro ➔
前端技术栈更迭极快,2021年才首次发布的Astro算是一个极其年轻的新起框架。作为一个专为内容展示设计的构建工具,它目前的行业热度和实际表现非常亮眼。最近我将个人站点的底层彻底重构为了Astro架构。这里直接从技术逻辑出发,梳理一下这个新框架的核心机制和开发体验。 1、Astro与其它主流框架有特别突出明显的区别? 常规的前端框架像Vue或React是把整个应用逻辑打包发送给浏览器解析。 Astro的核心区别在于默认剔除所有客户端JavaScript代码。它在构建阶段直接将组件编译成纯静态HTML。只有开发者明确标记需要交互的局部组件才会单独下发执行脚本。这种底层设计直接消除了框架运行时的性能损耗。 2、为什么推荐Astro? 2.1 逻辑简单容易上手 传统的单页应用配置路由通常需要引入专门的路由库并且维护复杂的映射表。Astro采用基于文件系统的直观路由逻辑。在特定目录下新建一个代码文件就自动生成对应的网址路径。 它的全局布局封装极其直观,没有沉重的状态管理负担,整体开发门槛比基础的Vue还要低。 假设你项目里有一个叫做 src/pages 的核心文件夹.你在里面新建几个代码文件.网页的网址就会自动按层级生成. 你新建 src/pages/index.astro 文件.用户访问 www.web-chang.com 就会直接打开这个页面. 你新建 src/pages/about.astro 文件.用户访问 www.web-chang.com/about 就能直接看到你的关于我页面. 你在 pages 目录下新建一个 blog 文件夹并新建 test.astro 文件.也就是 src/pages/blog/test.astro 这个物理路径.用户访问 www.web-chang.com/blog/test 就能直接打开这篇文章. 你完全不需要去维护类似 router.js 这种专门管理网址跳转的配置文件.你的物理代码文件夹长什么样.线上的网址路径结构就是什么样.这种所见即所得的设计直接干掉了繁琐的路由配置工作. 2.2 对服务器性能要求低能省钱 动态渲染框架需要始终消耗服务器的算力和内存来实时处理用户访问。Astro的纯静态打包产物对服务器物理性能几乎零要求。构建出来的最终文件可以直接托管到各类免费CDN或极低配置的轻量节点上。这对预算有限的独立开发者来说是极其硬核的降本方案。 2.3 兼容性好 做前端技术选型通常意味着被特定生态彻底绑定。Astro完全打破了这个壁垒。在一个Astro页面内部可以同时无缝混用Vue和React编写的UI组件。 举个极其直白的例子. 假设你手里有一段用Vue写好的顶部导航栏代码.同时你又在网上找到了一段用React写好的留言板代码.在传统的开发环境里,这两种代码底层规则完全不同,是绝对没法放在同一个页面里运行的. 但是在Astro的网页文件里,你可以直接把它们拼在一起.网页的页头位置直接引用Vue的代码,网页的页脚位置直接引用React的代码.Astro底层会自动同时解析这两种不同的语法,把它们变成正常的网页内容.它们不仅能同时完美显示在屏幕上,各自的点击反馈功能也完全互不干扰. 这种底层兼容意味着,以后你在网上看到任何好用的开源组件代码.根本不需要管它是基于Vue还是React写的,直接复制搬进你的Astro项目里就能跑通. 底层编译器会自动处理这些跨技术栈代码的依赖隔离与加载。开发者可以毫无障碍地复用自己以前积累的任何代码资产。 2.4 对SEO的优化 依靠客户端脚本动态渲染内容的网页对搜索引擎爬虫极不友好。Astro输出的纯静态HTML让爬虫能瞬间抓取到页面的全部完整文本。(WordPress相比之下垃圾来的说是)它原生提供完善的元数据配置支持。这种物理层面的预渲染机制能显著拉升站点的搜索引擎收录速度和排名权重。 3、极简的数据获取与安全闭环 独立开发者往往需要快速跑通全栈业务。Astro天然契合前后端分离的开发思维。它可以在编译阶段直接发起请求去拉取远端数据库的内容并物理硬编码写入最终的网页文件。结合无头后端管理系统,开发者可以彻底分离数据维护和前端视觉呈现。这套架构不仅从物理层面隔绝了后端接口泄露的风险,也把前端页面的访问响应速度推到了极限。 也就是直接把所有的页面都爬取下来转化成HTML文件直接供人访问







