1

私はに基づいて同形Reactアプリを書いています:

https://github.com/choonkending/react-webpack-node

例で使用されている css モジュールの代わりに、scss を使用したいと思います。そして、何らかの理由で、それらを機能させるのに非常に苦労しています。私の最初のステップは、サーバーとクライアントの両方の構成から webpack ローダーを削除し、それらcssを固有のローダーに置き換えることでした (および を削除します):scsspostcss

  loaders: [
    'style-loader',
    'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:3]',
    'sass-loader?sourceMap',
  ]

しかし、これはReferenceError: window is not defined、スタイルローダーとしてビルドすることが明らかにサーバー側のレンダリングに適していない場合にスローされます。そこで、次のアイデアは を使用することでしたisomorphic-style-loader。私が理解している限り、それを機能させるには、コンポーネントを高次コンポーネントで装飾する必要がありますwithStyles

import React, { PropTypes } from 'react';
import classNames from 'classnames';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from '../assets/scss/common/index.scss';

const App = (props, context) => (
  <div className={classNames('app')}>
    <h1 className="home_header">Welcome!</h1>
    {props.children}
  </div>
);

export default withStyles(s)(App);

次に、サーバー上のコード レンダリング ページでトリックを行います。しかし問題は、パッケージ ドキュメントの例では、Express 内で発生するフラックス アクション ( https://libraries.io/npm/isomorphic-style-loader#webpack-configuration ) と、使用しているボイラープレートがreact-router. insertCssしたがって、このオブジェクトをコンテキストにどのように挿入する必要があるかについて、私はちょっと迷っています。私はこれを試しました:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { RouterContext, match, createMemoryHistory } from 'react-router';
import axios from 'axios';
import { Provider } from 'react-redux';
import createRoutes from 'routes.jsx';
import configureStore from 'store/configureStore';
import headconfig from 'components/Meta';
import { fetchComponentDataBeforeRender } from 'api/fetchComponentDataBeforeRender';

const clientConfig = {
  host: process.env.HOSTNAME || 'localhost',
  port: process.env.PORT || '3001'
};

// configure baseURL for axios requests (for serverside API calls)
axios.defaults.baseURL = `http://${clientConfig.host}:${clientConfig.port}`;

function renderFullPage(renderedContent, initialState, head = {
  title: 'cs3',
  css: ''
}) {
  return `
  <!DOCTYPE html>
  <html lang="en">
  <head>
    ${head.title}
    ${head.link}
    <style type="text/css">${head.css.join('')}</style>
  </head>
  <body>
    <div id="app">${renderedContent}</div>
    <script type="text/javascript">window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};</script>
    <script type="text/javascript" charset="utf-8" src="/assets/app.js"></script>
  </body>
  </html>
  `;
}

export default function render(req, res) {
  const history = createMemoryHistory();
  const store = configureStore({
    project: {}
  }, history);

  const routes = createRoutes(store);

  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    const css = [];

    if (error) {
      res.status(500).send(error.message);
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search);
    } else if (renderProps) {
      const context = { insertCss: (styles) => css.push(styles._getCss()) };

      const InitialView = (
        <Provider context={context} store={store}>
            <RouterContext {...renderProps} />
        </Provider>
      );

      fetchComponentDataBeforeRender(store.dispatch, renderProps.components, renderProps.params)
      .then(() => {
        const componentHTML = renderToString(InitialView);
        const initialState = store.getState();
        res.status(200).end(renderFullPage(componentHTML, initialState, {
          title: 'foo',
          css
        }));
      })
      .catch(() => {
        res.end(renderFullPage('', {}));
      });
    } else {
      res.status(404).send('Not Found');
    }
  });
}

しかし、私はまだWarning: Failed context type: Required context 'insertCss' was not specified in 'WithStyles(App)'.これに取り組む方法を考えていますか? さらに重要なことは、それを行うためのより簡単な方法はありませんか? これは多くの追加作業のようです。

4

1 に答える 1

1

サーバー側のレンダリングを行っているときに、webpack で scss コンパイルを処理するには、いくつかの部分があります。まず第一に、ノードが.scssファイルをコンポーネントにインポートしようとするのは望ましくありません。

WEBPACK: trueしたがって、webpack 構成でグローバル変数を設定します。

plugins: [
    new webpack.DefinePlugin({
        'process.env': {
            WEBPACK: JSON.stringify(true),
        }
    })
],

.scssまた、コンポーネントでは、コンポーネントが webpack によって処理されている場合 (ビルド中または開発中)にのみ、ファイルのインポートを試みます。

if (process.env.WEBPACK) require('../assets/scss/common/index.scss');

コンポーネントごとに Sass ファイルが 1 つしかない場合 (そうするべきです)、これは常にワンライナーです。必要に応じて、追加の Sass ファイルを内部にインポートできますindex.scss

次に、設定でおそらくまだ css ローダーが必要なため、開発サーバーでは次のようになります。

{
    test: /\.s?css$/,
    loaders: ['style', 'css', 'sass']

},

そして、構成を構築するための次のようなもの:

{
    test: /\.s?css$/,
    loader: ExtractTextPlugin.extract('style', 'css!sass')
},
于 2016-08-02T04:49:49.283 に答える