yii2项目实战-资源包管理

资源包管理是个啥东东呢,可能一听上去有些蒙,没听过没见过。

其实这个资源包才是经常跟大家伙打交道的主儿,你真应该静下心来学一学。为什么这么说呢?因为平时我们管理静态资源文件比如css,js都得靠它。

更常见的是 yii2 内部很多小物件也都是利用他对资源进行管理。我们后面也准备自己手动写一个上传的小物件,所以在开始本章之前,你先要认识到我们这节要说的知识的重要性。很重要哈,为此我们也会说的很详细,看完后若是有任何问题或者想要点赞的,最下面随便哈。

正如我刚刚所说,这里所谓的资源指的就是静态文件css和js。你可能会疑惑:我更喜欢直接通过script标签和link标签引入js和css,有必要学这个吗?

我们使用yii框架无非也是便于实际开发,你php都会干啥还用yii呢?对吧,一个道理。

我们通过程序自动管理资源包的好处,也是为了避免引入各种css,js,对于一些复杂的js可能还要手动去解决各种依赖,再或者我们要升级一些资源文件,难不成你还要一个一个的找,然后再去替换?甚是麻烦!

啰哩啰唆又双叒叕那么多,我们小碎步快速步入正题。

还要再啰嗦两句(一般上课前你们不都是喜欢哪些啰嗦的老师嘛),资源包是个啥东西我们目前只有一个模糊的印象,可眼见为实心里有个谱总是好的。

资源包就是一个类,一个包含着我们要发布的css和js以及一些依赖包的类,当然他还有一个英文名:Asset Bundles。我们来看一个简单的资源包的定义(其实yii自带的我们一开始就在使用了)。

打开backend\assets目录,找到AppAssets类,我们在该类原有的基础之上补充了几个属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

namespace backend\assets;

use yii\web\AssetBundle;

/**
* Main backend application asset bundle.
*/
class AppAsset extends AssetBundle
{
// public $sourcePath = '@common/widgets/upload';
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}
```

我们先来分析下上面的各项都是什么意思,然后再看看怎么使用这个资源包(就是上面这个类)。

1、定义的资源包要继承 yii\web\AssetBundle 类

2、我们先解释下资源发布的概念:就是把我们资源包所定义的资源,拷贝一份到web可访问的目录中,也就是默认的@web/assets目录,即backend/web/assets目录

3、关于basePath和baseUrl属性:当我们要发布的资源位于web可访问的目录,比如backend/web/css/site.css,你需要设置basePath指向该目录且需要设置baseUrl。basePath属性表示我们要发布的资源所在的物理路径,baseUrl表示该资源文件可被web访问的URL,如上配置

4、下面解释下sourcePath的含义:这个属性需要跟basePath和baseUrl区分开,有很多人傻傻分不清楚。假设我们有一个资源位于common/widgets/upload目录,如common/widgets/upload/css/site.css,这个时候我们就需要设置sourcePath属性了,该属性表示资源所在的根目录,自动发布资源的时候会把该文件拷贝一份到默认的web可访问目录@web/assets,当然该目录可配置。有些新人可能会比较好奇,我为啥要把资源放到common/widgets/upload目录,这是因为一些widget往往需要你定义资源才能更好的“工作”,后面我们定义一个图片上传的widget你就明白啦,这里先把疑问暂存一下

来,我们找两个例子练练,顺便把如何定义好的资源发布出去也给说说。

练习一:如何在blog的index视图中发布@web/css/site_test.css资源?

1、在backend\web\css目录下定义一个site_test.css资源,我们写点简单的内容,如下

1
body {}

2、在backend\assets目录下定义一个资源包TestAsset,因为发布的资源本身就在web可访问目录,所以我们需要定义basePath和baseUrl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

namespace backend\assets;

use yii\web\AssetBundle;

/**
* Test asset bundle.
*/
class TestAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site_test.css',
];
}

3、资源包定义好了,我们看看怎么发布吧

打开backend/views/blog/index.php,我们在这个视图文件内调用一个资源包的register方法即可

1
backend\assets\TestAsset::register($this);

4、最后我们访问下/blog/index,右键查看源代码我们发现页面上果真引入了我们刚发布的css资源

1
<link href="/css/site_test.css">

同理,如果我们要发布一个非web可访问目录下的资源,是不是只需要设置sourcePath属性就好啦?同时记得不要再设置basePath和baseUrl属性了。

练习完后我们回来看看资源包的依赖问题。

假设我们有一个js脚本要发布,但是该脚本依赖jquery,也就是说如果没有jquery,我们这个脚本就无法正常执行,这就是我们说的资源包的依赖问题。

解决依赖问题,就要设置 yii\web\AssetBundle 的 depends 属性,即在发布我们要发布的资源之前,先把其要依赖的其他文件包含进来,这样就解决依赖问题了。

我们还以TestAsset为例,我们假设@web/js/test.js 依赖 jqury3.1 且该文件在 bootCdn 上。

我们先定义一个资源包,用于发布 jquery 3.1 这个js脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

namespace backend\assets;

use yii\web\AssetBundle;

/**
* Test2 asset bundle.
*/
class Test2Asset extends AssetBundle
{
public $js = [
'//cdn.bootcss.com/jquery/3.1.1/jquery.js'
];
}

随后,我们在 TestAsset 资源包上进行补充,引入test.js资源并指定当前资源包依赖 Test2Asset 资源包

1
2
3
4
5
6
7
public $js = [
'js/test.js'
];

public $depends = [
'backend\assets\Test2Asset'
];

最后我们在blog/index中发布TestAsset资源包,右键源码查看文件便可以很清晰的看见 jquery3.1 确实在 test.js 之前发布了,这就很好的帮我们解决掉依赖的问题了。

1
2
<script src="//cdn.bootcss.com/jquery/3.1.1/jquery.js"></script>
<script src="/js/test.js"></script>

有一个非常值得一提的问题我补充一下:按照刚刚发布的资源文件 site_test.css 来看,因为其本身就处于web可访问目录,所以发布过程中并没有源文件到@web/assets(linux上需要保证该目录可写)目录的拷贝,因为此时拷贝并没有太大的意义了。

但是对于非web目录的资源文件(比如我们目前采用的这套adminlte的css文件)来说,其源文件是 @vendor/almasaeed2010/adminlte/dist/css/AdminLTE.min.css,但是对于我们的应用来说,其引用的就是源文件拷贝到@web/assets/xxx/css/AdminLTE.min.css之后的文件。

无论是直接引用的源文件还是引用拷贝后的文件(@web/assets目录下的文件),都会面临一个问题:客户端缓存造成请求到的资源文件还是修改之前的内容。此时需要我们手动删除浏览器缓存,重新发起新的请求。

很繁琐对不对?这不太像强大的yii2会做的事。

我们希望,在修改了资源文件之后,客户端的资源文件会重新请求服务器,而不是去缓存里获取。通常,我们可以在资源文件后添加参数来区分资源文件的版本。在yii2中,也可以这么干。

1
2
3
'assetManager' => [
'appendTimestamp' => true,
],

你只需要简单的在components配置一下assetManager组件的appendTimestamp即可。

此时我们刷新下页面再看一下实际加载的资源文件

1
2
<link href="/css/site_test.css?v=1490953009">
<script src="/js/test.js?v=1502457674"></script>

配置appendTimestamp为true后,资源包会自动在文件后添加v,以示区分其版本,v的值是对应资源文件最新的更新时间。