HarmonyOS 包体积优化实战:从 HAP 变大到资源账本、模块拆分和构建守门
HarmonyOS 包体积优化实战从 HAP 变大到资源账本、模块拆分和构建守门很多 HarmonyOS 项目的包体积不是突然失控的。它通常是这样慢慢长大的一次需求加了几张高清引导图下一次活动页带进一批静态 JSON再后来某个小功能引入了一个大依赖。等到临近上架团队才发现 HAP 明显变重下载、安装和审核材料都变得被动。包体积优化不能只靠最后一天“删几张图”。更稳的做法是把包体积当成工程资产来管理先知道大在哪里再区分资源、代码、依赖和模块产物最后把检查动作放进构建和发版流程里。这篇文章围绕一个具体目标展开让一个 Stage 模型 HarmonyOS 工程具备可复盘的包体积治理流程。你可以直接照着做四件事建立资源账本知道图片、字体、JSON、rawfile 分别占了多少。给新增资源和依赖加 owner避免“谁都不知道是谁加的”。按 HAP、HAR、HSP 的边界判断哪些能力适合拆出去。在构建阶段生成体积报告发现异常增长时提前拦住。一、先定边界本文优化的是安装包体积不是运行内存包体积优化和运行性能优化容易混在一起。图片压缩可以同时影响包体积和运行内存但两者的分析入口不同。维度本文关注暂不展开安装包大小HAP、APP、资源、依赖、模块产物运行时内存峰值工程结构HAP、HAR、HSP、AppScope 资源页面渲染帧率构建检查构建产物扫描、体积差异报告后端接口耗时发版风险上架前包体积异常增长页面启动链路优化HarmonyOS 应用包结构里HAP 是应用安装和运行的基本单元HAR 常用于静态共享代码和资源HSP 是动态共享包可以在模块间共享代码和资源。体积治理时要先弄清楚资源最终进了哪个产物而不是只盯着工程目录。本文示例面向 HarmonyOS NEXT / Stage 模型 / ArkTS 工程。不同项目的 DevEco Studio、SDK、API 版本可能不同落地时以你本地构建产物为准。二、先跑一次基线没有基线就没有优化不要一上来删资源。第一步应该先生成一个“优化前基线”记录当前包体积分布。建议记录下面这些数据项目示例用途构建模式releasedebug 产物通常不能代表真实发布大小HAP 大小42.6 MB判断主包是否超预期图片资源大小18.2 MB判断是否图片过重rawfile 大小6.4 MB排查静态 JSON、模型、音频等资源三方依赖大小8.1 MB判断小功能是否引入大库最近版本对比4.7 MB发现异常增长来源如果团队没有历史报告可以从当前版本开始补。哪怕第一版只有总大小也比完全没有基线好。包体积治理最怕的是“感觉这次好像变大了”而不是“这次比上次大了 4.7 MB其中图片多了 3.1 MB”。三、资料与工程位置体积问题通常藏在这几类目录里实际排查时优先看下面几个位置位置常见问题排查重点AppScope/resources全局资源被所有模块打包使用是否放了只属于某个页面的图entry/src/main/resources图片、字体、rawfile 过大是否有未使用资源或重复资源feature_x/src/main/resources功能模块资源随模块进入产物是否应该做按需模块oh-package.json5依赖不断增加是否存在无 owner 的大依赖hvigorfile.ts构建没有体积检查是否能输出报告并比较阈值一个常见误区是只看resources/base/media。很多项目真正变大的地方反而是rawfile临时 JSON、离线包、测试数据、模型文件、音频文件都可能被放进去。只要它进入构建产物就会影响包体积。四、资源账本先把“谁占空间”说清楚下面这段脚本用于扫描资源目录按类型统计大小。它不是替代官方构建工具而是给团队一个可读的账本。importfsfromfs;importpathfrompath;typeResourceTypeimage|font|json|audio|raw|other;interfaceResourceSizeItem{filePath:string;type:ResourceType;sizeKb:number;}constimageExtnewSet([.png,.jpg,.jpeg,.webp,.svg]);constfontExtnewSet([.ttf,.otf]);constaudioExtnewSet([.mp3,.wav,.aac]);functiondetectType(filePath:string):ResourceType{constextpath.extname(filePath).toLowerCase();if(imageExt.has(ext)){returnimage;}if(fontExt.has(ext)){returnfont;}if(audioExt.has(ext)){returnaudio;}if(ext.json){returnjson;}if(filePath.includes(${path.sep}rawfile${path.sep})){returnraw;}returnother;}functionscanResources(rootDir:string):ResourceSizeItem[]{constresult:ResourceSizeItem[][];functionwalk(current:string):void{constentriesfs.readdirSync(current,{withFileTypes:true});for(constentryofentries){constfullPathpath.join(current,entry.name);if(entry.isDirectory()){walk(fullPath);continue;}conststatfs.statSync(fullPath);result.push({filePath:fullPath,type:detectType(fullPath),sizeKb:Number((stat.size/1024).toFixed(2))});}}walk(rootDir);returnresult;}这段代码的边界很清楚它只扫描资源文件不判断运行时是否真的使用。detectType()先按扩展名归类再单独识别rawfile。扫描结果可以用于生成报告也可以接到 CI 中做阈值检查。如果你的项目里还有模型文件、地图包、离线数据包可以继续扩展ResourceType。有了账本之后再决定压缩、删除或拆分。不要在不知道体积分布的情况下凭感觉删文件。五、生成报告让体积变化能被复盘资源扫描结果需要汇总成报告。报告不需要很复杂但必须能回答三个问题本次总大小是多少、最大资源是哪几类、和上一次相比增长了多少。interfacePackageSizeSummary{version:string;totalKb:number;imageKb:number;fontKb:number;jsonKb:number;audioKb:number;rawKb:number;otherKb:number;topFiles:ResourceSizeItem[];}functionbuildSummary(version:string,items:ResourceSizeItem[]):PackageSizeSummary{constsummary:PackageSizeSummary{version,totalKb:0,imageKb:0,fontKb:0,jsonKb:0,audioKb:0,rawKb:0,otherKb:0,topFiles:[]};for(constitemofitems){summary.totalKbitem.sizeKb;if(item.typeimage){summary.imageKbitem.sizeKb;}elseif(item.typefont){summary.fontKbitem.sizeKb;}elseif(item.typejson){summary.jsonKbitem.sizeKb;}elseif(item.typeaudio){summary.audioKbitem.sizeKb;}elseif(item.typeraw){summary.rawKbitem.sizeKb;}else{summary.otherKbitem.sizeKb;}}summary.topFiles[...items].sort((a,b)b.sizeKb-a.sizeKb).slice(0,20);returnsummary;}代码解释PackageSizeSummary不是构建产物格式而是团队内部的体积账本。topFiles保留前 20 个大文件方便评审时直接定位。报告按版本保存才能比较“这次为什么变大”。如果后续接入 HAP 解包扫描可以把 HAP 内部文件也喂给同一个汇总函数。建议把报告保存为package-size-report.json并在发版记录里保留一份。下一次体积反弹时不需要靠记忆排查。六、图片资源按展示场景准备不要把原图塞进包里图片通常是包体积增长最快的来源。尤其是启动页、引导页、活动页、空状态图很容易把设计源图直接放进工程。治理图片时先按展示场景分层场景建议不建议小图标使用合适尺寸或矢量资源放 2K 位图列表缩略图按卡片实际显示尺寸准备用详情页大图复用启动/引导图控制分辨率和数量多套未使用引导图同时保留活动页素材活动结束后及时清理长期留在正式资源目录可以给图片压缩策略写一个计划生成函数interfaceImageCompressPlan{source:string;displayWidthVp:number;displayHeightVp:number;targetWidthPx:number;targetHeightPx:number;quality:number;}functioncreateImagePlan(source:string,widthVp:number,heightVp:number):ImageCompressPlan{constscale3;consttargetWidthPxMath.ceil(widthVp*scale);consttargetHeightPxMath.ceil(heightVp*scale);return{source,displayWidthVp:widthVp,displayHeightVp:heightVp,targetWidthPx,targetHeightPx,quality:targetWidthPx1200?82:88};}这段代码表达的是策略不是强制所有项目都按 3 倍图处理。你可以根据目标设备、设计规范和视觉验收调整scale。重点是图片进入工程前要知道它服务于哪个展示尺寸而不是把设计原图直接打包。七、rawfile 和 JSON测试数据最容易混进正式包很多团队体积异常增长不是因为图片而是因为rawfile里混入了测试资源。例如mock 接口响应 JSON。临时调试日志。离线地图包或模型文件。设计标注图和验收截图。活动页下线后遗留的配置文件。可以建立一个发布白名单只允许明确声明用途的 rawfile 进入正式包interfaceRawFileRule{path:string;owner:string;reason:string;allowRelease:boolean;}functionfindReleaseRiskRawFiles(rules:RawFileRule[]):RawFileRule[]{returnrules.filter((item){constmissingOwneritem.owner.trim().length0;constmissingReasonitem.reason.trim().length0;returnitem.allowRelease(missingOwner||missingReason);});}这段代码防的不是技术错误而是流程漏洞owner为空时后续没人负责解释这个文件为什么存在。reason为空时评审无法判断它是否应该进正式包。allowRelease明确区分调试资源和发布资源。这类规则适合放在发版检查里而不是靠人工记忆。如果你的项目里有离线资源建议再加一列expireVersion活动结束或版本过期后自动提示清理。八、模块拆分不是所有能力都应该塞进 entry包体积优化不是简单拆模块。拆错了会让启动链路更复杂甚至引入新的加载问题。判断一个能力是否适合从主 HAP 中拆出去至少看三个条件判断点适合拆分不适合拆分是否首屏必需否是是否高频使用低频高频是否资源重图片、模型、离线包较多代码和资源都很轻下面是一个模块评估模型interfaceFeatureModuleSize{name:string;requiredAtStartup:boolean;monthlyUsagePercent:number;resourceKb:number;dependencyKb:number;}functionsuggestSplitModules(modules:FeatureModuleSize[]):FeatureModuleSize[]{returnmodules.filter((module){constnotStartupRequired!module.requiredAtStartup;constlowFrequencymodule.monthlyUsagePercent20;constheavyEnoughmodule.resourceKbmodule.dependencyKb1024;returnnotStartupRequiredlowFrequencyheavyEnough;});}代码解释requiredAtStartup保护启动主路径避免把启动必需能力拆走。monthlyUsagePercent用来衡量功能频率不能只凭产品印象。resourceKb dependencyKb表示拆分收益太小的模块不值得增加复杂度。这个函数只给建议真正拆分还要看业务路由、权限、测试覆盖和上架策略。HarmonyOS 工程中HAR 和 HSP 的使用边界要结合官方程序包结构理解。HAR 是静态共享包常用于共享代码和资源HSP 是动态共享包适合共享能力和资源。不要为了“看起来模块化”盲目拆分。九、依赖治理小功能引大库是体积杀手依赖问题很隐蔽因为它通常不会出现在页面代码里。一个看似很小的功能可能引入一套大库、Native 产物或重复资源。建议在oh-package.json5旁边维护一份依赖登记表interfaceDependencyRecord{name:string;version:string;owner:string;reason:string;removable:boolean;sizeKb:number;}functionfindSuspiciousDependencies(records:DependencyRecord[]):DependencyRecord[]{returnrecords.filter((item){constnoReasonitem.reason.trim().length0;constnoOwneritem.owner.trim().length0;constlargeDependencyitem.sizeKb500;returnlargeDependency(noReason||noOwner||item.removable);});}这段代码关注三个风险大依赖没有引入理由。大依赖没有 owner。依赖已经可移除但仍留在工程里。依赖治理不要只在发版前做。最好在代码评审时就要求说明为什么需要这个依赖、是否有轻量替代、是否只在某个可选模块使用。十、构建守门让异常增长提前暴露体积报告真正有用是因为它可以和上一版比较。下面的比较函数可以作为 CI 守门逻辑的核心。interfaceSizeDiffWarning{level:info|warning|block;message:string;}functioncomparePackageSize(previous:PackageSizeSummary,current:PackageSizeSummary):SizeDiffWarning[]{constwarnings:SizeDiffWarning[][];constdiffKbcurrent.totalKb-previous.totalKb;if(diffKb2048){warnings.push({level:block,message:本次资源体积增长${diffKb.toFixed(2)}KB超过 2MB需要说明原因});}elseif(diffKb1024){warnings.push({level:warning,message:本次资源体积增长${diffKb.toFixed(2)}KB建议复查新增资源});}if(current.imageKb-previous.imageKb1024){warnings.push({level:warning,message:图片资源增长超过 1MB请检查新增引导图、活动图和空状态图});}returnwarnings;}阈值不要照抄。工具类应用、内容型应用、离线资源型应用的包体积策略不一样。建议从宽松阈值开始例如单版本增长超过 2MB 必须说明原因等团队习惯稳定后再逐步收紧。十一、落地到工程一套可执行的检查命令可以把扫描脚本放在tools/package-size并给它一个固定入口tools/package-size/ ├── scan-resources.ts ├── build-summary.ts ├── compare-report.ts └── package-size-baseline.json本地执行流程可以这样设计hvigor assembleHap--modereleasenodetools/package-size/scan-resources.js ./entry/src/main/resources ./reports/package-size-current.jsonnodetools/package-size/compare-report.js ./reports/package-size-baseline.json ./reports/package-size-current.json如果你使用的是 DevEco Studio 图形界面构建也可以先手动构建 HAP再运行扫描脚本。关键不在于命令完全一致而在于每次发版都能生成同一种格式的报告。十二、常见问题排查按增长来源找不要全工程乱翻现象优先怀疑检查方法修复方向HAP 突然增加几 MB新增图片、rawfile 或依赖比较两版 topFiles删除未使用资源或压缩大图图片压缩后变糊压缩策略不分场景对比实际显示尺寸图标、照片、引导图分策略活动结束后包体积没降活动资源未清理查活动目录和 rawfile加资源过期版本拆模块后启动失败主路径依赖被拆走检查启动页依赖链启动必需能力留在主模块依赖越来越多没有 owner 和引入理由检查依赖登记表无理由大依赖进入评审发版前才发现异常构建阶段没有对比报告查 CI 或发版清单加体积报告和阈值提醒排查顺序建议固定先看版本差异再看资源分类最后看模块和依赖。不要一上来全工程搜索“哪个文件大”那样效率很低也容易误删业务仍在使用的资源。十三、发布前验收清单合入或发版前至少确认下面这些项检查项通过标准有优化前后报告能看到总大小和分类大小变化topFiles 已复查前 20 个大文件都有用途说明rawfile 已清理mock、临时截图、调试 JSON 没进正式包图片按场景处理图标、照片、引导图没有使用同一压缩策略大依赖有 owner每个大依赖都有引入理由和负责人可选模块已评估非首屏、低频、大资源能力有拆分结论构建守门已执行单版本异常增长会被提示或阻断验收清单的目的不是增加流程负担而是防止问题拖到上架前爆雷。包体积越早被看见修复成本越低。十四、给团队的推进节奏如果项目已经比较大不建议一次性做彻底重构。可以按三周推进周期目标产出第 1 周建账本资源扫描脚本、当前版本报告第 2 周清高收益资源大图、rawfile、过期活动资源清理记录第 3 周上构建守门基线报告、增长阈值、发版检查项这个节奏比较适合真实团队第一周先建立可见性第二周处理最明显收益第三周把流程固定住。只要流程固定后面的优化就不会变成一次性的“清仓大扫除”。十五、本文参考的官方资料华为开发者文档应用包体积优化https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-decrease_pakage_size华为开发者文档应用程序包基础知识https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-package-overview华为开发者文档应用程序包结构https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/application-package-structure-stage华为开发者文档HARhttps://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/har-package华为开发者文档打包工具https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/packing-tool十六、最后把包体积变成日常工程指标HarmonyOS 包体积优化的关键不是最后一天临时删文件而是建立一套能持续复盘的工程机制。先用资源账本看清楚体积来源再按图片、rawfile、依赖、模块拆分逐层治理最后把报告和阈值放进构建流程。这样每一次体积增长都有原因每一次优化都有记录包体积就不会失控到上架前才被发现。最后可以用这张表判断团队是否已经进入稳定状态判断问题稳定状态这次版本为什么变大能从报告里说出增长来源哪些资源可以删topFiles 和 rawfile 清单里有结论大依赖是谁引入的依赖登记表里有 owner 和理由下次还会不会反弹CI 或发版检查会提示异常增长新人接手能不能继续维护账本、阈值、验收清单都有文档如果这五个问题都能回答包体积治理就不再依赖某一个人的经验而是变成团队日常工程质量的一部分。

相关新闻

双目拼接中色差消除优化

双目拼接中色差消除优化

一、问题根源解析1. YUV(NV12/YUYV)微小 UV 值失效的核心原因YUV 中 U/V 量化是整数 8bit(0~255),中性灰中心点严格为 127,量化步长 1。差值仅为 2(U:127 vs 125)&#…

2026/7/19 14:29:01阅读更多 →
Wand-Enhancer终极指南:免费解锁Wand专业版功能完整方案

Wand-Enhancer终极指南:免费解锁Wand专业版功能完整方案

Wand-Enhancer终极指南:免费解锁Wand专业版功能完整方案 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 还在为Wand(原WeMo…

2026/7/19 14:29:01阅读更多 →
iOS导航栏透明化与毛玻璃效果:GKNavigationBarViewController最佳实践

iOS导航栏透明化与毛玻璃效果:GKNavigationBarViewController最佳实践

iOS导航栏透明化与毛玻璃效果:GKNavigationBarViewController最佳实践 【免费下载链接】GKNavigationBarViewController iOS自定义导航栏-导航栏联动 项目地址: https://gitcode.com/gh_mirrors/gk/GKNavigationBarViewController GKNavigationBarViewContro…

2026/7/19 14:29:01阅读更多 →
嵌入式SDRAM控制器:内存防火墙与旋转引擎的深度解析

嵌入式SDRAM控制器:内存防火墙与旋转引擎的深度解析

1. 项目概述:深入嵌入式系统的“内存交通枢纽” 在智能手机、平板电脑这类我们每天都会接触的嵌入式设备里,处理器(CPU/GPU)和外部内存(SDRAM)之间的数据交换,就像一座繁忙城市的交通。处理器是…

2026/7/19 22:04:47阅读更多 →
多模态自主智能体与树搜索:让AI真正‘看懂’并操作网页

多模态自主智能体与树搜索:让AI真正‘看懂’并操作网页

1. 项目概述:当AI开始“看懂”网页并自主决策你有没有过这种体验:在电商网站上比价,翻了五页才找到想要的型号;在政府服务页面里反复点击“下一步”,却总卡在某个没说明白的字段;或者帮长辈填一份医保申请表…

2026/7/19 22:04:47阅读更多 →
Node.js核心特性与五大应用场景解析

Node.js核心特性与五大应用场景解析

1. Node.js的核心定位与适用场景Node.js本质上是一个基于Chrome V8引擎的JavaScript运行时环境,它让JavaScript突破了浏览器的限制,能够在服务器端运行。这种设计带来了几个关键特性:事件驱动架构:采用单线程事件循环模型&#xf…

2026/7/19 22:04:47阅读更多 →
Python核心模块分类与使用指南

Python核心模块分类与使用指南

1. Python常用模块全景概览作为一门通用编程语言,Python的强大之处很大程度上来自于其丰富的标准库和第三方模块生态。这些模块覆盖了从基础数据处理到人工智能开发的各个领域,让开发者能够快速构建功能完善的应用程序。在Python的实际开发中&#xff0c…

2026/7/19 22:02:46阅读更多 →
锂电池智能充电器使用指南:从原理到实践,避免常见误区

锂电池智能充电器使用指南:从原理到实践,避免常见误区

锂电池充电器,看似简单,但真正用好它,远不止“插上电、接上电池”这么简单。很多人第一次接触B4-BC4S或B4-800D这类带电压显示、支持即插即充的智能充电器时,往往会被其相对丰富的功能界面和偶尔出现的“ER”报错搞得有些不知所措…

2026/7/19 22:02:46阅读更多 →
Android工程师面试进阶:大厂核心考点与系统设计

Android工程师面试进阶:大厂核心考点与系统设计

1. 面试季突围:Android工程师的进阶指南又到了一年一度的"金三银四"招聘旺季,对于Android开发者来说,这既是机遇也是挑战。作为经历过多次大厂面试的过来人,我深知这个时期准备的重要性。2019年的Android技术栈已经发生…

2026/7/19 22:02:46阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/19 0:01:04阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/19 0:01:04阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/19 0:01:04阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/18 22:49:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/19 14:50:26阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/19 18:50:36阅读更多 →