在HTTP/2的时代里,在你的网站里发布CSS和JS跟以前大不相同了,以下是我实践的一份建议。
我们听说HTTP/2已经很多年了,我们也写过一些相关的博客。但是我们并没有怎么使用它。直到现在,在一些最近的项目里,我把使用HTTP/2设定为一个目标,并且想出怎样最好的使用多路复用特性。这篇文章并不是来说明你为什么需要使用HTTP/2,而是讨论我是怎么在这种规范的转变中管理CSS和JS的。
拆分CSS
这是我们多年以来的最佳实践的反例。但是为了利用多路复用特性,最好把你的CSS拆分到更小的文件里,这样在每个页面中只加载需要的CSS。像下面这个例子这样:
代码语言:javascript复制<html>
<head>
<!-- 每个页面都使用的全局CSS, 头部/底部/其他 -->
<link href="stylesheets/global/index.css" rel="stylesheet">
</head>
<body>
<link href="stylesheets/modules/text-block/index.css" rel="stylesheet">
<div class="text-block">
...
</div>
<link href="stylesheets/modules/two-column-block/index.css" rel="stylesheet">
<div class="two-column-block">
...
</div>
<link href="stylesheets/modules/image-promos-block/index.css" rel="stylesheet">
<div class="image-promos-block">
...
</div>
</body>
</html>
是的,这些都是在标签内部
. 但是,不要紧张,在规范中并没说不让这样用。对于每个小的标签块,你的样式可以拆分为只包含对应的CSS。假设你正在使用最近很流行的模块化搭建你的页面,这很容易设置。
管理你的SCSS文件
经过一些试验,这是我最后整理的SCSS文件目录结构:
config 文件夹
我用这个文件夹来设置所用的变量。
这里最主要的文件是_index.scss
,它用来输入到其他SCSS文件,这样我可以获取到变量或者mixins
。里面是这样的:
@import "variables";
@import "../functions/*";
functions 文件夹
这个文件夹自身就完美的解释了它的含义;它包含了自定义的mixins
和functions
(方法),每个文件代表了一个mixins
或者function
(方法)
global 文件夹
这个文件夹是我在每个页面都有用到的CSS。适用于网站的头部,底部,重置,字体,和其他通用样式。
index.scss
如下所示:
@import "../config/index";
@import "_fonts.scss";
@import "_reset.scss";
@import "_base.scss";
@import "_utility.scss";
@import "_skip-link.scss";
@import "_header.scss";
@import "_content.scss";
@import "_footer.scss";
@import "components/*";
最后一行是输入到整个组件目录的子文件夹里,在模块化中避免额外的全局样式是个捷径。
modules 文件夹
在我们的HTTP/2设置中这是最重要的文件夹。当我拆分样式到对应的模块,这个文件夹会包含非常非常多的文件。所以一个子文件夹就是一个模块:
然后,每个模块的index.scss
就像下面这样:
// Pull in all global variables and mixins
@import "../../config/index";
// Pull in all partials in this module's folder
@import "_*.scss";
这样我可以获取到变量和mixins
,然后我可以拆分模块的CSS为许多部分,它们组合成一个单独的CSS模块文件夹。
pages 文件夹
事实上这个文件夹跟modules
文件夹基本一样,但我用来放页面的特殊样式。这种更细化的模块化在我们这些天做的东西里绝对罕见,但是它很好的把页面的特殊样式拆分出来了。
调整 Blendid
我们这些天做的大多数项目都是用Blendid来构建的。为了获取上述SCSS配置,我需要添加node-sass-glob-importer package。当我安装完成后,我只需要把它添加到Blendid的task-config.js
文件中。
var globImporter = require('node-sass-glob-importer');
module.exports = {
stylesheets: {
...
sass: {
importer: globImporter()
},
...
}
biu的一下,我就搞好了HTTP/2的SCSS配置。
福利: Craft 宏(可以理解为模板的意思)
我们在Viget(作者公司)很长一段时间都主张使用Craft,我就写了一个宏模板来减少这种方式下引入样式的重复性:
代码语言:javascript复制{%- macro css(stylesheet) -%}
<link rel="stylesheet" href="/stylesheets{{ stylesheet }}/index.css" media="not print">
{%- endmacro -%}
当我想要引入一个模块的CSS文件夹,只需要这样:
代码语言:javascript复制`{{ macros.css('/modules/image-block') }}`
这让我在处理站点中的样式关系更简单点。
管理 JS
嗯,就像我处理CSS一样,我希望把JS拆分成模块,这样每个页面只需要加载其所需的JS。接着,使用Blendid 配置,我只需要做一点微调就可以正常工作了。
相对于使用Webpack的require()
,我需要使用import()
,modules/index.js
文件就像这样:
const moduleElements = document.querySelectorAll('[data-module]');
for (var i = 0; i < moduleElements.length; i ) {
const el = moduleElements[i];
const name = el.getAttribute('data-module');
import(`./${name}`).then(Module => {
new Module.default(el);
});
}
就像Webpack文档中说的:“这个特性在内部依赖Promise。如果你在老式浏览器中使用import()
,记得用类似 es6-promise
或者 promise-polyfill
来兼容Promise。”
我安装了es6-promise,并引入到我的app.js
文件中,实现自动兼容。
So I can easily drop in the es6-promise polyfill into my main app.js
file and have it polyfill automatically:
`require('es6-promise/auto');`
是的,你就可以使用在Blendid中提及的方式来生成JS模块。
代码语言:javascript复制`<div data-module="carousel">`
完美吗?
不,但至少让你知道一种标准的方法来管理你的HTTP/2资源。随着我们思考如何更好的利用HTTP/2来分离代码,我非常期待这份方案会越来越完善。
往期精选文章 |
---|
ES6中一些超级好用的内置方法 |
浅谈web自适应 |
使用Three.js制作酷炫无比的无穷隧道特效 |
一个治愈JavaScript疲劳的学习计划 |
全栈工程师技能大全 |
WEB前端性能优化常见方法 |
一小时内搭建一个全栈Web应用框架 |
干货:CSS 专业技巧 |
四步实现React页面过渡动画效果 |
让你分分钟理解 JavaScript 闭包 |
小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。