首页 文章

使用 React-Router browserHistory,Webpack 2 historyApiFallback 和 Node

提问于
浏览
2

我正在尝试使用 React,Node,Webpack 2 本地运行我的 React 应用程序。每当我点击不是/的路由时,我得到 404.我的目标是能够运行我的节点服务器,运行 webpack-dev-server,使用 browserHistory 并返回我的 webpack historyApiFallback 工作。

目前的工作原理:

  • 如果我只运行webpack-dev-server而没有节点服务器,那么 browserHistory 工作正常,没有 404s。

  • 如果我用 hashHistory 运行节点它可以正常工作,没有 404s。

因此,排除我的路线不起作用。这是一些代码:

server.js

const express = require('express');
const expressGraphQL = require('express-graphql');
const schema = require('./schema');

const app = express();

app.use('/graphql', expressGraphQL({
  schema,
  graphiql: true
}));

const webpackMiddleware = require('webpack-dev-middleware');
const webpack = require('webpack');
const webpackConfig = require('../webpack.config.js');
app.use(webpackMiddleware(webpack(webpackConfig)));

app.listen(process.env.PORT || 5000, () => console.log('Listening'));

webpack.config.js

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const VENDOR_LIBS = [
  'axios', 'react', 'react-dom', 'react-router', 'react-apollo', 'prop-types'
];

module.exports = {
  entry: {
    bundle: './client/src/index.js',
    vendor: VENDOR_LIBS
  },
  output: {
    path: path.join(__dirname, 'dist'),
    publicPath: '/',
    filename: '[name].[chunkhash].js'
  },
  module: {
    rules: [
      {
        use: 'babel-loader',
        test: /\.js$/,
        exclude: /node_modules/
      },
      {
        test: /\.scss$/,
            use: [{
                loader: "style-loader"
            }, {
                loader: "css-loader"
            }, {
                loader: "sass-loader"
            }]
      },
      {
        test: /\.(jpe?g|png|gif|svg|)$/,
        use: [
          {
            loader: 'url-loader',
            options: {limit: 40000}
          },
          'image-webpack-loader'
        ]
      }
    ]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      names: ['vendor', 'manifest']
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    }),
    new HtmlWebpackPlugin({
      template: './client/src/index.html'
    })
  ],
  devServer: {
    historyApiFallback: true
  }
};

routes.js

import React from 'react';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';

import App from './components/App';
import Portal from './components/portal/Portal';

const componentRoutes = {
  component: App,
  path: '/',
  indexRoute: { component: Portal },
  childRoutes: [
    {
      path: 'home',
      getComponent(location, cb) {
        System.import('./components/homepage/Home')
          .then(module => cb(null, module.default));
      }
    }
  ]
};

const Routes = () => {
  return <Router history={ browserHistory } routes={ componentRoutes } />
};

export default Routes;

同样,目标是能够在本地启动我的节点服务器,使用 browserHistory 而不是 404。我不想使用 hashHistory,我需要使用我的节点服务器,所以我可以使用 graphql。我也不想恢复到 webpack v1。虽然这里是人们在 v1 中工作的链接:

historyApiFallback 在 Webpack dev 服务器中不起作用

1 回答

  • 2

    historyApiFallback选项专门用于webpack-dev-server。如果您正在运行自己的服务器,即使使用webpack-dev-middleware,也需要将其配置为在发生 404 时发送index.html。因为您正在使用html-webpack-plugin,所以要发送的index.html在您的文件系统上不存在,而只在内存中存在。要使其工作,您可以访问 webpack 编译器的输出,如评论 html-webpack-plugin#145所示。

    server.js

    const path = require('path');
    const express = require('express');
    const expressGraphQL = require('express-graphql');
    const schema = require('./schema');
    
    const app = express();
    
    app.use('/graphql', expressGraphQL({
      schema,
      graphiql: true
    }));
    
    const webpackMiddleware = require('webpack-dev-middleware');
    const webpack = require('webpack');
    const webpackConfig = require('../webpack.config.js');
    const compiler = webpack(webpackConfig);
    
    app.use(webpackMiddleware(compiler));
    // Fallback when no previous route was matched
    app.use('*', (req, res, next) => {
      const filename = path.resolve(compiler.outputPath, 'index.html');
      compiler.outputFileSystem.readFile(filename, (err, result) => {
        if (err) {
          return next(err);
        }
        res.set('content-type','text/html');
        res.send(result);
        res.end();
      });
    });
    
    app.listen(process.env.PORT || 5000, () => console.log('Listening'));
    

相关问题