Uniapp PWA首屏加载优化:预缓存、路由懒加载与资源压缩三板斧
1. 先别急着动代码弄清Uniapp PWA首屏加载的瓶颈在哪1.1 Uniapp H5端首屏加载到底加载了什么去年年中我把一个用Uniapp写的商城项目打包成H5应用顺手接上了PWA的manifest和Service Worker觉得既然能装到主屏体验应该没跑了。结果用户连续反馈首屏转圈我打开Chrome无痕窗口访问了一次Lighthouse的Performance得分只有三十多分连续好几个几百毫秒的长任务卡在主线程上。问题出在哪说白了就是首屏资源太重缓存策略又几乎等于没做。先说清楚Uniapp H5端是一个什么样的产物。它本质上就是一个标准的Vue SPApages.json里声明的页面会被编译成路由表App.vue和main.js负责拉起整个应用。打包后你会在dist目录里看到这些文件index.html入口、chunk-vendors.jsVue、Vue Router这类第三方库的集合、app.jsUniapp运行时加你的全局逻辑、若干页面chunk、还有一堆CSS、图片和字体。很多人有个错觉以为默认构建会把每个页面拆成独立文件不用管就是按需加载。但实际打开Network面板一看首屏往往要同时拉回一个体积不小的vendors文件。如果项目里又装了图表库、视频播放器、富文本编辑器这类重量级依赖chunk-vendors.js很容易膨胀到四五百KB甚至更多。这个文件在首屏就要被下载、解析、执行一套下来手机CPU已经被占掉一大截。需要注意资源的下载速度和解析速度是两回事。文件从服务器传过来就算gzip压缩到100KB浏览器还得把它还原成JavaScript源码然后分词、编译、执行。这个过程几乎不受网络带宽影响纯粹吃设备算力。低端安卓机上一个300KB的JS文件解析几十毫秒到上百毫秒是很正常的事。所以首屏优化不能只看传输体积还要看主线程到底执行了多少代码。这也是为什么后面路由懒加载的收益那么明显——它直接砍掉了首屏主线程的主要工作。1.2 为什么PWA场景下首屏慢比普通H5更扎眼普通H5页面其实有一种隐形的缓存优势用户第二次访问时浏览器会利用HTTP缓存把静态资源直接打到磁盘网络请求大量减少。但PWA从智能手机主屏上点开时很多浏览器会把它当成一个独立的App来冷启动如果Service Worker里什么缓存策略都没配这次冷启动和第一次访问几乎没有任何区别所有JS、CSS、图片都得重新从服务器拉一遍。更要命的是用户对PWA的预期不是网页而是App。一个装了美团、京东这类原生应用的人点开你的PWA却要等两三秒白屏他会马上关掉。弱网环境下更糟糕3G网络配合几百KB的JS首屏出图遥遥无期。所以PWA首屏优化的目标很明确把每次冷启动必须完成的工作量降到最低让从主屏点开图标到看到内容的时间尽量接近原生App。做到这一步靠的就是预缓存、路由懒加载和资源压缩这三个手段它们分别解决从哪取资源取多少资源资源有多大这三个核心问题。1.3 用哪些指标来量化现在的瓶颈动手改代码之前我强烈建议先把现状数据记录下来否则优化完连有没有变好都说不清。我一般会开Chrome DevTools的Lighthouse重点看Performance和Progressive Web App两个分类下的分数再切到Network面板按Transfer Size排序找出体积最大的几个请求最后在Performance面板里跑一次录制看主线程的长任务耗时和FCP、LCP出现的时间点。Lighthouse里FCP和LCP是最直观的首屏指标FCP意味着用户看到第一个像素LCP意味着主要内容出来了。Performance面板的Main Thread长任务如果超过200毫秒就会让用户感觉到卡顿这个数字通常比下载时间更能反映问题。把这些数据存到表格里做完每一板斧后跑一遍数字会告诉你哪一步真正有效哪一步只是心理安慰。2. 第一板斧预缓存——把App Shell腌进浏览器2.1 注册Service Worker的时机与前提Service Worker本质上是一个跑在浏览器后台的独立线程可以拦截页面的网络请求决定响应是来自缓存还是网络。预缓存就是在Service Worker安装阶段提前把首屏必需的静态资源写进CacheStorage。打个比方第一次访问时正常加载同时服务员把一桌菜提前腌好放进后厨柜子第二次你再进店不用等灶台起火直接上菜。在Uniapp项目里注册代码可以放在main.js里也可以放在App.vue的onLaunch生命周期中这两处都能保证应用启动时执行if (serviceWorker in navigator window.location.protocol.startsWith(http)) { window.addEventListener(load, () { navigator.serviceWorker.register(/sw.js, { scope: / }) .then(registration { console.log(SW registered, registration.scope); }) .catch(err console.warn(SW register failed, err)); }); }这里有两个前提要注意。第一PWA要求HTTPS环境本地调试时localhost除外如果部署到内网HTTP地址Service Worker注册会被浏览器直接拒绝别在这上面浪费排查时间。第二不要把注册逻辑写在开发环境里否则热更新和SW同时存在会互相打架。所以我一般会在外面套一层process.env.NODE_ENV production的判断只在生产构建里启用。2.2 预缓存清单怎么列预缓存最容易犯的错误是贪多恨不得把全站文件一次性都塞进缓存。但预缓存越多安装阶段写CacheStorage的时间越长反而拖慢了首次启动。PWA社区经典的App Shell模型值得照抄只缓存构成应用外壳的入口HTML、核心JS/CSS、manifest和图标让首屏骨架能秒开。页面内容和动态数据永远按需加载。手写一个sw.js骨架大致是这个样子const CACHE_VERSION app-shell-v1; // 改这个字符串来触发缓存更新 const PRECACHE_URLS [ /, /index.html, /manifest.json, /static/css/app.css, /static/js/chunk-vendors.js, /static/js/app.js, /static/icons/icon-192.png, /static/icons/icon-512.png ]; self.addEventListener(install, event { event.waitUntil( caches.open(CACHE_VERSION) .then(cache cache.addAll(PRECACHE_URLS)) .then(() self.skipWaiting()) ); }); self.addEventListener(activate, event { event.waitUntil( caches.keys() .then(keys Promise.all( keys.filter(key key ! CACHE_VERSION) .map(key caches.delete(key)) )) .then(() self.clients.claim()) ); });install阶段负责写入预缓存清单activate阶段负责把旧版本的缓存清掉。skipWaiting和clients.claim这两个方法很关键它们能让新SW尽快接管页面避免用户继续使用旧逻辑。PRECACHE_URLS里写死文件名有个隐患——构建产物的hash一变这个清单就失效了。这个问题我会在第5节专门展开先记住这里不是重点重点是App Shell的思路。2.3 运行时缓存策略别把所有请求一视同仁预缓存解决的是静态壳的问题运行时还有大量请求进来必须给它们分配不同的处理策略。如果对所有请求都无脑Cache First你会发现用户信息接口返回昨天的数据、订单列表永远不更新最后还得加班收拾烂摊子。按照资源类型来分一般是这样一张表资源类型推荐策略原因HTML入口Network First配合服务器304保证拿到最新入口文件避免旧入口引用不存在的chunk带hash的JS/CSSCache First 后台更新文件名一变自然重新拉取不存在旧内容问题图片/图标Stale-While-Revalidate缓存秒开后台偷偷更新保持新鲜API接口Network Only 或 Network First避免缓存到过期数据对应的fetch监听逻辑大概是这样的self.addEventListener(fetch, event { const url new URL(event.request.url); if (event.request.mode navigate) { event.respondWith( fetch(event.request).then(response { const clone response.clone(); caches.open(CACHE_VERSION).then(cache cache.put(/, clone)); return response; }).catch(() caches.match(/)) ); return; } if (event.request.method GET url.origin location.origin) { event.respondWith( caches.match(event.request).then(cached { const networkPromise fetch(event.request).then(response { if (response response.status 200) { const clone response.clone(); caches.open(CACHE_VERSION).then(cache cache.put(event.request, clone)); } return response; }).catch(() cached); return cached || networkPromise; }) ); } });页面导航用Network First很好理解用户每次点开App都要确保从服务器拿到最新的index.html。而带hash的JS/CSS用Cache First也安全因为文件名变了缓存自然命中不了新资源浏览器会去服务器拉新的。图片这类资源用Stale-While-Revalidate比较合适先返回旧缓存保证显示速度同时后台把新图片更新进缓存下次访问就是新的了。3. 第二板斧路由懒加载——首屏只买单页的账3.1 默认打包结果可能让你意外Uniapp编译到H5端很多人默认以为每个页面天然就是独立chunk按需加载肯定自动生效。我在不同版本的项目里观察到的结果其实不完全一致有的版本确实会按页面拆分有的版本则把大量逻辑合进app.js或把第三方依赖全部塞进chunk-vendors.js。与其听别人说不如你自己打开Network面板看一眼判断标准很简单首屏发起的请求里有没有出现其他页面的代码如果你打开首页却看到订单页、会员页的chunk也在加载那就是没拆干净。即便页面拆分生效了还有一个更隐蔽的坑vendors过度膨胀。比如你的项目里某个页面用到了图表库EChartsWebpack在默认配置下很可能把它归入公共依赖所有页面共享结果首屏为了可能用到的图表功能被迫加载一整套图表引擎。这种隐形的冗余比显式的合包更难受因为它藏得很深不仔细看根本发现不了。3.2 用subPackages把低频页面隔离出去Uniapp在原生小程序端很早就有分包的概念其实H5端同样可以利用。pages.json里的subPackages字段会被编译成路由级的按需加载模块只有访问到对应路径时才拉取该分包的JS。一个实际项目的配置长这样{ pages: [ { path: pages/index/index, style: { navigationBarTitleText: 首页 } }, { path: pages/detail/detail, style: { navigationBarTitleText: 详情 } } ], subPackages: [ { root: pages/order/, pages: [ { path: list, style: { navigationBarTitleText: 订单列表 } }, { path: confirm, style: { navigationBarTitleText: 确认订单 } } ] } ] }分包的原则是低频、重依赖的页面往里放比如订单列表、个人中心、设置页高频且轻量的页面留在主包。这样首屏只加载首页和详情页的资源其他页面等用户真正点进去再加载。配合前面说的预缓存用户跳转时会感觉这些分包页面几乎是瞬开的体验很接近原生。3.3 动态import与第三方库拆分如果某个页面必须留在主包里但它内部引用了大库那就把大库改成动态import让它在需要时才加载。比如图表库可以封装成一个异步加载函数async function loadChartLibrary() { const echarts await import(echarts); return echarts; }同时可以在vue.config.js里通过splitChunks把这类大库单独抽成异步chunk避免它和其他第三方依赖混进同一个vendors包里module.exports { chainWebpack: config { config.optimization.splitChunks({ chunks: all, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, name: vendors, priority: 10 }, chartLib: { test: /[\\/]node_modules[\\/]echarts[\\/]/, name: chart-lib, chunks: async, priority: 20 } } }); } };chunks: async意味着这个库只从异步加载的页面中去收集首屏同步引入的代码不会把它算进来。这样一来主bundle的体积被砍掉一大块图表页面打开时才会单独下载chart-lib chunk。整体记账方式就一句话首屏资源体积等于入口HTML加核心JS/CSS加首屏页面chunk加首屏真正用到的图片字体其他一切都必须延迟到需要时再加载。4. 第三板斧资源压缩——在字节层面抠出首屏时间4.1 JS/CSS压缩与Tree ShakingUniapp生产构建默认会压缩JS和CSS这一步通常不用额外配置。但压缩只解决传输体积真正浪费首屏性能的往往是被打包进去但从来没执行过的代码。Lighthouse的Unused JavaScript指标会告诉你答案如果首屏JS里有30%以上没有执行说明模块拆分不够细或者入口文件里引入了太多只用到一次的库。Tree Shaking是Webpack对ES Module静态分析的产物它能自动去掉没有引用的导出。所以平时写代码尽量统一用import和export少用require这种CommonJS写法后者会阻碍静态分析。另外别在App.vue的全局位置引入太多第三方库比如把axios挂在Vue.prototype上没问题但把一个完整的UI组件库全量引入到全局就会拖慢所有页面的首屏。按需引入组件库或者用动态import加载首屏不需要的组件都是更合理的方案。4.2 图片与字体最容易忽略的体积黑洞图片和字体的体积问题常常比JS还严重。设计稿里一张1920宽的全屏背景图可能超过1MB直接放在CSS里当背景首屏就会多出一整轮大请求。Uniapp的image组件有lazy-load属性但它只管滚动加载首屏大图依然要尽快出图。我的建议是首屏图优先转成WebP装饰性的图形尽量用SVG超过10KB的位图都过一遍压缩工具再放进去。字体同样是坑。中文网页如果引用一套完整字体文件动辄几MB而且很多项目的代码里只是偶尔用了几个特殊字符。把这些需求做字体子集化只保留实际用到的字形体积能降下来一个数量级。同时给字体规则加上font-display: swap让浏览器先用默认字体渲染文字字体文件加载完再做替换用户就不会看到大段空白文字。注意这个属性在部分浏览器上支持有限但它依旧是性价比很高的操作。4.3 服务端压缩和部署侧的配合前端资源压缩得再好到了服务器传输环节如果没开压缩等于白干。很多云厂商的CDN默认不开启gzip或者只针对HTML生效JS和CSS依然裸奔传输。可以手动在Nginx里加上这段配置gzip on; gzip_comp_level 6; gzip_min_length 1024; gzip_types text/plain text/css application/javascript application/json image/svgxml;gzip_min_length 1024的意思是小于1KB的文件不压避免浪费CPU却得不到明显收益。级别6是性价比比较高的档位再往上CPU消耗增加但体积缩减有限。如果服务器支持Brotli效果比gzip更好压缩率能再低10%到20%但Nginx需要额外编译对应模块。这里有一个容易被忽略的细节sw.js本身绝对不能被缓存。如果服务器给sw.js返回了带缓存头的响应浏览器拿到旧版Service Worker后续更新就永远不生效。Nginx里可以单独给它一个策略location /sw.js { add_header Cache-Control no-cache, no-store, must-revalidate; expires -1; }部署侧的配合还需要注意manifest.json里的start_url和scope必须和真实部署路径一致否则PWA安装后从主屏点开可能落到一个Service Worker管理不到的范围导致预缓存全部失明。这类问题症状很隐蔽但排查起来往往只需要看Network面板里SW是否接管了请求。5. 三板斧合体后的效果复盘以及我踩过的坑5.1 优化效果的复盘方式前面那张记录着FCP、LCP和主线程长任务的表格现在派上用场了。我手头那个商城项目优化前Lighthouse Performance大概35分FCP在4秒左右Network面板前几个请求明显是几百KB的JS。做完预缓存二次访问的FCP立刻降到1秒内因为App Shell已经从CacheStorage直接命中。再把路由懒加载落地后首次访问的主资源体积也瘦了一圈FCP大概进了1.5秒左右。最后加上图片压缩和gzip弱网下的体验差距很明显。不同项目的瓶颈不一样这些数字只能作为趋势参考不要照搬着给自己设定目标。唯一可靠的做法是盯着你自己的横向对比数据看每一步改动后FCP、LCP、请求数、传输体积哪一个发生了变化。如果某一步做完数字基本没动说明这个方向对你的项目不是主要矛盾及时调整别死磕。5.2 坑一预缓存旧HTML导致新版白屏这是我最先踩到、也最经典的坑。当我把index.html加入预缓存后二次访问直接命中旧缓存里的HTML里面的JS文件名还是上一个构建版本的hash而真正部署到服务器的新静态资源已经换了新hash。结果就是浏览器拿着旧入口去请求不存在的chunk加载失败白屏。虽然从缓存看是秒开但用户看到的是永远转不完的loading。解决办法有两个方向。要么对HTML使用Network First让它每次都先问服务器要最新入口拿不到再回退缓存要么在构建时通过Service Worker更新版本号配合旧缓存清理把旧入口一并清掉。我个人更推荐前者简单直接不至于引入新的更新时序问题。5.3 坑二误把接口缓存成静态资源第一次手写fetch策略时我图省事对同源GET请求一律Cache First结果没过多久就有用户反映订单页数据一直不更新。问题就出在订单列表接口也被缓存了而且Cache First策略下在缓存有效期内根本不会走到网络。后来我把所有以/api/开头的请求全部排除在缓存之外只在离线时才允许它们回退到缓存数据。如果你的业务需要真正的离线数据能力那应该给每个接口设计单独的缓存策略比如Network First加过期时间而不是一股脑套用静态资源的缓存逻辑。5.4 坑三sw.js更新不生效改完代码线上不更新Service Worker更新有一个很隐蔽的机制浏览器检查到新sw.js时会用新版本替换但默认要等所有页面全部关闭后新SW才会接管。如果不调用skipWaiting用户打开App时看到的永远是上一版逻辑你还以为是部署没生效。所以install事件里那句self.skipWaiting()非常关键配合activate阶段的self.clients.claim()才能让新SW立刻控制页面。同时记住服务器端sw.js务必no-cache否则浏览器压根不会去拿新版那就只能手动换sw.js路径来强制更新了。5.5 坑四预缓存清单写死文件名构建后对不上PRECACHE_URLS里写死文件名在单次构建里没问题但团队协作、版本迭代之后chunk的hash一变清单就要改。这个坑在每次发版时都会心累一次。比较省心的做法是构建后用脚本扫描dist目录自动生成预缓存清单。简单写一个Node脚本在package.json的build流程里串起来构建完成后遍历dist下所有带hash的静态文件生成一个sw-precache清单注入到sw.js里。门槛不高但一次配置长期受益比每天手动改文件名靠谱得多。最后说句实在话。三板斧不是魔法它帮你去掉的是那些完全可以避免的等待资源多拉了几百KB、逻辑多解析了几十毫秒、缓存没做导致每次都要回源。光做完预缓存二次访问就会明显快一截加上路由懒加载首次访问也会瘦一圈再配上压缩网络差的环境也能扳回一局。如果你的Uniapp PWA首屏还在被用户吐槽先从Network面板把体积排前几名的资源抓出来按照这个顺序一样样做效果基本不会让你失望。

相关新闻

UE架构实战:从UObject到GAS、多线程与数据驱动的工程取舍

UE架构实战:从UObject到GAS、多线程与数据驱动的工程取舍

聊到游戏引擎架构,前面几篇我们一直在拆通用概念:场景管理、组件模型、资源生命周期。到了第五篇,终于要落到 UE 实战了。很多人问过我一个问题:学了一堆架构理论,为什么一打开 UE 还是不知道该改哪里?我的…

2026/10/9 7:20:03 阅读更多 →
SpringBoot电影推荐系统:Java全栈工程能力实战指南

SpringBoot电影推荐系统:Java全栈工程能力实战指南

简介:这是一套面向计算机专业本科生的毕业设计级电影推荐系统实战项目,基于Java与SpringBoot框架开发,完整覆盖用户端推荐交互与管理员后台管理双模块,适用于课程设计、毕设选题及Java全栈能力进阶学习。资源包共813个文件&#x…

2026/10/9 7:20:03 阅读更多 →
hyperframes 帧调度实战:高密度数据可视化性能优化指南

hyperframes 帧调度实战:高密度数据可视化性能优化指南

1. 初识 hyperframes:它到底是什么,能解决什么问题第一次看到 hyperframes 这个词,很多人会以为是某个前端框架的新分支,或者是和 iframe 相关的某种嵌套方案。实际上,hyperframes 是一个面向高密度数据可视化与实时渲…

2026/10/9 7:20:03 阅读更多 →

最新新闻

给AI助手加持久记忆:基于SQLite的轻量级上下文记忆层设计实践

给AI助手加持久记忆:基于SQLite的轻量级上下文记忆层设计实践

每次新开一个会话,AI 就从"记得所有事的同事"退化成了"考场里刚拿到卷子的学霸"。昨天刚确认过的项目目录结构、已经调通的参数组合、反复讨论后定下的命名规则,今天必须从头解释一遍。这种"失忆循环"用一阵子真的会把手感…

2026/10/9 7:51:22 阅读更多 →
stm32mp157项目

stm32mp157项目

1.led点亮查询设备树中led的节点找到匹配的compatible属性根据compatible属性查找内核的led驱动代码查询到内核驱动代码为leds/leds-gpio.c阅读内核的led驱动代码发现,驱动只获取了gpio的属性信息,其控制led亮灭是靠gpio子系统来进行的查询内核的led设备…

2026/10/9 7:51:22 阅读更多 →
拆解玮创速擎(EnginePro):智能选型+3D建模+一键报价,制造企业的选型设计神器

拆解玮创速擎(EnginePro):智能选型+3D建模+一键报价,制造企业的选型设计神器

在制造业自动化输送设备、产线布局搭建中,选型设计往往不只是“画图报价”这么简单。产品参数多、配置复杂、客户需求个性化、价格变动灵活——传统的手动画图或人工Excel报价,有时会显得速度不够快、容易疏忽,甚至可能因为设备/产线模型不够…

2026/10/9 7:51:22 阅读更多 →
Python pip包管理从入门到精通:安装、虚拟环境与镜像源配置

Python pip包管理从入门到精通:安装、虚拟环境与镜像源配置

1. 为什么pip值得你花时间搞明白很多人第一次接触Python,卡住的地方根本不是语法,而是装不上包。你兴冲冲打开教程,照着敲下pip install requests,结果终端甩给你一句pip 不是内部或外部命令,或者更气人的是——装完了…

2026/10/9 7:51:22 阅读更多 →
职场拒绝同事的6大高情商技巧:如何礼貌说“不”而不伤和气

职场拒绝同事的6大高情商技巧:如何礼貌说“不”而不伤和气

周五傍晚六点半,同事端着水杯走到我工位旁边:“今晚能不能帮我把这份报表改一下?客户明天一早就要。”我盯着屏幕上的数据,脑子里疯狂喊着“别答应”,嘴上却说出了“好”。这种场景,我猜你也不陌生。拒绝别…

2026/10/9 7:51:22 阅读更多 →
SpiderDemo T5实战:动态接口与XPath解析全流程记录

SpiderDemo T5实战:动态接口与XPath解析全流程记录

SpiderDemo 是我最近一直在刷的一套爬虫练习网站,从最简单的静态页面抓取开始,一路做到第 5 期任务(T5)。这篇记录就想把 T5 的完整过程拆开来讲:从任务分析、页面结构定位、XPath 坑点,到最终的数据落盘和…

2026/10/9 7:50:21 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →