gracekrcx / weekly-notes

4 stars 0 forks source link

styled-components SSR 設定 #97

Open gracekrcx opened 4 years ago

gracekrcx commented 4 years ago

styled-components SSR 設定

img

基礎概念範例

src/client/App.js

  1. 在 client 端寫好了 html 和 style
import React from 'react' ; 
import styled from 'styled-components' ;

const AppContaienr = styled.div ` 
  display: flex; 
  justify-content: center; 
  font-size: 40px ; 
`;

const App = ( ) =>  < AppContaienr > 💅 < / AppContaienr > ;

export default App ;

src/client/Html.js :

  1. 然後準備一個 Html.js 模板,將所有 server 生成的應用程序代碼插入其中,然後作為常規的 HTML 發送給客戶端。 這個檔案就是一般的 html 檔,會接收 body, title, style 參數
const  Html  =  ( { body , styles , title } )  => ` 
 <!DOCTYPE html> 
  <html> 
   <head> 
    <title> ${ title } </title> 
    ${ styles }  
    </head>     
   <body style ="margin:0">       
    <div id="app"> ${ body } </div> 
   </body>  
 </html> ` ;      

export  default  Html ;

src/server.js

  1. 在 server 端接收 App,輸出 Html styled-components 在這給了 ServerStyleSheet,擷取 <App /> 中的所有 styled 組件創建一個Style Sheet。這個樣式表等等會傳入 Html 模板。
import express from 'express'; 
import React from 'react'; 
import { renderToString } from 'react-dom/server'; 
import App from './client/App';  // <-- 所有的程式 
import Html from './client/Html';  // <-- HTML 樣板
import { ServerStyleSheet } from 'styled-components';  // <--導入ServerStyleSheet

const port = 3000 ; 
constserver = express( );

server.get( '/' , ( req , res ) => { 
  const sheet = new ServerStyleSheet( ) ;  // <--創建樣式表

  const body = renderToString( sheet.collectStyles ( <App /> ) ) ;  // <--蒐集樣式
  const styles = sheet.getStyleTags() ;  // <--從表中獲取所有標籤
  const title = 'SSR with Styled Components' ;

  res.send( 
    Html({ 
      body , 
      styles ,  // <--將樣式傳遞給 Html 模板
      title
    }) 
  ); 
});

server.listen(port) ; 
console.log(`Serving at http://localhost:${port}`) ;

babel-plugin-styled-components

This plugin adds support for server-side rendering, minification of styles, and a nicer debugging experience.

yarn add babel-plugin-styled-components --dev

Then add it to your babel configuration like so:

{
  "plugins": ["babel-plugin-styled-components"]
}

That’s because styled-components needs an extra step to make sure the css class names are kept the same on the client side and server side. babel plugin 讓 classs name 在 client 端和 server 端維持一致

styled-components SSR

The basic idea is that everytime you render your app on the server, you can create a ServerStyleSheet and add a provider to your React tree, that accepts styles via a context API. 每次在 server 端 render 時,產生 ServerStyleSheet 和增加一個 provider 在 React tree,這樣就可以透過 context API 接收 styles

Example The basic API goes as follows:

import { renderToString } from 'react-dom/server'
import { ServerStyleSheet } from 'styled-components'

const sheet = new ServerStyleSheet()
try {
  const html = renderToString(sheet.collectStyles(<YourApp />))
  const styleTags = sheet.getStyleTags() // or sheet.getStyleElement();
} catch (error) {
  // handle error
  console.error(error)
} finally {
  sheet.seal()
}