1

style-loader私の目標は、CSS をサーバー側と同様に、またはプラグインがクライアント側で行う方法とまったく同じスタイル タグにレンダリングすることです。style-loaderDOM に直接書き込み、DOM が Node.js に存在しないため、これが不可能であることはわかっています。

現在、私は ExtractTextPlugin を使用していますが、すべての CSS を 1 つの大きなファイルにコンパイルしないと、サーバーで Webpack を実行して完全にコンパイルしない限り、ページの読み込み時にいくつかのスタイルが失われます。

ページをレンダリングするこのコードがあります:

サーバー.jsx

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

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

render-full-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>
    )
}

次のように、React モジュールで必要なときにスタイルをグローバルにインポートしています。

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

そして、CSS のロード方法を変更して、すべての CSS を var に入れ、ループして<style>タグを同じように出力できるようにしたいと思いますstyle-loader

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

これはWebpackで可能ですか? これを行うことができるようなプラグインはありisomorphic-style-loaderますか? もしそうなら、どのようにコードを変更しますか?

4

1 に答える 1

3

を使用したいものの例を次に示しますisomorphic-style-loader

まず、Style Helper を作成して、スタイルを DOM にプッシュするか、後でサーバーでレンダリングされる var にスタイルをロードすることを自動化します。

これは、スタイル ファイル (CSS、Sass、LESS、Stylus) の配列を受け入れるように変更して作成したスタイル ヘルパーの例です。

utility/style-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()fromを使用してこれを行う方法を示していますreact-redux

私のモジュール.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>タグの間に配置します。

これが私がそれをした方法の例です:

render-full-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 タグが Style Helper からスタイルを取得し、<style>タグ内に配置する方法に注目してください。反応が読み込まれると、何をすべきかが分かりますが、サーバーには実際にページを適切に表示するために必要な CSS しかありません。

于 2016-02-19T17:32:49.707 に答える