简体   繁体   English

historyApiFallback 在 Webpack 开发服务器中不起作用

[英]historyApiFallback doesn't work in Webpack dev server

I use Webpack dev server and browserHistory in React Router to manipulate with urls by HTML5 History API.在 React Router 中使用 Webpack 开发服务器和 browserHistory来操作 HTML5 History API 的 url。 historyapifallback-option does not work in my webpack config file. historyapifallback-option在我的 webpack 配置文件中不起作用。 After refreshing http://localhost:8080/users or http://localhost:8080/products I got 404.刷新http://localhost:8080/usershttp://localhost:8080/products后,我得到了 404。

webpack.config.js webpack.config.js

var webpack = require('webpack');
var merge = require('webpack-merge');

const TARGET = process.env.npm_lifecycle_event;

var common = {
    cache: true,
    debug: true,
    entry: './src/script/index.jsx',
    resolve: {
        extensions: ['', '.js', '.jsx']
    },
    output: {
        sourceMapFilename: '[file].map'
    },
    module: {
        loaders: [
            {
                test: /\.js[x]?$/,
                loader: 'babel-loader',
                exclude: /(node_modules)/
            }
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        })
    ]
};

if(TARGET === 'dev' || !TARGET) {
    module.exports = merge(common,{
        devtool: 'eval-source-map',
        devServer: {
            historyApiFallback: true
        },
        output: {
            filename: 'index.js',
            publicPath: 'http://localhost:8090/assets/'
        },
        plugins: [
            new webpack.DefinePlugin({
                'process.env.NODE_ENV': JSON.stringify('dev')
            })
        ]
    });
}

index.html索引.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
        <title>Test</title>
    </head>
    <body>
        <div id="content">
            <!-- this is where the root react component will get rendered -->
        </div>
        <script src="http://localhost:8090/webpack-dev-server.js"></script>
        <script type="text/javascript" src="http://localhost:8090/assets/index.js"></script>
    </body>
</html>

index.jsx索引.jsx

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {Router, Route, useRouterHistory, browserHistory, Link} from 'react-router';

class Home extends Component{
  constructor(props) {
    super(props);
  }

  render() {
      return <div>
          I am home component
          <Link to="/users" activeClassName="active">Users</Link>
          <Link to="/products" activeClassName="active">Products</Link>
        </div>;
  }
}

class Users extends Component{
  constructor(props) {
    super(props);
  }

  render() {
      return <div> I am Users component </div>;
  }
}

class Products extends Component{
  constructor(props) {
    super(props);
  }

  render() {
      return <div> I am Products component </div>;
  }
}

ReactDOM.render(
    <Router history={browserHistory} onUpdate={() => window.scrollTo(0, 0)}>
        <Route path="/" component={Home}/>
        <Route path="/users" component={Users} type="users"/>
        <Route path="/products" component={Products} type="products"/>
    </Router>
    , document.getElementById('content'));

package.json package.json

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.jsx",
  "scripts": {
    "start": "npm run serve | npm run dev",
    "serve": "./node_modules/.bin/http-server -p 8080",
    "dev": "webpack-dev-server -d --progress --colors --port 8090 --history-api-fallback"
  },
  "author": "",
  "license": "MIT",
  "dependencies": {
    "events": "^1.1.0",
    "jquery": "^2.2.3",
    "path": "^0.12.7",
    "react": "^15.0.2",
    "react-dom": "^15.0.2",
    "react-mixin": "^3.0.5",
    "react-router": "^2.4.0"
  },
  "devDependencies": {
    "babel": "^6.5.2",
    "babel-core": "^6.8.0",
    "babel-loader": "^6.2.4",
    "babel-polyfill": "^6.8.0",
    "babel-preset-es2015": "^6.6.0",
    "babel-preset-react": "^6.5.0",
    "babel-register": "^6.8.0",
    "http-server": "^0.9.0",
    "webpack": "^1.13.0",
    "webpack-dev-server": "^1.14.1",
    "webpack-merge": "^0.12.0"
  }
}

I tried to change devServer in my config, but it didn't help:我试图在我的配置中更改devServer ,但它没有帮助:

devServer: {
    historyApiFallback: {
        index: 'index.html',
    }
},

devServer: {
    historyApiFallback: {
        index: 'index.js',
    }
},

devServer: {
    historyApiFallback: {
        index: 'http://localhost:8090/assets',
    }
},

devServer: {
    historyApiFallback: {
        index: 'http://localhost:8090/assets/',
    }
},

devServer: {
    historyApiFallback: {
        index: 'http://localhost:8090/assets/index.html',
    }
},

devServer: {
    historyApiFallback: {
        index: 'http://localhost:8090/assets/index.js',
    }
},

devServer: {
    historyApiFallback: {
        index: 'http://localhost:8090/assets/index.js',
    }
},
output: {
    filename: 'index.js',
            publicPath: 'http://localhost:8090/assets/'
},

I meet the same question today.我今天遇到同样的问题。 let config in webpack.config.js: output.publicPath be equal to devServer.historyApiFallback.index and point out html file route 。my webpack-dev-server version is 1.10.1 and work well.让 webpack.config.js 中的 config: output.publicPath等于 devServer.historyApiFallback.index 并指出 html 文件路径。我的 webpack-dev-server 版本是 1.10.1 并且运行良好。 http://webpack.github.io/docs/webpack-dev-server.html#the-historyapifallback-option doesn't work, you must point out html file route. http://webpack.github.io/docs/webpack-dev-server.html#the-historyapifallback-option不行,必须指出html文件路径。

for example例如

module.exports = {
    entry: "./src/app/index.js",
    output: {
        path: path.resolve(__dirname, 'build'),
        publicPath: 'build',
        filename: 'bundle-main.js'
    },
    devServer: {
        historyApiFallback:{
            index:'build/index.html'
        },
    },
};

historyApiFallback.index indicate that when url path not match a true file,webpack-dev-server use the file config in historyApiFallback.index to show in browser rather than 404 page. historyApiFallback.index 表示当 url 路径与真实文件不匹配时,webpack-dev-server 使用 historyApiFallback.index 中的文件配置在浏览器中显示而不是 404 页面。 then all things about your route change let your js using react-router do it.然后所有关于你的路由变化的事情都让你的 js 使用 react-router 来做。

output: {
    ...
    publicPath: "/"
  },

Adding public path solved this for me添加公共路径为我解决了这个问题

I had this problem and was only able to fix it using index: '/' with webpack 4.20.2我遇到了这个问题,只能使用index: '/'和 webpack 4.20.2 来修复它

        historyApiFallback: {
            index: '/'
        }

There is a very tricky thing going on here!这里发生了一件非常棘手的事情!

The 404 can be two totally different things below. 404可以是下面两个完全不同的东西。 You can open the Network tab of Chrome to see if it's the initial request that is 404, or the assets within.您可以打开 Chrome 的 Network 选项卡,看看是 404 的初始请求还是其中的资产。

If you are not afraid of terminal, you can also do curl -v http://localhost:8081/product to see the actual HTTP response code.如果你不怕终端,你也可以执行curl -v http://localhost:8081/product来查看实际的 HTTP 响应代码。

Case 1: 404 on the initial HTML page案例 1:初始 HTML 页面上的 404

This is the case that set-up with historyFallbackApi is not correct.这是使用 historyFallbackApi 设置不正确的情况。

Usually just historyApiFallback: true should work in devServer configs of Webpack.通常只有historyApiFallback: true应该在devServer的 devServer 配置中工作。 ( source ) Yet, if you happen to have a custom output folder, you have to set the index property of historyApiFallback to the same path, as advised by the other answers on this question like jsdeveloper's or echzin's . 来源)但是,如果您碰巧有一个自定义output文件夹,则必须将historyApiFallbackindex属性设置为相同的路径,如jsdeveloper'sechzin's等关于此问题的其他答案所建议的那样。

Case 2: 404 on the assets (eg bundle.js or vendor.js )案例 2:资产上的 404(例如bundle.jsvendor.js

This one is quite interesting!这个挺有意思的!

In this case you do actually get the initial HTML (ie if you add view-source: before your URL to become view-source:http://localhost:8081/admin , you see your HTML, and/or curl command shows the HTML), but the page doesn't work in the browser.在这种情况下,您确实获得了初始 HTML(即,如果您在 URL 之前添加view-source:以成为view-source:http://localhost:8081/admin ,您会看到您的 HTML,和/或curl命令显示HTML),但该页面在浏览器中不起作用。

What historyApiFallback does, which might sound like a magic, is literally just setting req.url of the Express server to be the index.html file, for any incoming GET request within the domain. historyApiFallback所做的,可能听起来很神奇,实际上只是将 Express 服务器的req.url设置为index.html文件,用于域内的任何传入 GET 请求。 ( The main two lines in the Source Code ) 源代码中的主要两行

However, if the path to your assets is relative (eg in the view-source, you see <script src="vendor.js"></script> ) AND the path that you are landing is not at the same path-depth as index (eg you are trying to load http://localhost:8081/admin/user/12/summary while the main server is at http://localhost:8081/admin ), what happens is it cannot find the .js files for your JavaScript code.但是,如果您的资产路径是相对的(例如,在视图源中,您会看到<script src="vendor.js"></script>并且您登陆的路径不在相同的路径深度作为索引(例如,当主服务器位于http://localhost:8081/admin时,您尝试加载http://localhost:8081/admin/user/12/summary ),发生的情况是找不到 .js JavaScript 代码的文件。 (in my case http://localhost:8081/admin/user/12/vendor.js ) (在我的情况下http://localhost:8081/admin/user/12/vendor.js

在此处输入图像描述

Note that whatever router that deals with HTML5 History here (react router or vue router), knows how to initialize the internal path to document.location.href upon the initial load.请注意,这里处理 HTML5 历史记录的任何路由器(反应路由器或 vue 路由器)都知道如何在初始加载时初始化document.location.href的内部路径。 But, it doesn't know where is the "root" to properly update the assets' path to it.但是,它不知道正确更新资产路径的“根”在哪里。 (And maybe it's not even its job, in terms of responsibility.) As a result, the path to assets would be calculated based on the URL's path, not the index.html 's path! (就责任而言,它甚至可能不是它的工作。)因此,资产的路径将根据 URL 的路径而不是index.html的路径来计算! So, for just src="vendor.js" with no absolute / prefix, it tries to find /admin/user/12/vendor.js instead of /vendor.js .因此,对于没有绝对/前缀的src="vendor.js" ,它会尝试查找/admin/user/12/vendor.js而不是/vendor.js

What you need to do here is to make sure the output path of your WebPack is an absolute path and starts with / , so regardless of the landing URL, it would always work.您需要在这里做的是确保您的 WebPack 的output路径是绝对路径并且以/开头,因此无论登陆 URL 是什么,它都将始终有效。 ie it's always <script src="/vendor.js"></script> in the HTML source.即它总是<script src="/vendor.js"></script>在 HTML 源代码中。

To do so, you have to set output.publicPath to be an absolute path (with or without domain).为此,您必须将output.publicPath设置为绝对路径(带或不带域)。 You can verify this via the view-source: or curl technique above.您可以通过上面的view-source:curl技术来验证这一点。 :) :)

Ref.: https://webpack.js.org/configuration/dev-server/#devserver-historyapifallback参考: https ://webpack.js.org/configuration/dev-server/#devserver-historyapifallback

This works with any react-router这适用于任何反应路由器

You have to add historyApiFallback: true您必须添加historyApiFallback: true

module.exports = {
    cache: true,
    entry: "./index.js",
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'public')
    },
    context: SRC,
    devServer: {
        contentBase: path.resolve(__dirname, 'public/assets'),
        stats: 'errors-only',
        open: true,
        port: 8080,
        compress: true,
        historyApiFallback: true
    },
...
}

If you're finding that some paths work but others don't, you may be falling foul of the "dot rule".如果您发现某些路径有效而其他路径无效,则您可能违反了“点规则”。 Per the docs :根据文档

When using dots in your path (common with Angular), you may need to use the disableDotRule :在路径中使用点时(在 Angular 中很常见),您可能需要使用disableDotRule

webpack.config.js webpack.config.js

 module.exports = { //... devServer: { historyApiFallback: { disableDotRule: true, }, }, };

For me this setting worked out:对我来说,这个设置解决了:

 module.exports = {
    output: {
        path: path.resolve(__dirname, 'build'),
        publicPath: '/',
        filename: 'bundle-main.js'
    },

    devServer: {
    /* Telling the server to fallback to index.html if the route is not found at the backend server */
      historyApiFallback: true,
    }
};

In webpack.config.js just add these lines在 webpack.config.js 只需添加这些行

devServer: {
    open: true,
    historyApiFallback: true,
   allowedHosts: 'all',
   hot: true
    
  },

and add this -> // prefixes: ["http://your url:8081/"] it's working perfectly.并添加这个 -> // 前缀:["http://your url:8081/"] 它工作得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 webpack-dev-server historyApiFallback 不起作用 - webpack-dev-server historyApiFallback doesn't work webpack-dev-server内联标志不起作用 - webpack-dev-server inline flag doesn't work Webpack - 在 webpack-dev-server 上链接其他 Pug 页面不起作用 - Webpack - linking other Pug pages on webpack-dev-server doesn't work 使用 webpack 开发服务器进行单页应用 historyApiFallback 而不使用默认的 index.html 文件 - Using webpack dev server for Single Page App historyApiFallback without using the default index.html file 尽管将webpack-dev-server的historyApiFallback设置为true,但仍在我的React应用中接收404 - Receiving 404s in my React app despite setting historyApiFallback to true for webpack-dev-server "Webpack Dev Server 代理不会重定向到 api 后端" - Webpack Dev Server proxy doesn't redirect to api backend Webpack-dev-server不会在更改时构建文件 - Webpack-dev-server doesn't build files on change webpack-dev-server不会在子文件夹中编译React组件 - webpack-dev-server doesn't compile React components in subfolders Webpack 开发服务器重新加载但不显示标记或 CSS 更改? - Webpack dev server reloads but doesn't show Markup or CSS changes? webpack 开发服务器无法正常工作 - webpack development server doesn't work properly
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM