2016-09-06 9 views
0

私は、ReactでSSRに関する情報を見つけました。だから、私の場合(React/graphQL/Apollo/Express/Webpackのweb-app)にもっと役立つ例を見つけましたが、私は1つの問題を抱えていました。いくつかの例を下に:ルートをインポートする際のサーバー側レンダリングの問題

我々はルータをインポートするところから

server.js

... 
    import {router} from './client/App'; 
    import React from 'react'; 
    import { renderToString } from 'react-dom/server'; 
    import { match, RoutingContext, Route } from 'react-router'; 
    ... 
    function renderApp(props, res) { 
     const markup = renderToString(<RoutingContext {...props}/>); 
     const html = createPage(markup); 
     write(html, 'text/html', res); 
    } 

    app.get('*', (req, res, next) => { 
      const location = hist.createLocation(req.path); 
      match({routes: router, location: location}, (err, redirectLocation, renderProps) => { 
       if (err) { 
        writeError('ERROR!', res); 
        next(err); 
       } else if (redirectLocation) { 
        redirect(redirectLocation, res); 
       } else if (renderProps) { 
        renderApp(renderProps, res); 
       } else { 
        writeNotFound(res); 
       } 
      }); 
     }); 
    ... 

App.js

... 

import Login from './components/Login'; 
import Register from './components/Register'; 
... 
let routes = (
    <Route> 
     <Route path="login" component={Login}/> 
     <Route path="register" component={Register}/> 
     ... 
    </Route> 
); 

export let router = [{ 
    path: '/', 
    component: Layout, 
    indexRoute: { 
     component: View 
    }, 
    getChildRoutes(location, cb) { 
     require.ensure([],() => cb(null, routes)); 
    } 
}]; 

match({router, location},() => { 
    render(
     <ApolloProvider client={client}> 
      <div> 
       <Router routes={router} onUpdate={() => window.scrollTo(0, 0)} history={browserHistory}/> 
      </div> 
     </ApolloProvider>, 
     document.getElementById('root') 
    ); 
}); 

私はこのexampleのように全力を尽くす試みたが、server.jsに、私はインポートしようとすると問題があるrouterApp.jsサーバは動作せず、Reactコンポーネント(スタイルのインポートなど、私たちがクライアント上でできることはすべてサーバー上ではできないものすべて)に関連するエラーを表示します。

質問は何ですか、間違っていますか?この問題を起こさずにルートをインポートするにはどうすればよいですか? 私はすでにこの小さな仕事に多くの時間を腰掛けているのは本当に面倒です。

ご協力いただき、ありがとうございます。ありがとうございます!

答えて

1

ご存知のように、サーバー側のレンダリングでは、ノードサーバーの反応コンポーネントがレンダリングされます。ノードサーバはimport css/pngファイルをサポートしていません。

そして、あなたはあなたのクライアントコードを変更したくない場合は、ユーザーwebpack-isomorphic-toolsを試すことができ、それはあなたが必要とすることができますassert.jsonファイル、生成するのに役立ちます(「*を。CSS」)の呼び出しは、jsonオブジェクトを返しますwebpack css-loaderのようにCSSクラス名マップを生成しました。

あなたが興味があるなら、あなたはこれを見ることができますdemo。ここ

var WebpackIsomorphicToolsPlugin = require('webpack-isomorphic-tools/plugin'); 


module.exports = { 


    assets: { 
    images: { 
     extensions: [ 
     'jpeg', 
     'jpg', 
     'png', 
     'gif' 
     ], 
     parser: WebpackIsomorphicToolsPlugin.url_loader_parser 
    }, 
    fonts: { 
     extensions: [ 
     'woff', 
     'woff2', 
     'ttf', 
     'eot' 
     ], 
     parser: WebpackIsomorphicToolsPlugin.url_loader_parser 
    }, 
    svg: { 
     extension: 'svg', 
     parser: WebpackIsomorphicToolsPlugin.url_loader_parser 
    }, 

    bootstrap: { 
     extension: 'js', 
     include: ['./src/theme/bootstrap.config.js'], 
     filter: function(module, regex, options, log) { 
     function is_bootstrap_style(name) { 
      return name.indexOf('./src/theme/bootstrap.config.js') >= 0; 
     } 
     if (options.development) { 
      return is_bootstrap_style(module.name) && WebpackIsomorphicToolsPlugin.style_loader_filter(module, regex, options, log); 
     } 

     }, 

     path: WebpackIsomorphicToolsPlugin.style_loader_path_extractor, 
     parser: WebpackIsomorphicToolsPlugin.css_loader_parser 
    }, 
    style_modules: { 
     extensions: ['less','scss'], 
     filter: function(module, regex, options, log) { 
     if (options.development) { 
         return WebpackIsomorphicToolsPlugin.style_loader_filter(module, regex, options, log); 
     } else { 
         return regex.test(module.name); 
     } 
     }, 
     path: function(module, options, log) { 
     if (options.development) { 
         return WebpackIsomorphicToolsPlugin.style_loader_path_extractor(module, options, log); 
     } else { 
         return module.name; 
     } 
     }, 
     parser: function(module, options, log) { 
     if (options.development) { 
      return WebpackIsomorphicToolsPlugin.css_modules_loader_parser(module, options, log); 
     } else { 
       return module.source; 
     } 
     } 
    } 
    } 
} 

とあなたのserver.jsこの

function renderFullPage (title, css, html, initialState) { 
    return ` 
     <!DOCTYPE html> 
      <html> 
       <head> 
       <title>${title}</title> 
       <style type="text/css">${css}</style> 
       </head> 
       <body> 
       <div id="app">${html}</div> 

       <script> 
        window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}; 
       </script> 
       <script src="/assets/scripts/app.bundle.js"></script> 
       </body> 
      </html> 
    `; 
} 

const asyncStore = (store, renderProps) => { 
    let promise = Promise.all([ 
     store.dispatch(queryArtistList()), 
     store.dispatch(queryAuth()) 
    ]); 
    return promise; 
} 

const HomeCtrl = { 
    index: async (req, res) => { 
     // 补全同构应用运行时缺失的全局对象 
     global.window = { 
      navigator: { 
       userAgent: req.get('User-Agent'), 
      }, 
      location: { 
       protocol: req.protocol + ':', 
       hostname: req.hostname, 
      }, 
     }; 
     match({ routes, location: req.url }, async (err, redirectLocation, renderProps) => { 
      if (err) { 
       res.status(500).end(`Internal Server Error ${err}`); 
      } else if (redirectLocation) { 
       res.redirect(redirectLocation.pathname + redirectLocation.search + '/'); 
      } else if (renderProps) { 
       let store = configureStore(); 
       const state = store.getState(); 
       await asyncStore(store, renderProps); 
       const components = (<Provider store={store}> 
              <RouterContext {...renderProps} /> 
             </Provider>); 
       const html = renderToStaticMarkup(components); 

       res.end(renderFullPage('tokyo Artist', '', html, store.getState())); 

      } else { 
       res.status(404).end('Not found'); 
      } 
     }) 
    } 
} 

のように見えると確認してください、あなたはを生成した後にサーバーを起動する必要があり、あなたのWebPACK-同型-tools.jsですwebpack-asserts.json;

ので、あなたのapp.jsは次のようになります。詳細な回答のため

#!/usr/bin/env node 
const path = require('path'); 
const rootDir = path.resolve(__dirname, '..'); 
const fs = require('fs'); 

const babelrc = fs.readFileSync(rootDir + '/.babelrc', 'utf-8'); 
var config; 

try { 
    config = JSON.parse(babelrc); 
} catch (err) { 
    console.error('==>  ERROR: Error parsing your .babelrc.'); 
    console.error(err); 
} 

require('babel-register')(config); 

/** 
* Define isomorphic constants. 
*/ 
global.__CLIENT__ = false; 
global.__SERVER__ = true; 
global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production'; 
global.__DEVTOOLS__ = __DEVELOPMENT__; 


const WebpackIsomorphicTools = require('webpack-isomorphic-tools'); 
global.webpackIsomorphicTools = new WebpackIsomorphicTools(require('../webpack/webpack.isomorphic-tools')) 
    .development(__DEVELOPMENT__) 
    .server(__DEVELOPMENT__ ? __dirname : rootDir, function() { 
     require('../server/app.js'); 
    }); 
+0

感謝を! –

関連する問題