0

我正在使用 webpack@2 和 React-Router@4 构建一个 React 应用程序。在开发模式下一切正常,但对于生产我想使用服务器端渲染,它会导致我出现错误:

TypeError: Cannot read property 'pathname' of null
    at isActive (/react-app/node_modules/react-router/Link.js:120:46)
    at Object.children (/react-app/node_modules/react-router/Link.js:80:24)
    at Subscriber.render (/react-app/node_modules/react-broadcast/Subscriber.js:65:23)
    at /react-app/build/app.js:18:2455
    at s (/react-app/build/app.js:17:22003)
    at x._renderValidatedComponentWithoutOwnerOrContext (/react-app/build/app.js:18:2433)
    at x._renderValidatedComponent (/react-app/build/app.js:18:2741)
    at x.performInitialMount (/react-app/build/app.js:17:28173)
    at x.mountComponent (/react-app/build/app.js:17:26586)
    at Object.s.mountComponent (/react-app/build/app.js:1:27885)

这是我的应用程序组件:

import React from 'react';
import { render } from 'react-dom';
import { Match, Miss, Link } from 'react-router';

import Home from './Home';
import About from './About';
import NoMatch from './NoMatch';

export default () => (
  <div>
    <ul>
      <li><Link to="/">Home</Link></li>
      <li><Link to="/about">About</Link></li>
    </ul>

    <hr/>

    <Match exactly pattern="/" component={Home} />
    <Match pattern="/about" component={About} />

    <Miss component={NoMatch}/>
  </div>
);

这是 webpack 的入口点:

import React from 'react';
import express from 'express';
import morgan from 'morgan';
import path from 'path';
import { ServerRouter, createServerRenderContext } from 'react-router';
import { renderToString } from 'react-dom/server';

import App from './components/App';

const app = express();

app.use(morgan('combined'));
app.use(express.static(path.join(__dirname)));

app.set('view engine', 'pug');
app.set('views', path.join(__dirname, '../src/views'));

app.get('*', function(req, res) {
  const context = createServerRenderContext();

  let markup = renderToString(
    <ServerRouter
      location={req.url}
      context={context}
    >   
      <App/>
    </ServerRouter>
  );  

  const result = context.getResult();

  if (result.redirect) {
    res.writeHead(301, {
      Location: result.redirect.pathname
    }); 

    res.end();
  } else {
    if (result.missed) {
      res.writeHead(404);

      markup = renderToString(
        <ServerRouter
          location={req.url}
          context={context}
        >   
          <App/>
        </ServerRouter>
      );  

  const result = context.getResult();

  if (result.redirect) {
    res.writeHead(301, {
      Location: result.redirect.pathname
    }); 

    res.end();
  } else {
    if (result.missed) {
      res.writeHead(404);

      markup = renderToString(
        <ServerRouter
          location={req.url}
          context={context}
        >   
          <App/>
        </ServerRouter>
      );  
    }

    res.render('index', { includeCss: true, reactMarkup: renderToString(<App />) });
    res.end();
  }
});

app.listen(3000);

最后是 webpack 的配置:

const fs = require('fs');
const path = require('path');
const webpack = require('webpack');

const config = {
  target: 'node',

  entry: [
    path.join(__dirname, 'src/js/server.prod.js')
  ],

  output: {
    path: path.join(__dirname, 'build'),
    filename: 'app.js'
  },

  resolve: {
    extensions: ['.js', '.jsx']
  },

  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      },

      {
        test: /\.(eot|png|svg|ttf|woff|woff2)$/,
        use: 'file-loader'
      }
    ]
  },

  externals: fs.readdirSync('node_modules').reduce(function(acc, mod) {
    if (mod === '.bin') {
      return acc;
    }

    acc[mod] = 'commonjs ' + mod;
    return acc;
  }, {}),

  node:  {
    console: false,
    global: false,
    process: false,
    Buffer: false,
    __filename: false,
    __dirname: false,
  },

  plugins: [
    new webpack.optimize.UglifyJsPlugin()
  ],

  bail: true
};

module.exports = config;

有任何想法吗?

4

2 回答 2

0

在 Home.js 和 About.js

import { Link } from 'react-router';
于 2017-02-19T00:02:37.437 回答
0

您要导入的链接组件来自“react-router”这是问题所在,这适用于 react-router 版本 < 4.0。从 react-router 版本 4 开始,这个 Link 包是 react-router-dom 的一部分。所以你需要先安装 react-router-dom :

npm install --save react-router-dom

并像这样导入:

import { Link } from 'react-router-dom'
于 2017-07-03T09:56:56.990 回答