部署时React路由器无法正常工作

时间:2017-04-14 12:36:00

标签: javascript reactjs heroku webpack react-router

我是Heroku和部署的新手。我使用create-react-app创建了一个项目,并使用redux作为框架。部署到Heroku时,我遇到了反应路由器的问题。当我点击我的应用程序中的链接时,路由器可以工作,但是当我刷新页面时,它会抛出404 Not Found错误。

这是我的index.js

import { Router, Route, browserHistory, IndexRoute } from 'react-router'
import { syncHistoryWithStore } from 'react-router-redux'
import { Provider } from 'react-redux'
import ReactDOM from 'react-dom'
import React from 'react'

import App from './containers/App'
import configure from './store'
import Dashboard from './components/v1/dashboard/dashboard';
import Login from './components/v1/login/login';

const store = configure();
const history = syncHistoryWithStore(browserHistory, store);

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <Route path="/" component={App}>
        <IndexRoute component={Login} />
        <Router path="/dashboard" component={Dashboard}/>
      </Route>
    </Router>
  </Provider>,
  document.getElementById('root')
)

这是我的webpack.config.prod.js

'use strict';

var autoprefixer = require('autoprefixer');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ManifestPlugin = require('webpack-manifest-plugin');
var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
var paths = require('./paths');
var getClientEnvironment = require('./env');


var publicPath = paths.servedPath;
var shouldUseRelativeAssetPaths = publicPath === './';
var publicUrl = publicPath.slice(0, -1);
var env = getClientEnvironment(publicUrl);

if (env.stringified['process.env'].NODE_ENV !== '"production"') {
  throw new Error('Production builds must have NODE_ENV=production.');
}

const cssFilename = 'static/css/[name].[contenthash:8].css';
const extractTextPluginOptions = shouldUseRelativeAssetPaths
  ? { publicPath: Array(cssFilename.split('/').length).join('../') }
  : undefined;

module.exports = {
  bail: true,
  devtool: 'source-map',
  entry: [
    require.resolve('./polyfills'),
    paths.appIndexJs
  ],
  output: {
    path: paths.appBuild,
    filename: 'static/js/[name].[chunkhash:8].js',
    chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
    publicPath: publicPath
  },
  resolve: {
    fallback: paths.nodePaths,
    extensions: ['.js', '.json', '.jsx', ''],
    alias: {
      'react-native': 'react-native-web'
    }
  },

  module: {
    preLoaders: [
      {
        test: /\.(js|jsx)$/,
        loader: 'eslint',
        include: paths.appSrc
      }
    ],
    loaders: [
      {
        exclude: [
          /\.html$/,
          /\.(js|jsx)$/,
          /\.css$/,
          /\.scss$/,
          /\.json$/,
          /\.(jpe?g|png|gif|svg)$/i
        ],
        loader: 'url',
        query: {
          limit: 10000,
          name: 'static/media/[name].[hash:8].[ext]'
        }
      },
      {
        test: /\.(js|jsx)$/,
        include: paths.appSrc,
        loader: 'babel',

      },
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract(
          'style',
          'css?importLoaders=1&modules&localIdentName=[name]__[local]___[hash:base64:5]!postcss',
          extractTextPluginOptions
        )
      },
      {
        test: /\.scss$/,
        loaders: ["style", "css", "sass"]
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: 'file',
        query: {
          name: 'static/media/[name].[hash:8].[ext]'
        }
      }
    ]
  },

  postcss: function() {
    return [
      autoprefixer({
        browsers: [
          '>1%',
          'last 4 versions',
          'Firefox ESR',
          'not ie < 9', // React doesn't support IE8 anyway
        ]
      }),
    ];
  },
  plugins: [
    new InterpolateHtmlPlugin(env.raw),
    new HtmlWebpackPlugin({
      inject: true,
      template: paths.appHtml,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true
      }
    }),
    new webpack.DefinePlugin(env.stringified),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        screw_ie8: true, // React doesn't support IE8
        warnings: false
      },
      mangle: {
        screw_ie8: true
      },
      output: {
        comments: false,
        screw_ie8: true
      }
    }),
    new ExtractTextPlugin(cssFilename),
    new ManifestPlugin({
      fileName: 'asset-manifest.json'
    })
  ],
  node: {
    fs: 'empty',
    net: 'empty',
    tls: 'empty'
  }
};

这是我的package.json

{
  "name": "olep2",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "draft-js": "^0.10.0",
    "draft-js-export-html": "^0.5.2",
    "es6-promise": "^4.0.5",
    "express": "^4.15.2",
    "jquery": "^3.1.1",
    "lodash": "^4.17.4",
    "moment": "^2.17.1",
    "react": "^15.5.4",
    "react-bootstrap": "^0.30.7",
    "react-day-picker": "^5.0.0",
    "react-dom": "^15.5.4",
    "react-fontawesome": "^1.5.0",
    "redux-thunk": "^2.2.0",
    "requirejs": "^2.3.2"
  },
  "devDependencies": {
    "classnames": "^2.2.3",
    "cross-env": "^4.0.0",
    "css-loader": "0.26.1",
    "es6-promise": "^4.0.5",
    "file-loader": "0.10.0",
    "image-webpack-loader": "^3.2.0",
    "node-sass": "^4.5.0",
    "npm-run-all": "^4.0.2",
    "postcss-loader": "1.2.2",
    "prop-types": "^15.5.4",
    "react-hot-loader": "^1.3.0",
    "react-redux": "^4.4.0",
    "react-router": "^2.0.0",
    "react-router-redux": "^4.0.0",
    "redux": "^3.3.1",
    "redux-actions": "^0.9.1",
    "rucksack-css": "^0.8.5",
    "sass-loader": "^6.0.2",
    "style-loader": "0.13.1",
    "autoprefixer": "6.7.2",
    "babel-core": "6.22.1",
    "babel-eslint": "7.1.1",
    "babel-jest": "18.0.0",
    "babel-loader": "6.2.10",
    "babel-preset-react-app": "^2.2.0",
    "babel-runtime": "^6.20.0",
    "case-sensitive-paths-webpack-plugin": "1.1.4",
    "chalk": "1.1.3",
    "connect-history-api-fallback": "1.3.0",
    "cross-spawn": "4.0.2",
    "detect-port": "1.1.0",
    "dotenv": "2.0.0",
    "eslint": "3.16.1",
    "eslint-config-react-app": "^0.6.2",
    "eslint-loader": "1.6.0",
    "eslint-plugin-flowtype": "2.21.0",
    "eslint-plugin-import": "2.0.1",
    "eslint-plugin-jsx-a11y": "4.0.0",
    "eslint-plugin-react": "6.4.1",
    "extract-text-webpack-plugin": "1.0.1",
    "fs-extra": "0.30.0",
    "html-webpack-plugin": "2.24.0",
    "http-proxy-middleware": "0.17.3",
    "jest": "18.1.0",
    "json-loader": "0.5.4",
    "object-assign": "4.1.1",
    "promise": "7.1.1",
    "react-dev-utils": "^0.5.2",
    "url-loader": "0.5.7",
    "webpack": "1.14.0",
    "webpack-dev-server": "1.16.2",
    "webpack-manifest-plugin": "1.1.0",
    "whatwg-fetch": "2.0.2"
  },
  "scripts": {
    "start": "node scripts/start.js ",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --env=jsdom"
  },
  "jest": {
    "collectCoverageFrom": [
      "src/**/*.{js,jsx}"
    ],
    "setupFiles": [
      "<rootDir>/config/polyfills.js"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>[/\\\\](build|docs|node_modules|scripts)[/\\\\]"
    ],
    "testEnvironment": "node",
    "testURL": "http://localhost",
    "transform": {
      "^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest",
      "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
      "^(?!.*\\.(js|jsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"
    },
    "transformIgnorePatterns": [
      "[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$"
    ],
    "moduleNameMapper": {
      "^react-native$": "react-native-web"
    }
  },
  "babel": {
    "presets": [
      "react-app"
    ]
  },
  "eslintConfig": {
    "extends": "react-app"
  }
}

2 个答案:

答案 0 :(得分:2)

问题是您的网络服务器仅为根路由(“/”)提供“index.html”

您必须以所有路由(或仅使用的路由)将为index.hml提供服务的方式配置Web服务器

阅读以获取更多信息 Heroku Buildpack for create-react-app: static hosting for React.js web apps

答案 1 :(得分:0)

尝试此代码:

Server.js:

app.get("*", (req, res) => {
   let url = path.join(__dirname, '../client/build', 'index.html');
   if (!url.startsWith('/app/')) // we're on local windows
   url = url.substring(1);
  res.sendFile(url);
});

为我工作。