編譯型 JSS 框架 Linaria 的原理

2021-10-10 17:42:26 字數 4113 閱讀 1333

linaria 是乙個近似於styled-componentsemotionjss 框架,不同點在於,styled-componentsemotion是乙個執行時方案,而 linaria 是乙個編譯期 + 執行時方案。

執行時的 jss 方案必須內建乙個 css 處理器,並且在執行時去解析,分別增加了體積和效能上的成本。 linaria 創造性的在編譯期將相應的 jss 解析出來,抽出解壓到乙個 css 檔案中,並將相應的 jss **替換成乙個指向某個 css 類名的字串,避免了執行時方案的問題。

本文只做原理**,使用介紹相關請看 《linaria 也許是現在 react 最佳的 jss 方案》

對於以下**

import  from '@linaria/core'

let size = 5;

size = (function() ());

const headerclassname = css`

text-align: center;

color: #fff;

`;const headertitleclassname = css`

.$ px;

}`;console.log(headerclassname, headertitleclassname);

linaria 會將其編譯為

// index.bundle.js

var size = 5;

size = function () ();

var headerclassname = "hf71da1";

var headertitleclassname = "hi1y09m";

console.log(headerclassname, headertitleclassname);

/* index.css */

.hf71da1

.hi1y09m .hf71da1

通過編譯後的**我們可以看出:

linaria 的實現依賴於 wbepack(rollup) 和 babel 是必然的,使用 linaria 必須在 webpack 和 babel 分別設定@linaria/webpack4-loader@linaria/babel才可以。

通過webpack使用 linaria 需要.rules上進行如下配置

,
所有的 js **都會經過@linaria/webpack4-loader,其核心**如下

export default function index(

this: loadercontext,

sourcecodes: string,

inputsourcemap: rawsourcemap | null

) );

if (result.csstext) = result;

if (sourcemap) */`;

}if (result.dependencies?.length) catch (e) `, e);

}});

}this.callback(

null,

`$\n\nrequire($);`,

result.sourcemap ?? undefined

);return;

}

是乙個標準的 webpack 非同步 loader ,@linaria/webpack4-loader做的事情就是把傳入的源**當做引數傳入、呼叫transform函式,這個函式來自@linaria/babel@linaria/babel是 linaria 維護的解析 jss **的babel-preset

export default function transform(code: string, options: options): result ;

} // ...

const ast = parsesync(code, ,

});const = transformfromastsync(

ast!,

code,

//.....

)!;const = (metadata as babel.babelfilemetadata & ).linaria;

let csstext = '';

object.keys(rules).foreach((selector, index) => ,

original: rules[selector].start!,

name: selector,

source: '',

});// run each rule through stylis to support nesting

csstext += `$\n`;

});return ;

}

transform內部首先會判斷**是否使用 linaria 的 api ,如果使用了則解析相應的 jss **,**並執行相關的 js **,**這也是為什麼本文開頭例子處編譯後樣式表的font-size的值為 3 而非 5 的原因。解析的時候,@linaria/babel會將 jss 中的 css **寫到metadata裡,而非轉化後的源**處,隨後交付給@linaria/webpack4-loader處理。

metadata是 babel 解析、轉譯**時用於儲存一些輔助資訊的地方,其內容適用於輔助轉譯流程的,轉譯完成後就不存在了

也就是說,@linaria/babel只負責將 jss **根據檔案路徑計算出乙個雜湊名,作為類名,替換相應的jss **。 css 解壓相關的操作由@linaria/webpack4-loader負責。

@linaria/webpack4-loader會將metadata裡 css 解壓到.linaria-cache/index.linaria.css裡,然後在轉化後的源**末尾處加上require("./.linaria-cache/index.linaria.css"),隨後 webpack 解析時就會將解析.css檔案相關操作委託到處理.css檔案的 loader ,此時我們可以自由選擇使用mini-css-extract-plugin還是style-loader,或者其他的.cssloader ,重點在於我們擁有了webpack.css檔案相關的生態,而其他的 jss 方案就沒法做到這點。

js **經由@linaria/webpack4-loader@linaria/webpack4-loader內部使用@linaria/babel解析、執行 js **

@linaria/babel將 jss 編譯成根據檔案路徑生成的類名,將 css **寫入到生成的metadata,將其交付到@linaria/webpack4-loader@linaria/webpack4-loadermetadata的 css **解壓到/.linaria-cache檔案中

@linaria/webpack4-loader在解析後**末尾處加上require("./.linaria-cache/index.linaria.css"),交由 webpack 進行後續的處理

關於編譯型和解釋型

編譯型 編譯型 complie 將j a程式中的源 翻譯成計算機能看懂的語言,然後執行 編譯器做這事 就好像你看一本外國的翻譯書,翻譯一遍,你就可以一直看,如果這本書更新了,你就需要重新購買這本書的翻譯版。但編譯型的程式不可以跨平台,簡單理解 就是這本書原本是俄文翻譯成了中文,你給乙個美國人他能看懂...

後台T型框架

這段時間主要是開始涉及一下後端,起碼要做到能懂大部分。懂後端和不懂後端做專案肯定不一樣 在這裡主要是記錄一下,防止學的不好卻自我感覺很ok!1 後台介面主要是由 t 型組成。在 frameset 之中示意圖 舉例 frameset.html lang en charset utf 8 framese...

編譯型語言與解釋型語言

計算機是不能理解高階語言的,更不能直接執行高階語言,它只能直接理解機器語言,所以使用任何高階語言編寫的程式若想被計算機執行,都必須將其轉換成計算機語言,也就是機器碼。而這種轉換的方式有兩種 1 編譯 2 解釋 由此高階語言也分為編譯型語言和解釋型語言。一 編譯型語言 使用專門的編譯器,針對特定的平台...