[英]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/users
或http://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 响应代码。
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
文件夹,则必须将historyApiFallback
的index
属性设置为相同的路径,如jsdeveloper's或echzin's等关于此问题的其他答案所建议的那样。
bundle.js
or vendor.js
)bundle.js
或vendor.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.