- 原文地址:Managing CSS & JS in an HTTP/2 World
- 原文作者:
Trevor Davis- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:sunui
- 校對者:Usey95、alfred-zhong
使用了 HTTP/2,在網站中傳輸 CSS 和 JS 將變得完全不同,本文是結合我實踐的一份指南。
我們已經聽說 HTTP/2 很多年了。我們甚至寫了一些關於它的部落格。但我們的真正實踐並不多。一直到現在。在一些最近的專案中,我把使用 HTTP/2 作為一個目標,並弄清楚如何更好地應用多路複用。本文並不會主要去講你為什麼應該使用 HTTP/2,而是要討論我是如何管理 CSS 和 JS 的從而解釋這一正規化轉變。
拆分 CSS
這是我們多年來作為最佳實踐的反例。但為了汲取多路複用的好處,最好的方式還是把你的 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 的樣式。假如你正在使用模組化風格構建你的頁面,這很容易設定。
管理 SCSS 檔案
經過一些實踐,這是我整理的 SCSS 檔案結構:
CONFIG 資料夾
我使用這個資料夾設定一堆變數:
這裡的入口檔案是 _index.scss
,它引入了所有其他 SCSS 檔案,所以我可以訪問到一些變數和 mixins。它是這樣的:
@import "variables";
@import "../functions/*";複製程式碼
FUNCTIONS 資料夾
顧名思義,它包含了一些常見的 mixins 和函式,每一個 mixin 或函式都對應一個檔案。
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
最近所有的專案我們都是用 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 配置。
彩蛋:Craft 巨集
很長一段時間以來,我們在 Viget 都主張使用 Craft,我就寫了一個巨集來減少這種引入樣式的方式:
{%- macro css(stylesheet) -%}
<link rel="stylesheet" href="/stylesheets{{ stylesheet }}/index.css" media="not print">
{%- endmacro -%}複製程式碼
當我想要引入一個模組的 CSS 檔案,我只需這樣:
{{ macros.css('/modules/image-block') }}複製程式碼
如果我需要在整個網站上放置樣式表引用,這就更簡單了。
管理 JS
就像 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、前端、後端、產品、設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。