运维记录1——解决在Nginx下部署CRA项目,二级目录不能访问的问题
如果从头开始搭建React项目,create-react-app通常是开发者的首选。毕竟不是谁都有精力去了解WebPack的复杂配置,而CRA将配置隐藏开箱即用的特性必然会受到普遍欢迎。
根目录访问
到了部署阶段,我通常使用nginx作为web容器,将项目部署到一个根目录下访问。如
# nginx配置 server { listen 80; server_name my.website.com; ... location / { alias /data/www/react-project/dist; index index.html } }
那么只要我们将项目文件放到对应的目录下,重启nginx即可开始访问web页面。
二级目录访问
有时我们有多个web项目,多个项目不可能同时挂在根目录下,所以我们会划分二级目录来分别访问各个web项目。如
- http://my.website.com/project1 => 访问react-project1项目
- http://my.website.com/project2 => 访问react-project2项目
问题1:CSS等资源加载失败
此时,如果简单将nginx配置的location改为/project1,则会出现网页无法访问的错误。
# nginx配置 server { listen 80; server_name my.website.com; ... # location / { location /project1 { alias /data/www/react-project/dist; index index.html } }
现象
从dev工具可以看出,html文件有取得,但css、js等资源引用失败。css和js的文件路径都是http://my.website.com/static/...(或css)。
分析
CRA(create-react-app)的项目配置默认是跑在根目录下的。如果查看dist目录下的html会发现,所有的css或js文件的引用路径都是/开头的绝对路径。
解决
将打包路径从绝对路径改为相对路径:
# package.json { ... "homepage": ".", // 添加homepage属性,将路径改为当前目录 ... }
重新编译后看到,所有的资源文件路径都改过来了。
问题2:加载成功,网页空白
重新上传到服务器,更新dist目录下的文件,重启nginx后访问网页。
现象
结果发现,网页仍然是空白一片。查看html的渲染结果,发现似乎js并没有执行。
分析
在react-router-dom的例子中,通常使用的是BrowserRouter。这种类型的Router在向服务器发送请求时,如果相对于二级目录的路由去指向对应的页面路由,就会找不到资源,因此也就不会渲染。
解决
BrowserRouter有一个属性叫做basename,就是用于解决此类问题。
... import { Route, BrowserRouter as Router, Switch, Redirect } from 'react-router-dom'; ... ... <Router basename='/project1'> <Switch> <Redirect exact key='index' path='/' to='/home' /> { routes } </Switch> </Router> ...
问题3:访问成功,刷新后404
修改以上配置并编译部署,重启nginx后可正常访问网页。但刷新后,网页变为一片空白。
现象
网页显示,在请求页面路由如http://my.website.com/project... 时,该路由的请求状态为404。
分析
还是因为BrowserRouter的问题,之前能正常访问时因为路由中设置了Redirect,所以能访问到根目录并自动跳转到/home。但直接访问则会访问失败。
解决
在nginx配置中加入try_files命令
location /project1 { alias /data/www/react-project/dist; # index index.html try_files $uri /project1/index.html }
这样,在请求$uri时如果找不到对应的资源,会fallback回去加载index.html。
问题解决。