Yii 2.0.45虽无开箱即用的资源按需加载功能,但可通过defer/async控制JS、内联关键CSS+preload、预加载关联数据、CDN+压缩+版本化静态资源四方面优化首屏性能。

Yii 2.0.45 本身不提供“资源按需加载”的开箱即用功能,但完全可以通过组合原生 HTML 特性、框架机制和少量手动控制,实现 JS/CSS/关联数据的按需加载,显著减少首屏耗时。关键不是等框架支持,而是用对位置、时机和策略。
JS 脚本:用 defer/async 控制执行时机
非关键 JS(如统计、分享、客服插件)必须避免阻塞 HTML 解析和渲染。Yii 提供两种主流方式:
-
单个脚本注册时指定:调用
$this->registerJsFile()并显式设置'defer' => true或'async' => true,且'position'必须为View::POS_END,否则属性不会写入 script 标签; -
整包脚本统一配置:在自定义
AssetBundle中设置public $jsOptions = ['defer' => true],适用于页面专属逻辑+图表库等组合资源; -
注意依赖顺序:若你的 Bundle 依赖
JqueryAsset,而后者未设 defer,则 jQuery 仍同步加载——最终效果由依赖链中最“激进”的那个决定。
CSS 与图片:前端原生方案更直接
Yii 不干预 CSS 加载逻辑,优化靠标准 Web 手段:
- 关键 CSS 内联到
<head>,其余用<link rel="preload" as="style">或媒体查询(如media="print" onload="this.media='all'")实现异步加载; - 图片一律启用
loading="lazy"属性,浏览器原生支持视口内才加载,无需 JS 库; - 大图或背景图可配合 IntersectionObserver 手动触发加载,适合复杂交互场景。
数据库关联:别被“懒加载”误导
访问 $model->relation 看似延迟,实为“访问即查”,循环中反复触发就是典型的 N+1。这不是按需,是失控:
- 列表页查用户 + 头像,必须用
User::find()->with('profile')->all()预加载; - 分页场景慎用
joinWith(),可能因 JOIN 导致主表记录重复,反而增加数据量; - 中间表(如 user_role)务必建复合索引
(user_id, role_id),否则 JOIN 性能比 N+1 更差。
静态资源部署:CDN + Gzip + 版本化
资源加载慢常源于传输而非框架:
- 所有
AssetBundle的$baseUrl指向 CDN 域名(如https://cdn.example.com),让静态文件就近分发; - 确保 Web 服务器开启 Gzip/Brotli 压缩,PHP 层无需额外处理;
- 启用 AssetBundle 的
$publishOptions['forceCopy'] = false和YII_ENV_PROD下的资源合并压缩(需配合yii\bootstrap\BootstrapAsset等规范写法); - 资源 URL 后自动追加时间戳或哈希(通过
AssetManager::appendTimestamp),避免缓存 stale 问题。
不复杂但容易忽略:真正拖慢页面的,往往不是 Yii 本身,而是没管住 JS 执行时机、图片全量加载、以及把“访问才查”当成“按需加载”。从这四点下手,2.0.45 完全能跑出接近现代框架的首屏速度。


















