簡體   English   中英

您如何管理用於生產/部署 Node-React 應用程序的存儲庫?

[英]How do you manage repositories for production/deployment of Node-React app?

不久前,我們曾經有服務器渲染頁面,然后 React 出現在客戶端渲染和單頁應用程序中。它引入了虛擬 DOM 並改變了我們編寫代碼的方式。

在編寫我們的代碼之前,我們需要所有這些反應庫並將它們安裝為依賴項。 現在我們可以分解成許多組件,有許多 css 和 scss 文件,包括圖像。 但最后我們將構建文件,制作壓縮包並從構建文件夾提供服務。

快速獲取路線

app.get('*', (req,res) =>{
    res.sendFile(path.join(__dirname+'/client/build/index.html'));
});

繼承人,我所理解的:

Build 文件夾是 webpack 組合所有文件並創建准備部署的壓縮包的地方。 該文件基本上是每個瀏覽器都可以理解的簡單 HTML 和 JS 文件。 由於所有瀏覽器都不理解 ES6 等等,我們必須將所有這些文件轉換為每個瀏覽器都可以理解的純語言。

此外,webpack-dev 服務器僅用於開發目的,我們不會將其運行到生產環境中。

  1. 虛擬 DOM/真實 DOM 僅用於開發目的嗎? 或者那些反應庫在構建縮小的文件時也被轉換了? 如果以后是這種情況,react 是否在客戶端瀏覽器的后台模式下運行? 我想知道在構建應用程序后 react 如何處理客戶端路由。
  2. 您如何管理 Node-React 應用程序的 github 存儲庫? 您是否保留兩個不同的存儲庫,一個用於前端,另一個用於后端? 行業標准是什么?
  3. 如果你保留兩個倉庫,你如何部署前端代碼? 因為您無法將 webpack-dev-server 運行到生產環境中。 您也不能在后端(快速服務器)中指定公共靜態(構建文件夾),因為它們被分隔在兩個存儲庫中。 這兩個存儲庫的集成如何發生(假設我們有兩個 AWS EC2 實例,每個實例一個)或前端從前端存儲庫提供服務??)。 你真的可以在生產中使用像 npm serve 這樣的東西嗎??

我想做什么?

我想在 AWS 上部署我的 node-react 應用程序。 我在 github 上只有一個存儲庫。 我的 repo 中有一個文件夾“client”,其中所有反應代碼都與其 package.json 文件一起存放。 服務器的所有其他文件都在根文件夾中(服務器沒有自己的文件夾,文件分散在根文件夾中)。 所以有兩個 package.json 文件,一個在服務器的根文件夾中,一個在客戶端文件夾中。我計划在 docker 容器上運行 my-node 應用程序。

請幫助我理解代碼托管和部署的核心概念和標准實踐,使大型企業應用程序保持清晰。

我不會在這里解釋您問題中的所有要點,因為@Arnav Yagnik 和@PrivateOmega 在解釋其中大部分問題方面都做得非常出色。 我絕對會建議您在閱讀此答案之前正確閱讀他們的答案並閱讀提供的鏈接以獲取更多信息。

我想解決您部署 Node-React 應用程序的問題。 在生產中,通常,我們對前端(React)和后端(Node)都有不同的部署(或您在問題中提到的“存儲庫”)。 這允許您的后端位於 EC2 實例中,例如,具有自動擴展功能以確保它可以處理傳入的所有請求。

正如在前面的答案中提到的,以及在你的問題中,webpack 將 React 文件編譯並縮小為大多數瀏覽器可以運行的簡單 HTML 和 JS 文件(我不打算在這里解釋 VirtualDOM,因為它已經被完美解釋了在其他答案中)。 然后,您將獲取這些縮小的文件並從 S3 存儲桶中提供它們,例如,因為它是一個單頁應用程序(也在其他答案中討論過)並且業務邏輯已經在縮小的 JS 文件中,它只是簡單地發送對后端服務器的所有請求。

現在對於前端,您可以使用 TravisCI 例如構建文件夾(您在問題中談到的那個)部署到 EC2 實例並使用 NGINX 為您的文件提供服務,或者如果您可以正確配置 CDN 部署,您可以提供服務S3 存儲桶中的文件以獲得最佳性能。

您可以認為React 應用程序提供服務就像向用戶的瀏覽器發送一個神秘的代碼塊。 現在,您可以這個神秘的代碼塊部署到公開可用的 S3 存儲桶,並從那里提供服務。 同樣,由於 webpack 和縮小/丑化,任何人都無法正確理解您的原始代碼是什么,請記住,例如,您仍然可以訪問 Chrome 的“源”選項卡中的所有代碼。

我想用不同的方法解決這個問題。

服務器渲染頁面:概念沒有改變,服務器在遇到 DOC 請求時必須以 html 響應。 現在 HTML 可能包含也可能不包含腳本(可以是內聯或外部服務器地址)。 在問題的上下文的情況下,您仍然可以將 HTML 發送到它會下載您編寫的腳本(可能包括反應或不反應)。 在大多數情況下,您可以發送帶有腳本標簽的空 html,這些標簽將通過網絡下載腳本並執行它們,這些腳本將包含所有渲染邏輯。

回答您的問題: 1st :單線程 JS 中沒有后台模式(除非我們想談論工作人員,但我們可以將它們排除在外進行討論)。 通過編寫代碼,您不會與任何 DOM 進行交互。 您正在指示您的組件(由 React 擴展)何時更改其狀態以及何時重新渲染(setState)。 React 內部計算虛擬 DOM 並與 Real DOM 進行比較以計算將在 Real DOM 上進行的實際更改(這是非常抽象的答案,要獲得更多理解,請閱讀 react 文檔,這里的基線是您沒有與任何 DOM 交互只是指示 React 核心庫何時更新以及更新狀態是什么)

第二:如果你想支持 SSR(服務器渲染頁面)。 我建議使用不同的package.json制作 2 個文件夾,客戶端(這將包括所有客戶端組件和邏輯)和服務器(將包括所有服務器端邏輯),因為這兩個應用程序的包不同。這里沒有這樣的行業標准,什么浮動你的船應該可以工作,但通常根據邏輯實體制作目錄應該滿足分離和可維護性,如果將來你想在單獨的 repos 中分出服務器和客戶端,它肯定會讓這個過程變得容易。

第三:您避免在生產中運行 webpack-dev-server。 文件通常不會被混淆,因此有效負載很重(不要忘記你寫的代碼就在那里)。 即使您想制作不同的存儲庫,服務器也可以吐出 html,而 html 可以向您的客戶端服務器請求腳本。

如何部署:部署您的代碼並運行:

節點服務器/app.js

在 app.js 中,您可以編寫您提到的位置塊。

PS:如果您只需要具有該位置塊的服務器。 你真的需要一個快遞服務器嗎? 您可以將客戶端構建上傳到 CDN 並路由您的域以從 CDN 提供 index.html(也可以在此處使用 s3 存儲桶)

我想從盡可能多地清理術語開始。

就像你說的服務器渲染頁面過去是一個比較突出的標准,但是隨着React的引入,它根本沒有改變,因為即使是React也支持服務器渲染或SSR ,這意味着HTML頁面是在服務器端生成的然后使用瀏覽器提供給客戶端。

客戶端渲染意味着,將 HTML 頁面加載到瀏覽器,然后 javascript 代碼在這些 HTML 頁面之上呈現內容並使它們具有交互性。

單頁應用程序的概念是我們只有一個 HTML 文件或基礎 HTML 頁面,基於用戶交互和來自服務器的數據不斷重寫它。

Virtual Dom是 React 引入的一個驚人的概念。 React 庫代碼以樹的形式在內存中重新創建 HTML 頁面的所有元素(稱為 DOM 元素)的結構。 這使得稱為Fiber 的React 算法能夠根據路由更新或任何其他更改,首先在此樹狀結構上協調適當的更改,然后再將它們轉換為 HTML 頁面中的真實元素。

Babel是一個轉譯器,用於將瀏覽器引擎尚未開始支持的最新功能轉譯為他們可以理解的代碼,通常是 ES6+ 代碼到 ES6 之前,因為所有瀏覽器都支持。 在 React 應用程序中,如果您使用 JSX 語法編寫應用程序,babel 也支持將 JSX 轉換為普通的 javascript。

是的,由於 React 組件的組合特性,可以將頁面分解為多個組件,這意味着我們可以通過組合小而更集中的事物來構建復雜的事物。

最后,在將其提供給最終用戶之前,我們不能因為代碼量太大而導致 Web 應用程序延遲,因此在構建過程中,諸如縮小(刪除空格等)和其他優化(例如將多個 javascript 文件合並為一個)等都完成了,然后像你說的那樣從構建文件夾中提供壓縮包。

是的,構建文件夾是 webpack 進行縮小和組合以創建盡可能小的包的地方。 它是每個瀏覽器都能理解的基本 HTML 和 JS 文件,如果代碼包含特定瀏覽器不支持的內容,則還捆綁了適當的支持代碼或稱為 polyfill 的內容。 從技術上講,你不能說瀏覽器只理解 ES6 之前的代碼,因為很多瀏覽器引擎已經實現了大量的 ES6 特性。

Webpack 開發服務器僅用於通過像 node.js 服務器這樣的端口為 Webpack 應用程序提供服務,並為我們提供實時重新加載等功能,當您不斷更改應用程序代碼庫時需要它,而在生產中不需要它,因為像我們之前說過,在生產時它只是 HTML 和 JS,沒有人對這些文件進行任何更改。

  1. 虛擬 DOM 是 React 代碼使用的內存表示或概念,就像我們有堆棧和隊列一樣,它不僅在開發時使用。 是和否。因為我認為在生成生產包之前,運行應用程序所需的 React 源代碼的適當部分也將被捆綁。

  2. 我會說,不要有預設的方式,因為這完全取決於開發人員和團隊,因為我看到人們使用 2 個單獨的存儲庫,因為前端人員從事前端工作,而后端人員從事后端工作。 但是也有一種情況,每個人都是全棧開發人員,從技術上講,您可以將它放在一個帶有單個 package.json 的存儲庫中,並使用后端來提供前端文件,並且您必須手動安裝每個 react 依賴項,並且不能直接使用 CRA 或create-react-app 類似生成器。

  3. 2 個存儲庫與生產中的前端部署有什么關系? 您不需要在生產中運行 webpack-dev-server 到服務器文件。 您可以創建一個生產包,然后設置任何 http 服務器來為生成的包提供服務。

關於您當前的情況,我會說您可以使用單個 package.json 並將所有依賴項安裝在一起,或者使用 monorepo 方法使用lernayarn workspaces 之類的方法,而不是使用 2 個 package.json。

但是對於初學者,我建議使用 2 個單獨的存儲庫來減少遇到的問題。

如果您不知道,還有一個額外的好處,您可以使用 ES6 之前的代碼編寫 React,也可以不使用 JSX。

1) 虛擬 DOM 基本上是說你正在調用一個 react 函數,而不是對真實 DOM 進行操作的實際函數

像這個

document.getElementById("demo").innerHTML ="Helloworld"

修改實際的dom

但是這個

ReactDOM.render(
  <HelloMessage name="Taylor" />,
  document.getElementById('demo')
);

如果你正確地看到了這一點,你就沒有直接在 dom 上做任何事情,你只是讓 react 函數控制做事情,每當 react 想要根據它的重新渲染它時,內部 react 會負責修改那個 dom 元素演示自己的邏輯,這就是他們聲稱已優化的邏輯,這就是人們首先使用它的原因。 是的,當你使用 webpack 構建你的代碼時,它確實包含了 react,這是該縮小代碼的一部分,所以如果你在開發中看到任何錯誤堆棧跟蹤,你就會看到 react 是它的起點

2)我認為這是一個選擇,因為對此沒有限制

3) 進入部署階段,一般來說,如果你想使用 nodejs,你可以選擇 expressjs 服務器類型的部署,否則通常最好使用像 Nginx 或 Apache 這樣的高性能服務器,否則如果你不想進入這個整體人們通常使用基於 heroku 的部署,或者人們現在使用特殊的平台,如 netlify、surge.sh(在這些平台上部署非常容易)。

我相信其他人已經很好地解釋了 React Virtual DOM。 我將嘗試以簡單實用的方式解釋我(將)如何使用 NodeJS 和 React 管理動態網站(包括中型企業系統)的部署。 我也會盡量不讓你厭煩。

想象一下,React 從未存在過,而您正在構建一個傳統的服務器端渲染應用程序。 每次用戶點擊路由時,控制器與模型一起執行一些業務邏輯並返回一個視圖。 在 NodeJS 中,此視圖通常使用模板引擎(例如把手)進行編譯。 如果您思考一下,很明顯該視圖可以是任何 html 內容,然后將其作為響應發送回瀏覽器。

這是可以發回的典型響應:

<html>

<head>
    <title>Our Website</title>
    <style></style>
    <script src="/link/to/any/JS/script"></script>
</head>

<body>
    <h1>Hello World </h1>
</body>

</html>

如果此響應命中瀏覽器,則顯然屏幕上會顯示“Hello World”。 現在,通過這個簡單的方法,我們可以做強大的事情!

選項 1:我們可以指定一個控制器來處理所有傳入的路由app.get("*", controllerFunc)並為我們的整個服務器呈現一個視圖。

選項 2:我們可以要求多個控制器處理不同的路由並從我們的服務器呈現特定於路由的視圖。

選項 3:我們可以要求多個控制器處理不同的路由並從我們的服務器即時(即動態)生成頁面。

如果我們正在構建一個傳統的 Web 應用程序,選項 3 將是唯一合理的標准。 在這里,針對不同的路由動態生成頁面。 然而,使用選項 1,我們可以生成一個高質量的單頁應用程序,其中發送到服務器的響應是一個空的 html 頁面,但具有能夠操作 DOM 的內置 JS 腳本——是的, React 以下是這樣的響應:

<html>

<head>
    <title>Our Website</title>
    <style></style>
    <script src="/link/to/any/JS/script"></script>
</head>

<body>
    <h1>Hello World </h1>
    <div id="root"> </div>
    <script async type=”text/javascript” src="/link/to/our/transpiled/ReactSPA.js"></script>
    <!--async attribute is important to ensure that the script has access to the DOM whenever it loads. This also makes the script non-blocking -->
</body>

</html>

顯然,我們將所有責任交給生成的 SPA,所有路由邏輯都在客戶端處理(請參閱react-router-dom )。 在服務器端,我們可以引入選項 2 中的概念並調整 NodeJS 路由處理程序以偵聽任何 REST API 通信的另一個特定路由。 如果您熟悉app.get()app.get()app.post()注冊路由的順序很重要。

但是,使用選項 1,我們很快就會受到限制,只能從該服務器為一個單頁應用程序提供服務。 為什么? 因為我們已經要求一個控制器處理所有非 API 傳入路由並呈現一個視圖。 我們還冒着提供不必要的膨脹 JS 文件的風險。 當用戶可能想要的只是登錄頁面時,他們會獲得完整的網站。

但是,如果我們查看選項 2,我們可以進行更多調整,並為不同的路由提供多個單頁應用程序,所有這些都來自我們的服務器。 這種方法有助於減少發送到瀏覽器的 JS 構建的大小。 一個典型的例子是一個具有歡迎頁面(或介紹目錄)、登錄頁面和儀表板的網站。

通過為不同的路由分配控制器,我們可以為這些路由構建唯一的 SPA。 SPA 用於介紹頁面,另一個用於登錄頁面,然后另一個用於儀表板。 是的,瀏覽器在三者之間轉換時必須加載,但至少我們大大增加了我們網站的初始渲染時間。 我們還可以使用更安全的 cookie 選項進行授權,而不是將會話令牌存儲在localStorage上的安全性較低的選項。

在更高級的設置中,我們可以將具有不同 React 組件的動態網站呈現為動態生成的頁面中的小部件。 實際上,這就是 Facebook 所做的。

構建此類 SPA 或組件的方法非常簡單。 啟動一個 react 項目並配置 webpack 以將生產就緒的 JS 文件呈現到服務器端存儲庫中您首選的公共靜態目錄中。 視圖中指定的<script>可以輕松加載這些構建的 React 組件,因為它們存在於服務器端公共目錄的范圍內。

本質上,這意味着一個 repo 包含多個客戶端目錄和一個服務器目錄,其中 webpack 為每個客戶端項目生成的生產構建文件的目標設置為服務器的公共靜態目錄。 因此,每個客戶端的目錄都是一個項目(完整的 SPA 或簡單的 React 組件作為小部件),具有自己的 webpack.config 和 package.json 文件。 事實上,你可以有兩個單獨的配置文件——生產和開發。 然后,要構建,您可以使用npm ~relevant command~進行生產或開發構建。

然后,您可以繼續以托管任何 NodeJS 應用程序的方式托管它。 因為,主要應用程序是 NodeJS - 那就是服務器所在的位置。 用 PHP 和 Apache/NGINX 替換 NodeJS,概念還是一樣的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM