gracekrcx / weekly-notes

4 stars 0 forks source link

styled-components SSR - class name #95

Open gracekrcx opened 4 years ago

gracekrcx commented 4 years ago

styled-components SSR - class name

  1. 看起來在 class name 加 hash 是為了避免命名衝突
  2. 然後在 ssr 時會碰到的 server class name not match client name 造成 style 的錯誤,所以以 Next.js 為例,需要在 _document.js 增加 styleSheets 設定,把 css 也在 server 就一起 render
  3. 這篇文章 How To Render CSS on React App Servers 讓我開始找對方向 thanks this article

styled-components are not rendered to the server which makes them unavailable at that time

img

CSS-in-JS 是什麼

styled-components is css-in-js Library

CSS-in-JS 你所應該知道的一切 CSS-in-JS : 用 javasvript 寫 css

TL;DR: Thinking in components 用 components 的概念去寫 css,好重複使用 — No longer do you have to maintain a bunch of style sheets. CSS-in-JS abstracts the CSS model to the component level, rather than the document level (modularity). img img

Styled JSX

zeit/styled-jsx Full, scoped and component-friendly CSS support for JSX (rendered on the server or the client).

<style jsx> 讓 styles 在 server 端和 client 端都可以 render 的很好

import React from 'react';

const Button = props => (
  <button {...props}>
    {props.children}
    <style jsx>{`
      background: #0077e2;
      padding: 10px;
      color: #fff;
    `}</style>
  </button>
);
export default Button;

How styled-components works: A deep dive under the hood

1. Here is how the identifier computed:

counter++;
const componentId = 'sc-' + hash('sc' + counter);

componentId for the first styled component in an app is sc-bdVaJa

<style data-styled-components>
  /* sc-component-id: sc-bdVaJa */
</style>

Currently styled-components uses MurmurHash algorithm to create uniq identifier and then converts the hash number to alphabetic name.

2. 產生 CSS class name:

const className = hash(componentId + evaluatedStyles);

For our Button instance the generated className is jsZVzX. 這個 class name 也稱為 generatedClassName

3. CSS Preprocessing

function: (obtain valid CSS string)

const selector = '.' + className;
const cssStr = stylis(selector, evaluatedStyles);

output:

.jsZVzX {
  font-size: 24px;
  color: coral;
  padding: 0.25rem 1rem;
  border: solid 2px coral;
  border-radius: 3px;
  margin: 0.5rem;
}
.jsZVzX:hover{
  background-color: bisque;
}

帥呆了

4. render()

最後產生,styled-components renders an element with 3 class names

return ( 
  <TargetComponent 
    {...this.props} 
    className={this.props.className + ' ' + componentId + ' ' + generatedClassName}
  />
);

Final:

<button class="sc-bdVaJa jsZVzX">I'm a button</button>

this.props.className — 可選的 passed by parent component.

參考文章

How styled-components works: A deep dive under the hood Facebook CSS in JS CSS 的 100 個哀愁 利用 Styled System 建立一個更好的 UI 元件庫!

gracekrcx commented 4 years ago

一般 css

.dropdown {
  /// your style
}

.dropdown.active {
  background-color: red;
}

巢狀 class

.dropdown {
  //your style
  &.active {
    background-color: red;
  }
}

這樣的編譯方式,我們通常稱為預處理器(pre-processor)

styled-components 也是使用如此曹狀的寫法,CSS Preprocessing 使用的是 stylis.js,很順的就是 class 包著 cless 一直寫下去,需要 props 需要 calculation 就用大括號,其中背後就是這一個 pre-processor 在幫忙轉成複雜的樣子,而人類只需照著 html 結構一直包下去寫就 ok