- 原文地址:Managing CSS & JS in an HTTP/2 World
- 原文做者:
Trevor Davis- 译文出自:掘金翻译计划
- 本文永久连接:github.com/xitu/gold-m…
- 译者:sunui
- 校对者:Usey95、alfred-zhong
使用了 HTTP/2,在网站中传输 CSS 和 JS 将变得彻底不一样,本文是结合我实践的一份指南。css
咱们已经据说 HTTP/2 不少年了。咱们甚至写了一些关于它的博客。但咱们的真正实践并很少。一直到如今。在一些最近的项目中,我把使用 HTTP/2 做为一个目标,并弄清楚如何更好地应用多路复用。本文并不会主要去讲你为何应该使用 HTTP/2,而是要讨论我是如何管理 CSS 和 JS 的从而解释这一范式转变。html
这是咱们多年来做为最佳实践的反例。但为了汲取多路复用的好处,最好的方式仍是把你的 CSS 拆分红更小的文件,这样在每一页只加载必要的CSS。应该像这个例子这样:前端
<html>
<head>
<!--每一页都是用的全局样式, header/footer/etc -->
<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>复制代码
没错,<link>
标签放在了 <body>
内部,但没必要惊慌,这彻底合规。所以对于每个小的标签块,均可以拥有一个独立的只包含相应 CSS 的样式。假如你正在使用模块化风格构建你的页面,这很容易设置。node
通过一些实践,这是我整理的 SCSS 文件结构:react
CONFIG 文件夹android
我使用这个文件夹设置一堆变量:ios
这里的入口文件是 _index.scss
,它引入了全部其余 SCSS 文件,因此我能够访问到一些变量和 mixins。它是这样的:git
@import "variables";
@import "../functions/*";复制代码
FUNCTIONS 文件夹es6
顾名思义,它包含了一些常见的 mixins 和函数,每个 mixin 或函数都对应一个文件。github
GLOBAL 文件夹
这个文件夹包含我每一页都使用的 CSS。特别适合放一些相似网站的 header、footer、reset、字体和其余通用样式之类的东西。
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/*";复制代码
最后一行引入了全部 components 的子目录,这是将额外全局样式模块化的捷径。
MODULES 文件夹
这是咱们 HTTP/2 体系中最重要的文件夹。当我拆分样式到对应的模块,这个文件夹会包含很是很是多的文件。因此我从拆分每个模块到子目录开始:
每一个模块中的 index.scss
是这样的:
// 导入全部的全局变量和 mixin
@import "../../config/index";
// 导入这个模块文件夹中的全部部分
@import "_*.scss";复制代码
这样我能够访问到变量和 mixin,而后我能够把模块的 CSS 拆分为许多部分,它们组合成一个单独的 CSS 模块文件。
PAGES 文件夹
实质上这个文件夹和 modules 文件夹同样,但我为了页面特定的内容使用它”。这种更模块化的方式在咱们最近作的东西里绝对罕见,可是它很好地把页面的特殊样式拆分出来了。
最近全部的项目咱们都是用 Blendid 来构建的 。为了实现上文描述的 SCSS 配置,我须要添加 node-sass-glob-importer。一旦装好它,我只需把它添加到 Blendid 的 task-config.js
中。
var globImporter = require('node-sass-glob-importer');
module.exports = {
stylesheets: {
...
sass: {
importer: globImporter()
},
...
}复制代码
duang,这样就完成了管理 SCSS 的 HTTP/2 配置。
很长一段时间以来,咱们在 Viget 都主张使用 Craft,我就写了一个宏来减小这种引入样式的方式:
{%- macro css(stylesheet) -%}
<link rel="stylesheet" href="/stylesheets{{ stylesheet }}/index.css" media="not print">
{%- endmacro -%}复制代码
当我想要引入一个模块的 CSS 文件,我只需这样:
{{ macros.css('/modules/image-block') }}复制代码
若是我须要在整个网站上放置样式表引用,这就更简单了。
就像 CSS 同样,我想要把 JS 拆分为模块,这样每一页只加载必要的 JS。同样的,使用 Blendid 配置,为了一切正常运转我只须要作一点点微调。
我使用的是 import()
,而非 Webpack 的require()
,。所以如今的 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()
,记得使用一个 polyfill 来兼容 Promise,好比 es6-promise 或者 promise-polyfill“。
所以我把 es6-promise polyfill 加入到个人入口文件 app.js
中,使其自动兼容。
require('es6-promise/auto');复制代码
是的,而后你就能够在 Blendid 开箱即用的模式触发模块生成对应特定的 JS。
<div data-module="carousel">复制代码
还不,但至少能够引领你开始以合理的方式管理 HTTP/2 资源。随着咱们对如何拆分代码来更好地使用 HTTP/2 的思考,我真切地但愿这个配置将会愈来愈完善。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、React、前端、后端、产品、设计 等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。