當(dāng)你準(zhǔn)備把 Angular 應(yīng)用部署到遠程服務(wù)器上時,有很多可選的部署方式。
在完整部署應(yīng)用之前,你可以先臨時用一種技術(shù)來測試流程、構(gòu)建配置和部署行為。
在開發(fā)過程中,你通常會使用 ?ng serve
? 命令來借助 webpack-dev-server 在本地內(nèi)存中構(gòu)建、監(jiān)控和提供服務(wù)。但是,當(dāng)你打算部署它時,就必須使用 ?ng build
? 命令來構(gòu)建應(yīng)用并在其它地方部署這些構(gòu)建成果。
?ng build
? 和 ?ng serve
? 在構(gòu)建項目之前都會清除輸出文件夾,但只有 ?ng build
? 命令會把生成的構(gòu)建成果寫入輸出文件夾中。
默認(rèn)情況下,輸出目錄是 ?
dist/project-name/
?。要輸出到其它文件夾,就要修改 ?angular.json
? 中的 ?outputPath
?。
當(dāng)開發(fā)臨近收尾時,讓本地 Web 服務(wù)器使用輸出文件夾中的內(nèi)容提供服務(wù)可以讓你更好地了解當(dāng)應(yīng)用部署到遠程服務(wù)器時的行為。你需要用兩個終端才能體驗到實時刷新的特性。
ng build
? 命令把該應(yīng)用編譯進 ?dist
?文件夾。ng build --watch
與 ?ng serve
? 命令一樣,當(dāng)源文件發(fā)生變化時,就會重新生成輸出文件。
lite-server --baseDir="dist/project-name"
每當(dāng)輸出了新文件時,服務(wù)器就會自動刷新你的瀏覽器。
該方法只能用于開發(fā)和測試,在部署應(yīng)用時,它不受支持,也不是安全的方式。
Angular CLI 命令 ?ng deploy
?(在版本 8.3.0 中引入)執(zhí)行與你的項目關(guān)聯(lián)的 ?deploy
?CLI 構(gòu)建器。有許多第三方構(gòu)建器實現(xiàn)了到不同平臺的部署功能。你可以通過運行 ?ng add [package name]
? 把它們中的任何一個添加到項目中。
添加具有部署功能的程序包時,它將為所選項目自動更新自動更新工作區(qū)配置(?angular.json
? 文件)中的 ?deploy
?部分。然后,你就可以使用 ?ng deploy
? 命令來部署該項目了。
比如,以下命令將項目自動部署到 Firebase。
ng add @angular/fire
ng deploy
該命令是交互式的。在這種情況下,你必須擁有或創(chuàng)建 Firebase 帳戶,并使用該帳戶進行身份驗證。該命令提示你選擇要部署的 Firebase 項目。
該命令會構(gòu)建你的應(yīng)用,并將生產(chǎn)環(huán)境的資產(chǎn)文件上傳到 Firebase。
在下表中,你可以找到實現(xiàn)了到不同平臺部署功能的軟件包列表。每個軟件包的 ?deploy
?命令可能需要不同的命令行選項。你可以通過以下與包名稱相關(guān)的鏈接來閱讀更多內(nèi)容:
部署到 |
包 |
---|---|
@angular/fire
|
|
Azure | @azure/ng-deploy
|
Vercel | vercel init angular
|
Netlify | @netlify-builder/deploy
|
GitHub pages | angular-cli-ghpages
|
NPM | ngx-deploy-npm
|
@jefiozie/ngx-aws-deploy
|
如果要部署到自己管理的服務(wù)器上,或者缺少針對你喜歡的云平臺的構(gòu)建器,則可以創(chuàng)建支持你使用 ?ng deploy
? 命令的構(gòu)建器,或者通讀本指南以了解如何手動部署應(yīng)用程序。
最簡化的部署方式就是為開發(fā)環(huán)境構(gòu)建,并把其輸出復(fù)制到 Web 服務(wù)器上。
ng build
dist/
?)下的每個文件都復(fù)制到到服務(wù)器上的某個目錄下。index.html
? 上。 這是對應(yīng)用進行生產(chǎn)環(huán)境部署的最簡方式。
要將 Angular 應(yīng)用程序部署到 GitHub Pages,請遵循以下步驟:
git
?。創(chuàng)建存儲庫時,GitHub 已提供了這些命令,以便你可以在命令提示符下復(fù)制和粘貼它們。盡管 GitHub 會為你填上某些特定于項目的設(shè)置,但這些命令應(yīng)該類似于以下形式:git remote add origin https://github.com/your-username/your-project-name.git
git branch -M main
git push -u origin main
當(dāng)你從 GitHub 粘貼這些命令時,它們會自動運行。
gh-pages
? 的 ?git
?分支。git checkout -b gh-pages
ng build
?和以下選項,使用 Github 項目名稱構(gòu)建應(yīng)用。這里的 ?your_project_name
?是你在步驟 1 中為 GitHub 存儲庫提供的項目的名稱。確保在項目名稱的兩邊都包含有斜杠,如 ?/your_project_name/
?的斜杠。
ng build --output-path docs --base-href /your_project_name/
docs/index.html
? 復(fù)制為 ?docs/404.html
?。https://<user_name>.github.io/<project_name>
?。參閱 angular-cli-ghpages,這個包用到了全部這些特性,還提供了一些額外功能。
這一節(jié)涵蓋了你可能對服務(wù)器或準(zhǔn)備部署到服務(wù)器的文件要做的那些修改。
Angular 應(yīng)用很適合用簡單的靜態(tài) HTML 服務(wù)器提供服務(wù)。 你不需要服務(wù)端引擎來動態(tài)合成應(yīng)用頁面,因為 Angular 會在客戶端完成這件事。
如果該應(yīng)用使用 Angular 路由器,你就必須配置服務(wù)器,讓它對不存在的文件返回應(yīng)用的宿主頁(index.html)。
帶路由的應(yīng)用應(yīng)該支持“深鏈接”。 所謂深鏈接就是指一個 URL,它用于指定到應(yīng)用內(nèi)某個組件的路徑。 比如,?http://www.mysite.com/heroes/42
? 就是一個到英雄詳情頁面的深鏈接,用于顯示 ?id: 42
? 的英雄。
當(dāng)用戶從運行中的客戶端應(yīng)用導(dǎo)航到這個 URL 時,這沒問題。 Angular 路由器會攔截這個 URL,并且把它路由到正確的頁面。
但是,當(dāng)從郵件中點擊鏈接或在瀏覽器地址欄中輸入它或僅僅在英雄詳情頁刷新下瀏覽器時,所有這些操作都是由瀏覽器本身處理的,在應(yīng)用的控制范圍之外。 瀏覽器會直接向服務(wù)器請求那個 URL,路由器沒機會插手。
靜態(tài)服務(wù)器會在收到對 ?http://www.mysite.com/
? 的請求時返回 ?index.html
?,但是會拒絕對 ?http://www.mysite.com/heroes/42
? 的請求, 并返回一個 ?404 - Not Found
? 錯誤,除非,它被配置成了返回 ?index.html
?。
沒有一種配置可以適用于所有服務(wù)器。 后面這些部分會描述對常見服務(wù)器的配置方式。 這個列表雖然不夠詳盡,但可以為你提供一個良好的起點。
服務(wù)器 |
詳細信息 |
---|---|
Apache |
向 ?
|
Nginx |
使用 ?
|
Ruby |
使用 ( sinatra ) 和配置服務(wù)器 ?
|
IIS |
向 ?
|
你不能直接配置 GitHub Pages 服務(wù)器,但可以添加 404 頁面。將 ? |
|
添加重寫規(guī)則。
|
你的所有應(yīng)用程序 JavaScript 文件都必須由服務(wù)器提供出來,并將 Content-Type 標(biāo)頭設(shè)置為 ?text/javascript
? 或其他與 JavaScript 兼容的 MIME-type。
默認(rèn)情況下,大多數(shù)服務(wù)器和托管服務(wù)已經(jīng)這樣做了。
如果服務(wù)器為 JavaScript 文件配置了錯誤的 MIME 類型,將導(dǎo)致應(yīng)用程序無法啟動并出現(xiàn)以下錯誤:
Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.
如果是這種情況,你將需要檢查你的服務(wù)器配置并將其重新配置為使用 ?Content-Type: text/javascript
? 來提供 ?.js
? 文件。
Angular 開發(fā)者在向與該應(yīng)用的宿主服務(wù)器不同域的服務(wù)器發(fā)起請求時,可能會遇到一種 跨域資源共享(CORS)錯誤。 瀏覽器會阻止該請求,除非得到那臺服務(wù)器的明確許可。
客戶端應(yīng)用對這種錯誤無能為力。 服務(wù)器必須配置成可以接受來自該應(yīng)用的請求。 要了解如何對特定的服務(wù)器開啟 CORS,參閱enable-cors.org。
?production
?配置項指定如下優(yōu)化特性。
特性 |
詳細信息 |
---|---|
預(yù)先 (AOT) 編譯 |
預(yù)編譯 Angular 的組件模板。 |
生產(chǎn)模式 |
部署到啟用了生產(chǎn)模式的生產(chǎn)環(huán)境。 |
打包 |
把你的多個應(yīng)用于庫文件拼接到少量包(bundle)中。 |
縮小 |
刪除多余的空格、注釋和可選令牌。 |
丑化 |
重寫代碼,使用簡短的、不容易理解的變量名和函數(shù)名。 |
死代碼消除 |
刪除未引用過的模塊和很多未用到的代碼。 |
除了構(gòu)建期優(yōu)化之外,Angular 還支持運行期生產(chǎn)模式。Angular 應(yīng)用默認(rèn)運行在開發(fā)模式下,你可以在瀏覽器的控制臺中看到如下信息:
Angular is running in development mode.
Call `enableProdMode()` to enable production mode.
生產(chǎn)模式通過禁用僅供開發(fā)用的安全檢查和調(diào)試工具(比如,expression-changed-after-checked 檢測)來提高應(yīng)用程序性能。使用生產(chǎn)配置構(gòu)建應(yīng)用程序時會自動啟用 Angular 的運行時生產(chǎn)模式。
通過只加載應(yīng)用啟動時絕對必須的那些模塊,你可以極大縮短應(yīng)用啟動的時間。
可以配置 Angular 的路由器,來推遲所有其它模塊(及其相關(guān)代碼)的加載時機,方法有一直等到應(yīng)用啟動完畢,或者當(dāng)用到時才按需惰性加載。
不要急性(EAGERLY)導(dǎo)入來自惰性加載模塊中的任何東西
如果要惰性加載某個模塊,就要小心別在應(yīng)用啟動時要急性加載的模塊(比如根模塊 ?AppModule
?)中導(dǎo)入它。 如果那么做,該模塊就會立刻加載起來。
配置打包方式時必須考慮惰性加載。 因為默認(rèn)情況下惰性加載的模塊沒有在 JavaScript 中導(dǎo)入過,因此打包器默認(rèn)會排除它們。 打包器不認(rèn)識路由器配置,也就不能為惰性加載的模塊創(chuàng)建獨立的包。 你必須手動創(chuàng)建這些包。
CLI 會運行 Angular Ahead-of-Time Webpack 插件,它會自動識別出惰性加載的 ?NgModules
?,并為它們創(chuàng)建獨立的包。
如果你對哪些東西拖慢了應(yīng)用有更加清晰、精確的了解,就可以更好地決定優(yōu)化什么以及如何優(yōu)化。 慢的原因可能和你所想的不一樣。 你可能花費了大量的時間和金錢來優(yōu)化一些實際上無關(guān)緊要的東西,甚至可能讓應(yīng)用變得更慢。 你應(yīng)該測量應(yīng)用在運行環(huán)境中的實際行為,這才是最重要的。
Chrome DevTools 的網(wǎng)絡(luò)和性能頁是你開始學(xué)習(xí)如何測量性能的好地方。
WebPageTest工具是另一個不錯的選擇,它還能幫你驗證這次部署是否成功。
source-map-explorer 工具可以幫你在生產(chǎn)環(huán)境構(gòu)建之后探查 JavaScript 包。
安裝 ?source-map-explorer
? :
npm install source-map-explorer --save-dev
為生產(chǎn)環(huán)境構(gòu)建應(yīng)用,包括源碼映射表(source map)
ng build --source-map
在 ?dist/
? 目錄下列出生成的包。
ls dist/project-name/*.js
運行瀏覽器來生成其中一個包的圖形化表示。 下面的例子展示了 ?main
? 包的圖表。
node_modules/.bin/source-map-explorer dist/project-name/main*
?source-map-explorer
? 會分析與包一起生成的 source map,并畫出所有依賴的地圖,精確展示哪些類包含在哪個包中。
下面是范例應(yīng)用 ?cli-quickstart
? 中 ?main
?包的輸出。
HTML 的 <base href="..."/> 標(biāo)簽指定了用于解析靜態(tài)文件(如圖片、腳本和樣式表)相對地址的基地址。 比如,對于 ?<base href="/my/app/">
?,瀏覽器就會把 ?some/place/foo.jpg
? 這樣的 URL 解析成到 ?my/app/some/place/foo.jpg
? 的請求。 在導(dǎo)航期間,Angular 路由器使用 base href 作為到組件模板文件和模塊文件的基地址。
在開發(fā)期間,你通常會在存有 ?index.html
? 的目錄下啟動開發(fā)服務(wù)器。 那就是根目錄,你要在 ?index.html
? 的頂部附近添加 ?<base href="/">
?,因為 ?/
? 就是該應(yīng)用的根路徑。
但是在共享或生產(chǎn)服務(wù)器上,你可能會在子目錄下啟動服務(wù)器。 比如,當(dāng)前應(yīng)用的加載地址可能類似于 ?http://www.mysite.com/my/app
?,這里的子目錄就是 ?my/app/
?。所以你就要往服務(wù)端版本的 ?index.html
? 中添加 ?<base href="/my/app/">
?。
這里如果不配置 ?base
?標(biāo)簽,應(yīng)用就會失敗,并在瀏覽器的控制臺中為缺失的文件顯示一個 ?404 - Not Found
? 錯誤??纯此?b>試圖從哪里去查找那些文件,并據(jù)此調(diào)整 base 標(biāo)簽。
一個命令行選項,用于指定在編譯時解析圖片、腳本和樣式表等資產(chǎn)(assets)的相對 URL 的基礎(chǔ)路徑。比如:?ng build --deploy-url /my/assets
?。
?deploy url
? 和 ?base href
? 這兩個定義的作用有所重疊。
但是,定義 ?base href
? 有一些獨有的作用。
base href
? 可用于定位相對路徑模板 (HTML) 資產(chǎn)和針對相對路徑的 fetch/XMLHttpRequests。
?base href
? 也可用于定義 Angular 路由器的默認(rèn)基礎(chǔ) URL。需要進行更復(fù)雜設(shè)置的用戶可能需要在應(yīng)用程序中手動配置 ?APP_BASE_HREF
?令牌。(比如,應(yīng)用程序路由基地址是 ?/
?,但各種資產(chǎn)、腳本等都在 ?/assets/
? 下)。
與可以只在一個地方定義的 ?base href
? 不同,?deploy url
? 需要在構(gòu)建時硬編碼到應(yīng)用程序中。這意味著指定 ?deploy url
? 會降低構(gòu)建速度,但這是使用在整個應(yīng)用程序中嵌入自己的選項的代價。這也是為什么說 ?base href
? 通常是更好的選擇。
更多建議: