在 webpack-dev-server 的 historyApiFallback 中匹配根路由

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

Sample repo demonstrating the issue is here.

我正在尝试设置 webpack 开发服务器以便:

  1. / 的请求由 public/landing.html(静态登陆页面)
  2. 提供
  3. 对任何其他内容的请求都由我的 React 应用程序处理

使用 create-react-appbased on webpack-dev-server's options, I've set up my webpackDevServer.config.js 如下:

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' }, ], },

当我启动 webpack 时,这是我看到的:

如何让 landing.html 响应 / 的请求?

想到两个想法:

  1. Webpack Dev Server 无法实现您想做的事情(据我所知)
  2. 并且,一旦 npm run build 为 运行 并部署,部署的应用程序将不会遵循与 Webpack Dev Server
  3. 中配置的相同规则

即使我在 #1 上弄错了,但如果您打算部署该应用程序,#2 似乎是一个更大的问题。这让我推荐了一个替代设置,它将在开发 生产(或任何部署的地方)上工作。

几个选项:

  • 将应用程序设置为单页应用程序 (SPA) 并使用 React Router 提供静态路由(//subpage)和通配符(其他所有内容)
  • 设置节点(或另一台服务器)为静态路由(//subpage)和通配符(其他所有内容)提供服务

一次尝试

在尝试设置路由时,我能够实现此设置:

  • 当请求 / 时显示 landing.html
  • 当请求 /subpage 时显示 subpage.html
  • 在特定路径显示React App,如app.html

为此,请进行以下更改:

  1. /public/index.html移动到/public/app.html

    mv ./public/index.html ./public/app.html
    
  2. /config/webpackDevServer.config.js中,将historyApiFallback更新为:

    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. /config/paths.js 中将 appHTML 更新为:

    appHtml: resolveApp("public/app.html")
    
  4. /config/webpack.config.dev.js, updateplugins` 中包括:

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

请求随机 URL,如 localhost:3000/foo 将 return 一个空白页面,但包含来自 app.html 页面的 HTML 而没有捆绑 <script> 标签注入。所以也许你可以找到解决这个最后障碍的方法。

我以 webpack-dev-middleware 结束 opening a bug request 并发现这不是错误而是配置失败。

具体来说,问题在于将 HtmlWebpackPluginhistoryApiFallback 一起使用。我相信插件是在正则表达式匹配之前处理的,HtmlWebpackPlugin 的默认文件输出是 index.html;这意味着开箱即用,/ 将始终路由到 HtmlWebpackPlugin 输出文件。

解决方法是在HtmlWebpackPlugin中设置自定义文件名,这样就可以重新控制匹配了。 Here's a sample repo demonstrating the fix 这是 webpack 配置:

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',
    }),
  ],
};