1

我的目標是將CSS渲染到服務器端的樣式標記中,或者如何使用style-loader插件在客戶端執行此操作。我知道這是不可能的,因爲style-loader直接寫入DOM並且Node.js中不存在DOM。如何使用Webpack將樣式加載到React服務器端並返回樣式加載器客戶端?

目前我正在使用ExtractTextPlugin,但是如果我沒有將所有CSS編譯成一個大文件,當頁面加載時會錯過一些樣式,除非我在服務器上運行Webpack並且不編譯它顧左右而言他。

我有了這個代碼渲染頁面:

server.jsx

const renderedContent = renderToString(
    <Provider store={store} history={history}> 
     <RoutingContext {...renderProps} /> 
    </Provider> 
) 

const finalState = store.getState() 
const renderedPage = renderFullPage(renderedContent, finalState) 

渲染全page.jsx

module.exports = function renderFullPage(renderedContent = undefined, state = {}) { 
    return '<!DOCTYPE html>' + renderToStaticMarkup(
     <html lang="en"> 
     <head> 
      <meta charSet="utf-8" /> 
      <meta name="viewport" content="width=device-width, initial-scale=1" /> 
      {typeof __production !== 'undefined' && __production === true && <link id="css" rel="stylesheet" href="/main.css" />} 
     </head> 
     <body> 
      <div id="root"><div dangerouslySetInnerHTML={{__html: renderedContent}}></div></div> 
      <script dangerouslySetInnerHTML={{__html: 'window.__INITIAL_STATE__ =' + JSON.stringify(state)}} /> 
      <script src="/bundle.js"></script> 
     </body> 
     </html> 
    ) 
} 

我是重要的納克全球的風格,當我需要他們在我的陣營模塊,像這樣:

import './../../assets/styl/flex-video' 

而且我想改變我如何加載CSS把所有CSS成一個變種我可以遍歷和輸出<style>標籤以同樣的方式style-loader做它像這樣:

{typeof __production !== 'undefined' && __production === true && cssFiles.map((styles) => { 
    <style>{styles}</style> 
})} 

這是可能的的WebPack?有沒有像isomorphic-style-loader這樣的插件能夠做到這一點?如果是這樣,我將如何修改我的代碼?

回答

1

下面是您要使用isomorphic-style-loader的示例。

首先,您創建一個樣式助手來自動化將樣式推送到DOM或將它們加載到稍後將在服務器上呈現的var中。

這是我創建修改以接受的風格文件的陣列(CSS,薩斯,LESS,手寫筆)樣式助手的示例:

公用事業/樣式helper.jsx

import React, { Component } from 'react' 
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment' 

const css = [] 

const collectOrRender = function(styles) { 
    let renderedCollection = [] 

    for (let i = 0, l = styles.length; i < l; i++) { 
     const stylesFile = styles[i] 

     if (canUseDOM) { 
      renderedCollection[stylesFile._insertCss()] 
     } 

     css.push(stylesFile._getCss()) 
    } 

    return renderedCollection 
} 

export function styleHelper(ComposedComponent, styles) { 
    return class Styles extends Component { 
     componentWillMount() { 
      this.styleRemovers = collectOrRender(styles) 
     } 

     componentWillUnmount() { 
      setTimeout(() => { 
       for (let i = 0, l = this.styleRemovers.length; i < l; i++) { 
        let styleRemover = this.styleRemovers[i] 
        typeof styleRemover === 'function' && styleRemover() 
       } 
      }, 0) 
     } 

     render() { 
      return <ComposedComponent {...this.props} /> 
     } 
    } 
} 

export function renderStyles() { 
    return css.join('') 
} 

然後,你必須抓住你的風格助手,並讓它在裝載時包裹你的模塊。

這個例子顯示瞭如何使用connect()react-redux

我-module.jsx

// Utilities 
import { styleHelper } from 'utilities/style-helper' 

const styles = [ 
    require('normalize.css'), 
    require('styl/global'), 
    require('styl/site'), 
    require('styl/bubble') 
] 

class myModule extends Component { 
    render() { return (
     <div /> 
    )} 
} 

export default connect(
    state => ({ menuIsOpen: state.collapsibleMenu.menuIsOpen }) 
)(styleHelper(myModule, styles)) 

處理客戶端上裝載。現在在服務器上,您將所有這些樣式存儲到一個數組中。您需要將該數組拉到HTML頁面中,並將其放置在<style>標籤之間。

這裏是我是如何做的一個例子:

渲染全page.jsx

import React from 'react' 
import { renderToStaticMarkup } from 'react-dom/server' 

// Utilities 
import { renderStyles } from './style-helper' 

module.exports = function renderFullPage(renderedContent = undefined, state = {}) { 
    return '<!DOCTYPE html>' + renderToStaticMarkup(
     <html lang="en"> 
     <head> 

      {/* Critical Styles */} 
      <style dangerouslySetInnerHTML={{__html: renderStyles()}} /> 
     </head> 
     <body> 
      <div id="root" dangerouslySetInnerHTML={{__html: renderedContent}}></div> 
      <script dangerouslySetInnerHTML={{__html: 'window.__INITIAL_STATE__ =' + JSON.stringify(state)}} /> 
      <script src="/bundle.js"></script> 
     </body> 
     </html> 
    ) 
} 

注意風格標籤怎麼會從風格助手的樣式,並將它們內部<style>標記。當反應加載時,它會確定要做什麼,但現在服務器將只有CSS才能正確顯示頁面。

相關問題