nginx 部署 react 项目
前言
我用的是 create-react-app 在 nginx 上部署的前端项目,并使用 nginx 实现了下载文件的功能
nginx 的根目录是/usr/share
location /pkg/ {
if (!-f $request_filename) {
return 404 '文件不存在';
}
}
# 可以看到,下载升级包的页面路径是/upgrade
location /upgrade {
try_files $uri $uri/ /upgrade/index.html;
}
项目部署上线结果白屏问题
- react 项目配置页面路由的 basename(前端路由的/等于 nginx 的根目录/use/share)
function App() {
return (
<Router basename="/upgrade">
<Switch>
<Route exact path="/">
<Main />
</Route>
<Route exact path="/404">
<NotFoundPage />
</Route>
<Route>
<NotFoundPage />
</Route>
</Switch>
</Router>
)
}
- pakage.json 中配置
"homepage": "/upgrade",
如果是 webpack 而不是脚手架 create-react-app,则配置 publicPath,目的是让 html 中引用的 js,css 文件的路径是以/upgrade 开头的,那么路由就可以找到他们了,homepage 只会影响项目中引用的静态资源的路径
<script src="/upgrade/static/js/2.c8c300b5.chunk.js"></script>
<script src="/upgrade/static/js/main.529d8b95.chunk.js"></script>
需求:前端实现下载文件,如果文件不存在则使用 react-router 跳转到 404 页面
// head请求文件是否存在,如果存在才创建a标签触发浏览器的下载行为
axios.head(path, {
validateStatus: status => {
if (status >= 200 && status < 300) {
const a = document.createElement("a")
a.href = path
a.style.display = "none"
a.rel = "noopener noreferrer"
a.target = "_blank"
a.download = `${key}.pkg`
a.type = "application/octet-stream"
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
} else if (status === 404) {
props.history.push("/404")
}
return false
},
})
为什么使用 head 先请求一次?
HTTP HEAD
方法 请求资源的头部信息, 并且这些头部与 HTTP GET
方法请求时返回的一致. 该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载, 以此可以节约带宽资源.