Matching root route in webpack-dev-server's historyApiFallback`

拜拜、爱过 提交于 2020-01-24 10:59:06

问题


Sample repo demonstrating the issue is here.

I'm trying to set up webpack dev server so that:

  1. Requests to / are served by public/landing.html (a static landing page)
  2. Requests to anything else are served by my React app

Using create-react-app, and based on webpack-dev-server's options, I've set up my webpackDevServer.config.js as follows:

historyApiFallback: { // Paths with dots should still use the history fallback. // See https://github.com/facebookincubator/create-react-app/issues/387. disableDotRule: true, rewrites: [ // shows views/landing.html as the landing page { from: /^\/$/, to: 'landing.html' }, // shows views/subpage.html for all routes starting with /subpage { from: /^\/subpage/, to: 'subpage.html' }, // shows views/404.html on all other pages { from: /./, to: '404.html' }, ], },

And when I start webpack here's what I see:

  • Requests to /subpage are routed correctly to subpage.html
  • Requests to /foo are routed correctly to 404.html. Eventually, these would be handled by my React app.
  • Requests to / are routed incorrectly to my React app.

How can I get landing.html to respond to requests at /?


回答1:


I ended up opening a bug request with webpack-dev-middleware and discovered it was not a bug but a failure of configuration.

Specifically, the issue is using HtmlWebpackPlugin alongside historyApiFallback. I believe plugins are processed before the regex matching, and HtmlWebpackPlugin's default file output is index.html; this means that out of the box, / will always be routed to the HtmlWebpackPlugin output file.

The solution to this is to set a custom filename in HtmlWebpackPlugin, which allows you to control the matching again. Here's a sample repo demonstrating the fix and here's the webpack config:

module.exports = {
  context: __dirname,
  entry: [
    './app.js',
  ],
  output: {
    path: __dirname + "/dist",
    filename: "bundle.js"
  },
  devServer: {
    publicPath: "/",
    // contentBase: "./public",
    // hot: true,
    historyApiFallback: {
      // disableDotRule: true,
      rewrites: [
        { from: /^\/$/, to: '/public/index.html' },
        { from: /^\/foo/, to: '/public/foo.html' },
        { from: /(.*)/, to: '/test.html' },
      ],
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: "Html Webpack html",
      hash: true,
      filename: 'test.html',
      template: 'public/plugin.html',
    }),
  ],
};



回答2:


Two thoughts come to mind:

  1. What you want to do is not possible with Webpack Dev Server (as far as I'm aware)
  2. And, once npm run build is run and deployed the deployed app would not follow the same rules as configured in Webpack Dev Server

Even if I'm mistaken on #1, #2 seems like a bigger issue if you ever plan to deploy the app. This leads me to recommend an alternate setup which will work on dev and production (or wherever it's deployed).

A few options:

  • setup the app as a single-page app (SPA) and use React Router to serve the static routes (/ and /subpage) and wildcards (everything else)
  • setup node (or another server) to serve the static routes (/ and /subpage) and wildcards (everything else)

An Attempt

In an attempt to setup the routes I was able to achieve this setup:

  • Display landing.html when / is requested
  • Display subpage.html when /subpage is requested
  • Display the React App at a specific path, like app.html

To do this make the following changes:

  1. Move /public/index.html to /public/app.html

    mv ./public/index.html ./public/app.html
    
  2. In /config/webpackDevServer.config.js, update historyApiFallback to:

    historyApiFallback: {
      // Paths with dots should still use the history fallback.
      // See https://github.com/facebookincubator/create-react-app/issues/387.
      disableDotRule: true,
      rewrites: [
        // shows views/landing.html as the landing page
        { from: /^\/$/, to: "landing.html" },
        // shows views/subpage.html for all routes starting with /subpage
        { from: /^\/subpage/, to: "subpage.html" },
        // shows views/app.html on all other pages
        // but doesn't work for routes other than app.html
        { from: /./, to: "app.html" }
      ]
    }
    
  3. In /config/paths.js update appHTML to:

    appHtml: resolveApp("public/app.html")
    
  4. In /config/webpack.config.dev.js, updateplugins` to include:

    new HtmlWebpackPlugin({
      filename: "app.html",
      inject: true,
      template: paths.appHtml
    })
    

Requesting a random URL, like localhost:3000/foo will return a blank page but contains the HTML from the app.html page without the bundled <script> tags injected. So maybe you can find a solution to this final hurdle.



来源:https://stackoverflow.com/questions/47273319/matching-root-route-in-webpack-dev-servers-historyapifallback

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!