在Drupal8中,CSS和JS通过加载模块和主题的系统加载,组件库(asset libraries)。
Drupal用一个高级的原则:CSS/JS 只有在你告知Drupal加载时才被加载。Drupal不会在所有页面加载全部的CSS/JS,因为这样不利于前端性能。
与Drupal 7的不同
主要4点:
- 不再有THEME.info 文件,但是有包含相同内容的THEME.info.yml 文件
- Stylessheets属性不再存在于THEME.info.yml文件,因为现在只使用库了(stylesheets-override 和 stylesheets-remove 依然存在并和原来一样工作)
- Scripts 属性也不存在于THEME.info.yml文件,因为现在只使用库了
- 只有页面需要的JS会被加入到该页面。 因为,Drupal默认不需要给不登陆的用户分享大部分JS。这意味着jQuery不会自动被所有页面加载(link is external)。
- jQuery或其他JS(已经在组件库中定义了),你需要用“在需要的组件库声明需求”的方式告诉Drupal。
过程
通常步骤:
- 保存CSS/JS文件
- 定义一个包含CSS和JS文件的库
- 将这个库附到钩子函数中一个呈递的数组中
但是,在主题中,第三部有另一个方法,主题可以选择加载任意数量的组件库在所有的页面中
定义库
要定义一个库,往主题文件夹中加入 *.libraries.yml 文件。(如果你的主题名是fluffiness, 那么文件名应该是fluffiness.libraries.yml)每个库都是包含CSS/JS详细信息的一个目录,例如:
cuddly-slider: version: 1.x css: theme: css/cuddly-slider.css: {} js: js/cuddly-slider.js: {}
但是,记住Drupal8不再默认对所有页面加载jQuery,只是在需要的时候加载。 因此,我们必须声明我们主题的cuddly-slider库声明了对包含jQuery的库的需求。这不是一个模块或主题分享jQuery,而是 Drupal的核心core/jQuery是我们需要声明的需求。(这是一个跟着/和库名的扩展命名,所以,如果有其他库想依赖我们cuddly- slider这个库,它必须要声明对fluffiness/cuddly-slider的需求。因为fluffiness是我们的主题名)这个例子中,假设JS (cuddly-slider.js)是位于你主题的js子文件夹中。你也可以从外部链接引入JS, CSS 和其他可能。详细信息在https://www.drupal.org/node/2274843(link is external) 或 https://www.drupal.org/node/2201089(link is external)
所以,要确保jQuery在js/cuddly-slider.js中可用,我们需要更新代码:
cuddly-slider: version: 1.x css: theme: css/cuddly-slider.css: {} js: js/cuddly-slider.js: {} dependencies: - core/jquery
当然,一个库可以只包含CSS组件,或JS组件。绝大多数主题都会想要一个global-styling组件库,为了需要被全范围加载的CSS (比如,应用主题的所有页 – 通常是整个站点,出了管理员页面):
global-styling: version: 1.x css: theme: css/layout.css: {} css/style.css: {} css/colors.css: {} css/print.css: { media: print }
当然,如你所期望,CSS在这里的顺序也是它们被加载的顺序
在Drupal 7中,你需要指出媒体属性(screen,print,all)作为stylesheets属性的子键值,现在,对任意CSS组件,你可以把它定义成一个值,例如:
css/print.css: { media: print }
给页面附加库
根据你需要加载的组件,你会想用不同的方式附加相关的组件库。毕竟,一些组件库所有页面都需要,一些只被少数需要,还有一些被大多数但不是全部需要。
附加到所有页面
要为所有使用你主题的页面附加库,需要在你主题的*.info.yml文件中声明它,在libraires键值的下面:
name: Exampletype: themecore: 8.xlibraries: - fluffiness/cuddly-slider
你想列多少库就可以列多少库,它们都会在每一页被加载。
然后,清除缓存让Drupal加载新信息
为一个子集的页面附加库
在一些情况下,你不需要你的库被所有页面加载,而是只需要一部分(子集)页面加载。例如,你可以只需要你的库在某个特定区块(block)出现时或者某个特定节点类型显示时被激活。
一个主题可以通过在.theme文件中置入THEME_preprocess_HOOK()函数实现。需要用你的主题的机器名替换THEME和主题的钩子函数的机器名替换HOOK。
例如,如果你想给维护页附加JS,钩子部分就是maintenance_page,你的函数应该是这样:
<?phpfunction fluffiness_preprocess_maintenance_page(&$variables) { $variables['#attached']['library'][] = 'fluffiness/cuddly-slider';}?>
你可以对其他主题的钩子做类似的事情,当然,你的函数也可以包含逻辑部分,例如,检测哪个区块被区块钩子预处理了,哪个节点类型被节点类型预处理了,等等。
在twig模板中附加库
你可以在twig模板中附加一个库,使用的是attach_library() 这个twig函数。
所以,在任何*.html.twig中:
{{ attach_library('fluffiness/cuddly-slider') }}<div>Some fluffy markup {{ message }}</div>
附加可设置的JS
在某些情况下,你可能希望根据一些PHP的计算信息来附加JS到页面上。
这 时,建立一个JS文件,像以前一样定义并附加一个库,但是也要附上JS设置并通过drupalSettings(Drupal 7的Drupal.settings的继承者)让JS读取这些设置。不过,要想让drupalSettings对我们的JS可用,我们需要做让 jQuery可用的同样工作:我们需要声明需求。
所以就变成了:
cuddly-slider: version: 1.x js: js/cuddly-slider.js: {} dependencies: - core/jquery - core/drupalSettings
和
<?phpfunction fluffiness_page_attachments_alter(&$page) { $page['#attached']['library'][] = 'fluffiness/cuddly-slider'; $page['#attached']['drupalSettings']['fluffiness']['cuddlySlider']['foo'] = 'bar';}?>
“bar”是一些计算的值。
这样,cuddl-slider.js就可以访问drupalSettings.fluffiness.cuddlySlider.foo了,并===’bar’
内置JS
不鼓励内置JS,建议把需要内置的JS存到一个文件里,因为这样可以在客户端缓存JS,也可以审查JS。
内置生成附加物的JS
例如广告,社交媒体分享按钮,社交媒体插件。这些会用到内置JS。但是他们只是一类特定的内容/附加物,因为它们不装饰站点内容或让内容产生交互,而是用过JS从外部输入内容。
你需要这些或在一个自定义的区块中,或直接在Twig模板中。
例如:
<script type="text/javascript"><!--ad_client_id = "some identifier"ad_width = 160;ad_height = 90;//--></script><script type="text/javascript" src="/images/2021/07/19/03/2021071903512015330000.js"></script> <a class="twitter-timeline" href="https://twitter.com/wimleers" data-widget-id="307116909013368833">Tweets by @wimleers</a><script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
影响整个页面的内置JS
例如: 分析插件,和分享的字体服务。影响整个页面的内置JS可以分为两种,前端设计或逻辑性的。
前端设计的情况下,JS属于主题。把JS直接放置到html.html.twig文件中。在字体的情况下,也允许将KS放置到对的地方会给你最好的终端用户体验,因为它允许你防止字体加载中的FOUT(未设计字体的闪现)
(更多内容在此:“Async Typekit & the Micro-FOUT”(link is external))
其他情况,JS属于模块,请看“Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module”(link is external)。
与Drupal 7的不同
- 在Drupal 7中,库需要用hook_library_info()定义,这被*.libraries.yml文件取代。
- 在Drupal 8中,drupal_add_css(), drupal_add_js(), 和drupal_add_library()被去除以支持#attached
原文链接:https://www.drupal.org/theme-guide/8/assets(link is external)