“中国要复兴、富强,必须在开源软件领域起到主导作用,为了国家安全和人类发展,责无旁贷,我们须为此而奋斗”——By:云客
drupal使用渲染占位符机制的目的是为了提高系统性能,具体来讲就是提高缓存利用率和效率
具体解决以下问题:
1:有时候页面是一模一样的,仅仅某一元素不一样,比如一个页面仅显示的用户名不一样,如果有一万的用户岂不是要在缓存中保存一万份?这是不划算的,也不合理,这种现象叫做上下文基数过大
2:有些内容变化频率特别快,几秒钟就变化,甚至更短,这个时候缓存的成本相对就大,使用缓存不划算,可以将变化频率特别快的部分独立出来,不进行缓存
3:有些内容很快就过期,缓存没什么价值,还会浪费缓存执行成本,可以将这部分内容独立出来不进行缓存
综上所述三条,你会发现他们就对应缓存三要素:上下文、标签、时间,由于这些原因导致缓存不划算花费过大
所以设置占位符机制,将这些缓存不划算的内容分割出来,在原来的地方设置一个占位符,然后仅缓存划算的内容,渲染时从缓存取出数据后再根据占位符信息才将缓存不划算的内容渲染后最终替换回去
可以看出渲染数组的占位符机制是非常有用的,本质上讲是将高动态、高基数的内容(使用缓存不划算的内容)延迟渲染,改善缓存性能。
判断页面某部分是否缓存划算从而运用占位符的过程叫做“Auto-placeholdering”(自动占位过程),它是怎么自动的呢?就得依据渲染配置
容器参数中的renderer.config就是此配置,默认值如下:
[renderer.config] => Array
(
[required_cache_contexts] => Array
(
[0] => languages:language_interface
[1] => theme
[2] => user.permissions
)
[auto_placeholder_conditions] => Array
(
[max-age] => 0
[contexts] => Array
(
[0] => session
[1] => user
)
[tags] => Array
(
)
)
可以看到在auto_placeholder_conditions中可以肯定会引起缓存不划算的项目均被指定为默认配置了,这些将进行占位符替换
要配置更多的内容就要依据站点的实际情况,这也是站点优化的一个重要内容。
这个默认值是在core.services.yml中指定的,用户可以在\sites\default\services.yml中自定义,它会覆盖核心提供的配置
下面来看看drupal具体是怎么实现占位符机制的:
要使用占位符机制的内容都是缓存不划算的,在正常的渲染流程中将对这部分内容的渲染独立出来,在最后进行
为此系统给渲染数组定义了一个叫做延迟构建的键名:$elements['#lazy_builder'],它的值是一个只有两个元素的数组
第一个元素表示回调,第二个元素表示回调的参数,参数被限制为仅标量数据类型或NULL
要进行占位符机制渲染的内容必须设置延迟构建,使用回调产生内容
设置了延迟构建的渲染数组表示该渲染数组的所有内容均由延迟构建回调产生,没有过多的属性也没有子元素
换句话说就是该渲染数组不允许有'#lazy_builder','#cache','#create_placeholder'之外的元素存在
当对这样的渲染数组进行渲染时系统判断它能不能和该不该产生占位符,如果可以则跳过渲染,并在父渲染数组中产生一个占位符(相当于暂时返回一个占位符作为渲染结果markup)
判断和产生占位符的工作是由渲染占位符产生器实现的,它在容器中的服务id为render_placeholder_generator
类实现:Drupal\Core\Render\PlaceholderGenerator 它实现了接口:Drupal\Core\Render\PlaceholderGeneratorInterface
该接口很简单,只有三个方法,分别对应于能不能(系统能否创建)、该不该(根据渲染配置判断是否应该创建)、创建占位符(负责具体创建工作)
来看一下渲染占位符产生器的具体实现:
代码位于:Drupal\Core\Render\PlaceholderGenerator(注:在本系列后续文章中均使用名字空间指代代码位置,看到这里读者应可以通过类加载器知道文件位置)
canCreatePlaceholder方法:要创建占位符必须要存在延迟构建#lazy_builder,以及#create_placeholder不为false或不设置
shouldAutomaticallyPlaceholder方法:依据渲染配置来判断是否应该运用占位符机制
createPlaceholder方法:可以看到回调参数是一个字符串格式,返回的占位渲染数组只包含:#lazy_builder、#cache、#markup、#attached,其中#markup包含的内容就是占位符,可以看到调试信息
总结注意:
占位内容由回调产生,所以运用占位符机制时,#lazy_builder必须存在
设置#lazy_builder时如果存在#create_placeholder其值为false,将不会产生占位符,而是直接渲染,这常用于根渲染
#lazy_builder指定的回调返回的渲染数组将在另外一个渲染上下文中渲染,它的子元素可以是任意的,如果是值得进行缓存的内容将会被缓存,这归功于渲染的自我递归调用实现
最终返回的渲染页面会合并所有的缓存属性数据,包括占位渲染数组的数据,这些数据会被drupal的动态缓存模块用到
反馈互动