【react】將react項目嵌入到django中+解決頁面刷新404+發佈到IIS上後靜態資源無法找到

Table of Contents

需求

思路&原理

如何做

有坑咋辦

1 發佈到IIS上後,靜態資源無法加載

2 頁面刷新404


 

需求

最近要做一個project,打算前後端分離,但服務器端口號有限,對nginx 這種端口複用的手段也不是很熟悉(公司的服務器都是windows的,相關資料少的一批……_(:з」∠)_),所以只能大開腦洞了。

後端我們使用的是django。那麼,如果能夠將react 打出來的包塞到django裏頭,當做django項目的一部分,不就可以只用一個端口了麼??

(以下只是我個人解決問題的一個總結,肯定有很多很笨的地方,如果有人看到還望指正。)

 

思路&原理

從前後端分離的角度,react打出來的包通常會被當做一個獨立的項目看待。但實際上,react的包就是由各種靜態資源(HTML,css,js...)組成的。因此可以將其當做單純的靜態資源,放置到django中對應的位置中去。

這裏有兩個思路:

1 Inside Django App: 將react project拆散,分別塞入到django項目某App的各個位置(templates,statics等等)

2 Outside Django App: 保持react project的完整性,把它放置在與django項目的App同層級的位置

這裏我使用了後一種方案

 

如何做

這裏借鑑了這個帖子: https://www.cnblogs.com/ranyihang/p/10694635.html 這裏說的是VUE,但道理都一樣。

 step 1, 將react 文件放置到與App同級的位置:

這裏爲了清晰起見,在build外又包了一層:

step 2, 修改django templates 查找路徑:

被塗死的就是我在外層包裹的文件名。經過測試,不影響其他App的工作。

 

step3,設置static路徑(注意此處有坑!!在本地運行沒問題,但發佈到IIS上後還需要進一步處理。後面再講)

在STATICFILE_DIRS中:

塗死處爲外層包裹的文件夾名。正常這裏應該是App的名字。

 

step4,在django中添加導向react project的url:注意此處有坑!!無論本地還是發佈到IIS後,都會出現刷新頁面404的情況)

from django.views.generic.base import TemplateView  # try integrate react into django
urlpatterns = [
path('XXX', TemplateView.as_view(template_name='index.html')),]

如此就可以了。

 

有坑咋辦

這個過程中遇到兩個坑:

1 發佈到IIS上後,靜態資源無法加載

各種404.

這是因爲IIS 發佈後,頁面上的靜態資源是ip/static/XXX 這種形式。

理論上只要用虛擬路徑指向react project的靜態資源就好。但這裏有兩個問題,第一如果項目中有vendor,創建虛擬路徑貌似不好用。第二,如果django是多App的,那麼會有一個虛擬路徑文件夾static下有多個文件夾,分別指向多個App的情況。此時如果直接將react project的靜態文件夾(js,css等)掛在虛擬路徑文件夾static下就太亂了,不方便維護。

那怎麼辦?簡單,把整個react project都塞到static下面就行!

解決方案:

第一步,在IIS上創建虛擬路徑,在static下指向build:

第二步,將react project 中的index.html的所有“/static/XXX和”/vendor/XXX都改成"/static/build/static和"/static/build/vendor

done~

2 頁面刷新404

如果將react project單獨發佈,只能設置路由重寫來解決這個問題。比如nginx:

location / {
            root   C:/nginx-1.5.9/html/build;
            index  index.html index.htm;  
            try_files $uri $uri/ /index.html;  # look at here
        }

至於IIS……咱別提IIS了好嗎_(:з」∠)_

氮素!如果將react project視作django的一部分,這個問題就很簡單了。

爲什麼?看問題出現的原理:

刷新出現404多因爲使用了react-router。按照它的邏輯,要先加載頁面,然後再進行路由。這個時候url會發生變化,跟初始進入頁面時不同。

由於url的變化,刷新時使用的url無法被找到,因此還沒等加載頁面就被攔截住了。

以上是我總結的。具體可以看網上的帖子,說的更準確些。

但無論如何,可以確定這個節點的路由,是由後端完成的,也就是django。

那把路由註冊到django裏不就完事了嘛╮(╯▽╰)╭

依然如下。只不過這裏的XXX要與react-router中的一致。

path('XXX', TemplateView.as_view(template_name='index.html')),  # try to solve the issue that when refresh the web page, page is 404

好了,問題解決。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章