翻譯自 https://github.com/dojo/framework/blob/master/docs/en/building/supplemental.md
創新互聯成立于2013年,是專業互聯網技術服務公司,擁有項目網站設計制作、網站建設網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元玄武做網站,已為上家服務,為玄武各地企業和個人服務,聯系電話:18982081108
一個包就是一部分代碼,它用于表示一部分功能。可以按需異步、并行加載包。與不使用任何代碼拆分技術的應用程序相比,合理分包的應用程序可以顯著提高響應速度,需要請求的字節數更少,加載的時間更短。在處理大型應用程序時,這一點尤其重要,因為這類應用程序的大部分表現層邏輯在初始化時是不需要加載的。
Dojo 嘗試使用路由和 outlet 智能地做出選擇,自動將代碼拆分為更小的包。通常各個包內的代碼都是緊密相關的。這是構建系統內置的功能,可直接使用。但是,對于有特殊分包需求的用戶,Dojo 還允許在 .dojorc
配置文件中顯示定義包。
默認情況下,Dojo 應用程序只創建一個應用程序包。但是 @dojo/cli-build-app 提供了很多配置選項,這些選項可將應用程序拆分為較小的、可逐步加載的包。
默認情況下,Dojo 會基于應用程序的路由自動創建包。要做到這一點需要遵循以下幾條規則。
src/routes.ts
必須默認導出路由配置信息Outlet
的 render
函數必須使用內聯函數src/routes.ts
export default [
{
path: 'home',
outlet: 'home',
defaultRoute: true
},
{
path: 'about',
outlet: 'about'
},
{
path: 'profile',
outlet: 'profile'
}
];
src/App.ts
export default class App extends WidgetBase {
protected render() {
return (
<div classes={[css.root]}>
<Menu />
<div>
<Outlet key="home" id="home" renderer={() => <Home />} />
<Outlet key="about" id="about" renderer={() => <About />} />
<Outlet key="profile" id="profile" renderer={() => <Profile username="Dojo User" />} />
</div>
</div>
);
}
}
將會為應用程序的每個頂級路由生成單獨的包。在本例中,會生成一個應用程序的主包以及 src/Home
、src/About
和 src/Profile
三個包。
使用 @dojo/cli-create-app 新建一個應用程序,然后運行 npm run build
,就可看到自動分包的實際效果。Dojo 將自動為示例應用程序中的所有路由創建包。
可以在 .dojorc
配置文件中手動分包,這就為應用程序提供了一種聲明式代碼拆分的手段。當自動根據路由分包無法滿足需求時,這對于將應用程序拆分為更小的包是極其有用的。
bundles
功能是 build app 命令的一部分。配置由由一組包名和緊隨其后的文件列表或匹配符組成。
例如,以下配置將 About
和 Profile
合在一個包中,并命名為 additional.[hash].js
。在 w()
中使用的部件模塊將被自動轉換為在父部件中延遲加載的本地注冊項。
.dojorc
{
"build-app": {
"bundles": {
"additional": ["src/widgets/About", "src/widgets/Profile"]
}
}
}
如果我們想分地區創建國際化模塊,我們應該使用通配符以確保將每個語言目錄下的所有文件都會包含在內。
.dojorc
{
"build-app": {
"bundles": {
"fr": ["src/**/nls/fr/**"],
"de": ["src/**/nls/de/**"]
}
}
}
在這種情況下,Dojo 將創建名為 fr.[hash].js
的包,和名為 de.[hash].js
的包。想了解更新信息,請參閱國際化參考指南中的使用消息包。
有時,根據構建工具自動分包或者在 .dojorc
中手動定義的包中會重復包含被多個包共享的資源。有一些是無法避免的。一個避免重復的法則是嘗試將共享代碼移到應用程序依賴樹的最外圍。換句話說,就是盡可能減少共享代碼之間的依賴。如果大量的代碼在包之間共享(例如,公共的部件),請考慮將這些資源放在一個包中。
很多靜態資源,如在模塊中導入的 CSS 和圖片,在構建過程中會被自動內聯。但是,有時還需要為網站圖標(favicon)或視頻文件等靜態資源提供服務。
靜態資源存放在項目根目錄下的 assets/
文件夾中。在構建時,這些資源會被復制到應用程序構建版本的 assets/
文件夾中。
構建也會解析 src/index.html
中引用的 CSS、JavaScript 和圖片資源等,對這些資源名進行哈希處理,并在輸出文件夾中包含這些資源??梢詫?favicon 存放在 src
文件夾中,然后在 src/index.html
中引用。構建會自動對 favicon 文件名進行哈希處理,并會將文件復制到輸出文件夾中,然后重命名為 favicon.[hash].ico
。
漸進式 web 應用程序(PWA)由一系列技術和模式組成,主要用于改善用戶體驗,幫助創建更可靠和可用的應用程序。尤其是移動用戶,他們會發現應用程序能更好的集成到他們的設備中,就跟本地安裝的應用程序一樣。
漸進式 web 應用程序主要由兩種技術組成:Service Worker 和 Manifest。Dojo 的構建命令通過 .dojorc
的 pwa
對象支持這兩種技術。
Manifest 在一個 JSON 文件中描述一個應用程序,并提供了一些詳細信息,因此可以直接從萬維網安裝到設備的主屏幕上。
.dojorc
{
"build-app": {
"pwa": {
"manifest": {
"name": "Todo MVC",
"description": "A simple to-do application created with Dojo",
"icons": [
{ "src": "./favicon-16x16.png", "sizes": "16x16", "type": "image/png" },
{ "src": "./favicon-32x32.png", "sizes": "32x32", "type": "image/png" },
{ "src": "./favicon-48x48.png", "sizes": "48x48", "type": "image/png" },
{ "src": "./favicon-256x256.png", "sizes": "256x256", "type": "image/png" }
]
}
}
}
}
當提供了 manifest 信息時,dojo build
將在應用程序的 index.html
中注入必需的 <meta>
標簽。
mobile-web-app-capable="yes"
: 告知 Android 上的 Chrome 可以將此應用程序添加到用戶的主界面上。apple-mobile-web-app-capable="yes"
: 告知 iOS 設備可以將此應用程序添加到用戶的主界面上。apple-mobile-web-app-status-bar-
: 告知 iOS 設備,狀態欄使用默認外觀。apple-touch-icon="{{icon}}"
: 相當于 Manifest 中的 icons,因為 iOS 當前沒有從 Manifest 中讀取 icons,所以需要為 icons 數組中每張圖片單獨注入一個 meta 標簽。Service worder 是一種 web worker,能夠攔截網絡請求、緩存和提供資源。Dojo 的 build 命令能夠自動構建功能全面的 service worker,它會在啟動時激活,然后使用配置文件完成預緩存和自定義路由處理。
例如,我們編寫一個配置文件來創建一個簡單的 service worker,它會緩存除了 admin 包之外的所有應用程序包,也會緩存應用程序最近訪問的圖像和文章。
.dojorc
{
"build-app": {
"pwa": {
"serviceWorker": {
"cachePrefix": "my-app",
"excludeBundles": ["admin"],
"routes": [
{
"urlPattern": ".*\\.(png|jpg|gif|svg)",
"strategy": "cacheFirst",
"cacheName": "my-app-images",
"expiration": { "maxEntries": 10, "maxAgeSeconds": 604800 }
},
{
"urlPattern": "http://my-app-url.com/api/articles",
"strategy": "cacheFirst",
"expiration": { "maxEntries": 25, "maxAgeSeconds": 86400 }
}
]
}
}
}
}
在底層,@dojo/webpack-contrib
中的 ServicerWorkerPlugin
用于生成 service worker,它的所有選項都是有效的 pwa.serviceWorker
屬性。
屬性 | 類型 | 可選 | 描述 |
---|---|---|---|
bundles | string[] |
是 | 需要進行預緩存的一組包。默認是所有包。 |
cachePrefix | string |
是 | 在運行時進行預緩存使用的前綴。 |
clientsClaim | boolean |
是 | Service worker 是否要在開始激活時控制客戶端。默認為 false 。 |
excludeBundles | string[] |
是 | 要從預緩存中排除的一組包。默認為 [] 。 |
importScripts | string[] |
是 | 需要在 service worker 中加載的一組腳本的路徑。 |
precache | object |
是 | 描述預緩存配置選項的對象(見下文)。 |
routes | object[] |
是 | 一組描述要在運行時緩存的配置對象(見下文)。 |
skipWaiting | boolean |
是 | Service worker 是否要跳過“等待”生命周期。 |
precache
選項使用以下選項控制預緩存行為:
屬性 | 類型 | 可選 | 描述 |
---|---|---|---|
baseDir | string |
是 | 匹配 include 時使用的根目錄。 |
ignore | string[] |
是 | 一組通配符模式的字符串,當生成預緩存項時用于匹配需要忽略的文件。默認為 [ 'node_modules/**/*' ] 。 |
include | string or string[] |
是 | 一個或者一組通配符模式的字符串,用于匹配 precache 應該包含的文件。默認是構建管道中的所有文件。 |
index | string |
是 | 如果請求以 / 結尾的 URL 失敗,則應該查找的 index 文件名。默認為 'index.html' 。 |
maxCacheSize | number |
是 | 往預緩存中添加的每一個文件不應超過的最大字節數。默認為 2097152 (2 MB)。 |
strict | boolean |
是 | 如果為 true ,則 include 模式匹配到一個不存在的文件夾時,構建就會失敗。默認為 true 。 |
symlinks | boolean |
是 | 當生成預緩存時是否允許軟連接(symlinks)。默認為 true 。 |
除了預緩存之外,還可以為特定路由提供緩存策略,以確定它們是否可以緩存以及如何緩存。routes
選項是一組包含以下屬性的對象:
屬性 | 類型 | 可選 | 描述 |
---|---|---|---|
urlPattern | string |
否 | 用于匹配特定路由的模式字符串(會被轉換為正則表達式)。 |
strategy | string |
否 | 緩存策略(見下文)。 |
options | object |
是 | 一個描述附加選項的對象。每個選項的詳情如下。 |
cacheName | string |
是 | 路由使用的緩存名稱。注意 cachePrefix 不會 添加到緩存名前。默認為主運行時緩存(${cachePrefix}-runtime-${domain} )。 |
cacheableResponse | object |
是 | 使用 HTTP 狀態碼或者報頭(Header)信息來決定是否可以緩存響應的內容。此對象有兩個可選屬性:statuses 和 headers 。statuses 是一組對緩存生效的狀態碼。headers 是一組 HTTP 的 header 和 value 鍵值對;至少要與一個報頭匹配,響應才會被視為有效。當 strategy 的值是 'cacheFirst' 時,默認為 { statuses: [ 200 ] } ;當 strategy 的值為 networkFirst 或者 staleWhileRevalidate 時,默認為 { statuses: [0, 200] } |
expiration | object |
是 | 控制如何讓緩存失效。此對象有兩個可選屬性。maxEntries 是任何時間可以緩存的響應個數。一旦超過此最大值,就會刪除最舊的條目。maxAgeSeconds 是一個響應能緩存的最長時間(以秒為單位),超過此時長就會被刪除。 |
networkTimeoutSeconds | number |
是 | 與 networkFirst 策略一起使用,指定當網絡請求的響應多久沒有返回時就從緩存中獲取資源,單位為秒。 |
目前支持四種路由策略:
networkFirst
嘗試通過網絡加載資源,如果請求失敗或超時才從緩存中獲取資源。對于頻繁更改或者可能頻繁更改(即沒有版本控制)的資源,這是一個很有用的策略。cacheFirst
優先從緩存中加載資源,如果緩存中不存在,則通過網絡獲取。這對于很少更改或者能緩存很長一段時間的資源(受版本控制的資源)來說是最好的策略。networkOnly
強制始終通過網絡獲取資源,對于無需離線處理的資源是很有用的策略。staleWhileRevalidate
同時從緩存和網絡中請求資源。網絡成功響應后都會更新緩存。此策略最適用于不需要持續更新的資源,比如用戶信息。但是,當獲取第三方資源時沒有發送 CORS 報頭,就無法讀取響應的內容或驗證狀態碼。因此,可能會緩存錯誤的響應。在這種情況下,networkFirst
策略可能更適合。構建時渲染(Build-time rendering,簡稱 BTR)在構建過程中將一個路由渲染為一個 HTML,并將在初始視圖中顯示的、關鍵的 CSS 和資源嵌入到頁面中。Dojo 能預渲染路由使用的初始 HTML,并直接注入到頁面中,這樣會帶來很多與服務器端渲染(***)相同的好處,如性能提升、搜索引擎優化且沒有引入 *** 的復雜性。
首先確保 index.html
中包含一個擁有 id
屬性的 DOM 節點。Dojo 的虛擬 DOM 會使用這個節點來比較和渲染應用程序的 HTML。BTR 需要此設置,這樣它就能渲染在構建階段生成的 HTML。這將會為路由創建一個響應非常快的初始渲染。
index.html
<!DOCTYPE html>
<html lang="en-us">
<head>
<title>sample-app</title>
<meta name="theme-color" content="#222127" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="app"></div>
</body>
</html>
然后將應用程序掛載到指定的 DOM 節點上:
main.ts
const r = renderer(() => w(App, {}));
const domNode = document.getElementById('app') as HTMLElement;
r.mount({ registry, domNode });
然后更新項目的 .dojorc
配置文件,設置根 DOM 節點的 id
和在構建時要渲染的路由。
.dojorc
{
"build-app": {
"build-time-render": {
"root": "app",
"paths": [
"#home",
{
"path": "#comments/9999",
"match": ["#comments/.*"]
}
]
}
}
}
此配置描述了兩個路由。一個是 home
路由,一個是較復雜的 comments
路由。comments
是一個比較復雜的路由,需要傳入參數。match
參數用于確保在構建時為此路由生成的 HTML 可以應用到與此正則表達式匹配的任何路由上。
BTR 在構建時為每個渲染路徑(path)生成一份屏幕快照,存在 ./output/info/screenshots
文件夾中。
構建時渲染支持使用 @dojo/framework/routing/history/HashHistory
或 @dojo/framework/routing/history/StateHistory
history 管理器的應用程序。當使用 HashHistory
時,確保所有的路徑都是以 #
字符開頭。
build-time-render
功能標記運行時渲染公開了一個 build-time-render
功能標記,可用于跳過在構建時不能執行的功能。這樣在創建一個初始渲染時,就可以避免對外部系統調用 fetch
,而是提供靜態數據。
if (!has('build-time-render')) {
const response = await fetch(/* remote JSON */);
return response.json();
} else {
return Promise.resolve({
/* predefined Object */
});
}
Dojo 提供了一個 block 系統,在構建階段的渲染過程中會執行 Node.js 代碼。執行的結果會被寫入到緩存中,然后在瀏覽器運行階段會以相同的方式、透明的使用這些緩存。這就為使用一些瀏覽器中無法實現或者性能不佳的操作開辟了新的機會。
例如,Dojo 的 block 模塊可以讀取一組 markdown 文件,將其轉換為 VNode,并使它們可以在應用程序中渲染,所有這些都可在構建時執行。然后 Dojo block 模塊的構建結果會緩存在應用程序的包中,以便在運行時在瀏覽器中使用。
Dojo block 模塊的用法與在 Dojo 部件中使用其它 meta 的用法類似。因此無需大量的配置或其他編寫模式。
例如,block 模塊讀取一個文本文件,然后將內容返回給應用程序。
src/blocks/read-file.ts
import * as fs from 'fs';
import { resolve } from 'path';
export default (path: string) => {
path = resolve(__dirname, path);
return fs.readFileSync(path, 'utf8');
};
src/widgets/MyBlockWidget.tsx
import Block from '@dojo/framework/core/meta/Block';
import WidgetBase from '@dojo/framework/core/WidgetBase';
import { v } from '@dojo/framework/core/vdom';
import readFile from '../blocks/read-file';
export default class MyBlockWidget extends WidgetBase {
protected render() {
const message = this.meta(Block).run(readFile)('../content/hello-dojo-blocks.txt');
return v('div', [message]);
}
}
這個部件會在構建階段運行 src/blocks/read-file.ts
模塊來讀取指定文件的內容。然后將內容作為文本節點,用作部件 VDOM 輸出的子節點。
構建工具的靜態代碼分析工具能夠從它創建的包中移除無用的代碼。命名的條件塊是使用 dojo 框架的 has
模塊定義的,并且可以在 .dojorc
中靜態設置為 true 或 false,然后在構建階段移除。
main.ts
import has from '@dojo/framework/has';
if (has('production')) {
console.log('Starting in production');
} else {
console.log('Starting in dev mode');
}
export const mode = has('production') ? 'dist' : 'dev';
.dojorc
{
"build-app": {
"features": {
"production": true
}
}
}
上述的 production
功能將構建生產版本(dist
模式)設置為 true
。構建系統使用 @dojo/framework/has
將代碼標記為無法訪問,并在構建時移除這些無用的代碼。
比如,上述代碼將重寫為:
static-build-loader 輸出
import has from '@dojo/framework/has';
if (true) {
console.log('Starting in production');
} else {
console.log('Starting in dev mode');
}
export const mode = true ? 'dist' : 'dev';
然后,構建工具的無用分支移除工具將移除無用的代碼。
Uglify 輸出
console.log('Starting in production');
export const mode = 'dist';
任何沒有被靜態斷言的功能都不會被重寫。這就允許在運行時來確定是否存在這個功能。
構建系統已提供以下功能(feature),用于幫助識別特定的環境或操作模式。
功能標記 | 描述 |
---|---|
debug |
提供了一種為代碼創建代碼路徑的方法,該代碼路徑僅在調試或者提供更強的診斷時有用,在為 生產 構建時是不需要的。默認為 true ,但在構建生產版本時應該靜態地配置為 false 。 |
host-browser |
確定當前環境下 global 上下文中是否包含 window 和 document 對象,因此通??梢园踩丶僭O代碼運行在瀏覽器環境下。 |
host-node |
嘗試檢測當前環境是不是 node 環境。 |
build-time-render |
在構建期間渲染時由 BTR 系統靜態定義。 |
通常不能被打包的非模塊化庫或者獨立的應用程序,如果需要引入到 dojo 應用程序中,則可以通過提供一個 require
或 define
實現,并在項目的 .dojorc
文件中做一些配置。
要配置外部依賴項,則需要為 build-app
配置對象設置 externals
屬性。externals
是一個對象,包含以下兩個屬性:
outputPath
: 一個可選屬性,指定一個將文件復制到何處的輸出路徑。dependencies
: 一個必填的數組,定義哪些模塊應該通過外部加載器加載,以及在構建時應該包含哪些文件。每個記錄可以是以下兩種類型之一:
屬性 | 類型 | 可選 | 描述 |
---|---|---|---|
from |
string |
否 | 相對于項目根目錄的路徑,指定位于何處的文件夾或目錄要復制到已構建應用程序中。 |
to |
string |
是 | 一個路徑,表示將 from 路徑下的依賴復制到何處的目標路徑。默認情況下,依賴會被復制到 ${externalsOutputPath}/${to} ;如果沒有設置 to ,依賴會被復制到 ${externalsOutputPath}/${from} 。如果路徑中包含 . 字符或者路徑表示的是一個文件夾,則需要以正斜杠結尾。 |
name |
string |
是 | 在應用程序代碼中引用的模塊 id 或者全局變量名。 |
inject |
string, string[], or boolean |
是 | 此屬性表示這個依賴定義的(或者包含的),要在頁面中加載的腳本或樣式文件。如果 inject 的值為 true ,那么就會在頁面中加載 to 或 from 指定位置的文件。如果依賴的是文件夾,則 inject 可以被設置為一個或者一組字符串,來定義一個或多個要注入的文件。inject 中的每個路徑都應該是相對于 ${externalsOutputPath}/${to} 或 ${externalsOutputPath}/${from} (具體取決于是否指定了 to )。 |
type |
'root' or 'umd' or 'amd' or 'commonjs' or 'commonjs2' |
是 | 強制模塊用指定的方法解析。如果是 AMD 風格,則必須使用 umd 或 amd 。如果是 node 風格則必須使用 commonjs ,并且值為 root 時以全局的方式訪問對象。 |
例如,以下配置會將 src/legacy/layer.js
注入到應用程序頁面中;注入定義了 MyGlobal
全局變量的文件;聲明模塊 a
和 b
為外部依賴,且要委托給外部層;然后復制 node_modules/legacy-dep
下的文件,并將其中的幾個文件注入到頁面中。所有文件都將被復制到 externals
文件夾中,也可以使用 externals
配置中的 outputPath
屬性來重新指定文件夾。
{
"build-app": {
"externals": {
"dependencies": [
"a",
"b",
{
"from": "node_modules/GlobalLibrary.js",
"to": "GlobalLibrary.js",
"name": "MyGlobal",
"inject": true
},
{ "from": "src/legacy/layer.js", "to": "legacy/layer.js", "inject": true },
{
"from": "node_modules/legacy-dep",
"to": "legacy-dep/",
"inject": ["moduleA/layer.js", "moduleA/layer.css", "moduleB/layer.js"]
}
]
}
}
}
externals
中包含的依賴項的類型會被安裝到 node_modules/@types
中,這跟其它依賴項是一樣的。
因為這些文件位于主構建(main build)之外,所以在生產構建中不會執行版本控制或哈希處理(在 inject
中指定資源的鏈接除外)??梢栽?to
屬性中指定版本號,將依賴復制到對應版本的文件夾下,這樣就能避免緩存不同版本的文件。
Dojo 的構建管道為項目提供了一個端到端的工具鏈,但是,在極少數情況下,可能需要自定義工具鏈。只要將項目脫離 Dojo 的構建管道,就可以自定義工具鏈。
將項目脫離構建管道,是一個不可逆的、單向過程,它會導出 Webpack、Intern 以及 dojo
命令使用的其他項目的底層配置文件。如果提供的生成工具無法提供所需的功能或特性,推薦的方法是 fork 選定的構建命令,然后往工具中添加額外的功能。Dojo 的 CLI 本質上是專門按模塊化設計的,考慮到了這個用例。
要將一個項目脫離出 dojo 構建管道,請使用 dojo eject
命令,它將提示你確實已明白過程是不可逆的。這個導出過程將所有已安裝的 dojo 命令中導出的配置信息存到 config
文件夾中。這個過程也會安裝一些項目需要的附加依賴。
現在項目已經是一個 webpack 項目。可以通過修改 config/build-app/base.config.js
來更改構建配置。
然后,可以通過運行 webpack 的構建命令并提供配置項來觸發一個構建。此外,使用 webpack 的 env 標記(例如 --env.mode=dev)來指定模式,默認為 dist。
./node_modules/.bin/webpack --config=config/build-app/ejected.config.js --env.mode=[mode]
名稱欄目:DojoBuild進階
轉載源于:http://www.2m8n56k.cn/article44/ggdihe.html
成都網站建設公司_創新互聯,為您提供標簽優化、微信公眾號、網站內鏈、電子商務、自適應網站、網站收錄
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:[email protected]。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯