Dojo Build 進(jìn)階

翻譯自 https://github.com/dojo/framework/blob/master/docs/en/building/supplemental.md

創(chuàng)建包

一個包就是一部分代碼,它用于表示一部分功能。可以按需異步涛菠、并行加載包棍潘。與不使用任何代碼拆分技術(shù)的應(yīng)用程序相比紫岩,合理分包的應(yīng)用程序可以顯著提高響應(yīng)速度啸澡,需要請求的字節(jié)數(shù)更少,加載的時間更短烂叔。在處理大型應(yīng)用程序時,這一點尤其重要固歪,因為這類應(yīng)用程序的大部分表現(xiàn)層邏輯在初始化時是不需要加載的蒜鸡。

Dojo 嘗試使用路由和 outlet 智能地做出選擇,自動將代碼拆分為更小的包牢裳。通常各個包內(nèi)的代碼都是緊密相關(guān)的逢防。這是構(gòu)建系統(tǒng)內(nèi)置的功能,可直接使用蒲讯。但是忘朝,對于有特殊分包需求的用戶,Dojo 還允許在 .dojorc 配置文件中顯示定義包判帮。

默認(rèn)情況下局嘁,Dojo 應(yīng)用程序只創(chuàng)建一個應(yīng)用程序包溉箕。但是 @dojo/cli-build-app 提供了很多配置選項,這些選項可將應(yīng)用程序拆分為較小的悦昵、可逐步加載的包肴茄。

使用路由自動分包

默認(rèn)情況下,Dojo 會基于應(yīng)用程序的路由自動創(chuàng)建包旱捧。要做到這一點需要遵循以下幾條規(guī)則独郎。

  1. src/routes.ts 必須默認(rèn)導(dǎo)出路由配置信息
  2. 部件所屬的模塊必須默認(rèn)導(dǎo)出部件
  3. Outletrender 函數(shù)必須使用內(nèi)聯(lián)函數(shù)

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>
        );
    }
}

將會為應(yīng)用程序的每個頂級路由生成單獨的包。在本例中枚赡,會生成一個應(yīng)用程序的主包以及 src/Home氓癌、src/Aboutsrc/Profile 三個包。

使用 @dojo/cli-create-app 新建一個應(yīng)用程序贫橙,然后運行 npm run build贪婉,就可看到自動分包的實際效果。Dojo 將自動為示例應(yīng)用程序中的所有路由創(chuàng)建包卢肃。

手動分包

可以在 .dojorc 配置文件中手動分包疲迂,這就為應(yīng)用程序提供了一種聲明式代碼拆分的手段。當(dāng)自動根據(jù)路由分包無法滿足需求時莫湘,這對于將應(yīng)用程序拆分為更小的包是極其有用的尤蒿。

bundles 功能是 build app 命令的一部分。配置由由一組包名和緊隨其后的文件列表或匹配符組成幅垮。

例如腰池,以下配置將 AboutProfile 合在一個包中,并命名為 additional.[hash].js忙芒。在 w() 中使用的部件模塊將被自動轉(zhuǎn)換為在父部件中延遲加載的本地注冊項示弓。

.dojorc

{
    "build-app": {
        "bundles": {
            "additional": ["src/widgets/About", "src/widgets/Profile"]
        }
    }
}

如果我們想分地區(qū)創(chuàng)建國際化模塊,我們應(yīng)該使用通配符以確保將每個語言目錄下的所有文件都會包含在內(nèi)呵萨。

.dojorc

{
    "build-app": {
        "bundles": {
            "fr": ["src/**/nls/fr/**"],
            "de": ["src/**/nls/de/**"]
        }
    }
}

在這種情況下奏属,Dojo 將創(chuàng)建名為 fr.[hash].js 的包,和名為 de.[hash].js 的包潮峦。想了解更新信息囱皿,請參閱國際化參考指南中的使用消息包

分包注意事項

有時跑杭,根據(jù)構(gòu)建工具自動分包或者在 .dojorc 中手動定義的包中會重復(fù)包含被多個包共享的資源铆帽。有一些是無法避免的。一個避免重復(fù)的法則是嘗試將共享代碼移到應(yīng)用程序依賴樹的最外圍德谅。換句話說爹橱,就是盡可能減少共享代碼之間的依賴。如果大量的代碼在包之間共享(例如,公共的部件)愧驱,請考慮將這些資源放在一個包中慰技。

靜態(tài)資源

很多靜態(tài)資源,如在模塊中導(dǎo)入的 CSS 和圖片组砚,在構(gòu)建過程中會被自動內(nèi)聯(lián)吻商。但是,有時還需要為網(wǎng)站圖標(biāo)(favicon)或視頻文件等靜態(tài)資源提供服務(wù)糟红。

靜態(tài)資源存放在項目根目錄下的 assets/ 文件夾中艾帐。在構(gòu)建時,這些資源會被復(fù)制到應(yīng)用程序構(gòu)建版本的 assets/ 文件夾中盆偿。

構(gòu)建也會解析 src/index.html 中引用的 CSS柒爸、JavaScript 和圖片資源等慢洋,對這些資源名進(jìn)行哈希處理轮纫,并在輸出文件夾中包含這些資源∮倒樱可以將 favicon 存放在 src 文件夾中求橄,然后在 src/index.html 中引用今野。構(gòu)建會自動對 favicon 文件名進(jìn)行哈希處理,并會將文件復(fù)制到輸出文件夾中罐农,然后重命名為 favicon.[hash].ico条霜。

漸進(jìn)式 web 應(yīng)用程序

漸進(jìn)式 web 應(yīng)用程序(PWA)由一系列技術(shù)和模式組成,主要用于改善用戶體驗涵亏,幫助創(chuàng)建更可靠和可用的應(yīng)用程序蛔外。尤其是移動用戶,他們會發(fā)現(xiàn)應(yīng)用程序能更好的集成到他們的設(shè)備中溯乒,就跟本地安裝的應(yīng)用程序一樣。

漸進(jìn)式 web 應(yīng)用程序主要由兩種技術(shù)組成:Service Worker 和 Manifest豹爹。Dojo 的構(gòu)建命令通過 .dojorcpwa 對象支持這兩種技術(shù)裆悄。

Manifest

Manifest 在一個 JSON 文件中描述一個應(yīng)用程序,并提供了一些詳細(xì)信息臂聋,因此可以直接從萬維網(wǎng)安裝到設(shè)備的主屏幕上光稼。

.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" }
                ]
            }
        }
    }
}

當(dāng)提供了 manifest 信息時,dojo build 將在應(yīng)用程序的 index.html 中注入必需的 <meta> 標(biāo)簽孩等。

  • mobile-web-app-capable="yes": 告知 Android 上的 Chrome 可以將此應(yīng)用程序添加到用戶的主界面上艾君。
  • apple-mobile-web-app-capable="yes": 告知 iOS 設(shè)備可以將此應(yīng)用程序添加到用戶的主界面上。
  • apple-mobile-web-app-status-bar-style="default": 告知 iOS 設(shè)備肄方,狀態(tài)欄使用默認(rèn)外觀冰垄。
  • apple-touch-icon="{{icon}}": 相當(dāng)于 Manifest 中的 icons,因為 iOS 當(dāng)前沒有從 Manifest 中讀取 icons权她,所以需要為 icons 數(shù)組中每張圖片單獨注入一個 meta 標(biāo)簽虹茶。

Service worker

Service worder 是一種 web worker逝薪,能夠攔截網(wǎng)絡(luò)請求、緩存和提供資源蝴罪。Dojo 的 build 命令能夠自動構(gòu)建功能全面的 service worker董济,它會在啟動時激活,然后使用配置文件完成預(yù)緩存和自定義路由處理要门。

例如虏肾,我們編寫一個配置文件來創(chuàng)建一個簡單的 service worker,它會緩存除了 admin 包之外的所有應(yīng)用程序包欢搜,也會緩存應(yīng)用程序最近訪問的圖像和文章封豪。

.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 }
                    }
                ]
            }
        }
    }
}

ServiceWorker 配置

在底層,@dojo/webpack-contrib 中的 ServicerWorkerPlugin 用于生成 service worker狂巢,它的所有選項都是有效的 pwa.serviceWorker 屬性撑毛。

屬性 類型 可選 描述
bundles string[] 需要進(jìn)行預(yù)緩存的一組包。默認(rèn)是所有包唧领。
cachePrefix string 在運行時進(jìn)行預(yù)緩存使用的前綴藻雌。
clientsClaim boolean Service worker 是否要在開始激活時控制客戶端。默認(rèn)為 false斩个。
excludeBundles string[] 要從預(yù)緩存中排除的一組包胯杭。默認(rèn)為 []
importScripts string[] 需要在 service worker 中加載的一組腳本的路徑受啥。
precache object 描述預(yù)緩存配置選項的對象(見下文)做个。
routes object[] 一組描述要在運行時緩存的配置對象(見下文)。
skipWaiting boolean Service worker 是否要跳過“等待”生命周期滚局。

預(yù)緩存

precache 選項使用以下選項控制預(yù)緩存行為:

屬性 類型 可選 描述
baseDir string 匹配 include 時使用的根目錄居暖。
ignore string[] 一組通配符模式的字符串,當(dāng)生成預(yù)緩存項時用于匹配需要忽略的文件藤肢。默認(rèn)為 [ 'node_modules/**/*' ]太闺。
include string or string[] 一個或者一組通配符模式的字符串,用于匹配 precache 應(yīng)該包含的文件嘁圈。默認(rèn)是構(gòu)建管道中的所有文件省骂。
index string 如果請求以 / 結(jié)尾的 URL 失敗,則應(yīng)該查找的 index 文件名最住。默認(rèn)為 'index.html'钞澳。
maxCacheSize number 往預(yù)緩存中添加的每一個文件不應(yīng)超過的最大字節(jié)數(shù)。默認(rèn)為 2097152 (2 MB)涨缚。
strict boolean 如果為 true轧粟,則 include 模式匹配到一個不存在的文件夾時,構(gòu)建就會失敗。默認(rèn)為 true逃延。
symlinks boolean 當(dāng)生成預(yù)緩存時是否允許軟連接(symlinks)览妖。默認(rèn)為 true

運行時緩存

除了預(yù)緩存之外揽祥,還可以為特定路由提供緩存策略讽膏,以確定它們是否可以緩存以及如何緩存。routes 選項是一組包含以下屬性的對象:

屬性 類型 可選 描述
urlPattern string 用于匹配特定路由的模式字符串(會被轉(zhuǎn)換為正則表達(dá)式)拄丰。
strategy string 緩存策略(見下文)府树。
options object 一個描述附加選項的對象。每個選項的詳情如下料按。
cacheName string 路由使用的緩存名稱奄侠。注意 cachePrefix 不會 添加到緩存名前。默認(rèn)為主運行時緩存(${cachePrefix}-runtime-${domain})载矿。
cacheableResponse object 使用 HTTP 狀態(tài)碼或者報頭(Header)信息來決定是否可以緩存響應(yīng)的內(nèi)容垄潮。此對象有兩個可選屬性:statusesheadersstatuses 是一組對緩存生效的狀態(tài)碼闷盔。headers 是一組 HTTP 的 header 和 value 鍵值對弯洗;至少要與一個報頭匹配,響應(yīng)才會被視為有效逢勾。當(dāng) strategy 的值是 'cacheFirst' 時牡整,默認(rèn)為 { statuses: [ 200 ] };當(dāng) strategy 的值為 networkFirst 或者 staleWhileRevalidate 時溺拱,默認(rèn)為 { statuses: [0, 200] }
expiration object 控制如何讓緩存失效逃贝。此對象有兩個可選屬性。maxEntries 是任何時間可以緩存的響應(yīng)個數(shù)迫摔。一旦超過此最大值沐扳,就會刪除最舊的條目。maxAgeSeconds 是一個響應(yīng)能緩存的最長時間(以秒為單位)句占,超過此時長就會被刪除迫皱。
networkTimeoutSeconds number networkFirst 策略一起使用,指定當(dāng)網(wǎng)絡(luò)請求的響應(yīng)多久沒有返回時就從緩存中獲取資源辖众,單位為秒。

目前支持四種路由策略:

  • networkFirst 嘗試通過網(wǎng)絡(luò)加載資源和敬,如果請求失敗或超時才從緩存中獲取資源凹炸。對于頻繁更改或者可能頻繁更改(即沒有版本控制)的資源,這是一個很有用的策略昼弟。
  • cacheFirst 優(yōu)先從緩存中加載資源啤它,如果緩存中不存在,則通過網(wǎng)絡(luò)獲取。這對于很少更改或者能緩存很長一段時間的資源(受版本控制的資源)來說是最好的策略变骡。
  • networkOnly 強(qiáng)制始終通過網(wǎng)絡(luò)獲取資源离赫,對于無需離線處理的資源是很有用的策略。
  • staleWhileRevalidate 同時從緩存和網(wǎng)絡(luò)中請求資源塌碌。網(wǎng)絡(luò)成功響應(yīng)后都會更新緩存渊胸。此策略最適用于不需要持續(xù)更新的資源,比如用戶信息台妆。但是翎猛,當(dāng)獲取第三方資源時沒有發(fā)送 CORS 報頭,就無法讀取響應(yīng)的內(nèi)容或驗證狀態(tài)碼接剩。因此切厘,可能會緩存錯誤的響應(yīng)。在這種情況下懊缺,networkFirst 策略可能更適合疫稿。

構(gòu)建時渲染

構(gòu)建時渲染(Build-time rendering,簡稱 BTR)在構(gòu)建過程中將一個路由渲染為一個 HTML鹃两,并將在初始視圖中顯示的遗座、關(guān)鍵的 CSS 和資源嵌入到頁面中。Dojo 能預(yù)渲染路由使用的初始 HTML怔毛,并直接注入到頁面中员萍,這樣會帶來很多與服務(wù)器端渲染(SSR)相同的好處,如性能提升拣度、搜索引擎優(yōu)化且沒有引入 SSR 的復(fù)雜性碎绎。

使用 BTR

首先確保 index.html 中包含一個擁有 id 屬性的 DOM 節(jié)點。Dojo 的虛擬 DOM 會使用這個節(jié)點來比較和渲染應(yīng)用程序的 HTML抗果。BTR 需要此設(shè)置筋帖,這樣它就能渲染在構(gòu)建階段生成的 HTML。這將會為路由創(chuàng)建一個響應(yīng)非吃┝螅快的初始渲染日麸。

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>

然后將應(yīng)用程序掛載到指定的 DOM 節(jié)點上:

main.ts

const r = renderer(() => w(App, {}));
const domNode = document.getElementById('app') as HTMLElement;
r.mount({ registry, domNode });

然后更新項目的 .dojorc 配置文件,設(shè)置根 DOM 節(jié)點的 id 和在構(gòu)建時要渲染的路由逮光。

.dojorc

{
    "build-app": {
        "build-time-render": {
            "root": "app",
            "paths": [
                "#home",
                {
                    "path": "#comments/9999",
                    "match": ["#comments/.*"]
                }
            ]
        }
    }
}

此配置描述了兩個路由代箭。一個是 home 路由,一個是較復(fù)雜的 comments 路由涕刚。comments 是一個比較復(fù)雜的路由嗡综,需要傳入?yún)?shù)。match 參數(shù)用于確保在構(gòu)建時為此路由生成的 HTML 可以應(yīng)用到與此正則表達(dá)式匹配的任何路由上杜漠。

BTR 在構(gòu)建時為每個渲染路徑(path)生成一份屏幕快照极景,存在 ./output/info/screenshots 文件夾中察净。

History 管理器

構(gòu)建時渲染支持使用 @dojo/framework/routing/history/HashHistory@dojo/framework/routing/history/StateHistory history 管理器的應(yīng)用程序。當(dāng)使用 HashHistory 時盼樟,確保所有的路徑都是以 # 字符開頭氢卡。

build-time-render 功能標(biāo)記

運行時渲染公開了一個 build-time-render 功能標(biāo)記,可用于跳過在構(gòu)建時不能執(zhí)行的功能晨缴。這樣在創(chuàng)建一個初始渲染時译秦,就可以避免對外部系統(tǒng)調(diào)用 fetch,而是提供靜態(tài)數(shù)據(jù)喜庞。

if (!has('build-time-render')) {
    const response = await fetch(/* remote JSON */);
    return response.json();
} else {
    return Promise.resolve({
        /* predefined Object */
    });
}

Dojo Blocks

Dojo 提供了一個 block 系統(tǒng)诀浪,在構(gòu)建階段的渲染過程中會執(zhí)行 Node.js 代碼。執(zhí)行的結(jié)果會被寫入到緩存中延都,然后在瀏覽器運行階段會以相同的方式雷猪、透明的使用這些緩存。這就為使用一些瀏覽器中無法實現(xiàn)或者性能不佳的操作開辟了新的機(jī)會晰房。

例如求摇,Dojo 的 block 模塊可以讀取一組 markdown 文件,將其轉(zhuǎn)換為 VNode殊者,并使它們可以在應(yīng)用程序中渲染与境,所有這些都可在構(gòu)建時執(zhí)行。然后 Dojo block 模塊的構(gòu)建結(jié)果會緩存在應(yīng)用程序的包中猖吴,以便在運行時在瀏覽器中使用摔刁。

Dojo block 模塊的用法與在 Dojo 部件中使用其它 meta 的用法類似。因此無需大量的配置或其他編寫模式海蔽。

例如共屈,block 模塊讀取一個文本文件,然后將內(nèi)容返回給應(yīng)用程序党窜。

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]);
    }
}

這個部件會在構(gòu)建階段運行 src/blocks/read-file.ts 模塊來讀取指定文件的內(nèi)容拗引。然后將內(nèi)容作為文本節(jié)點,用作部件 VDOM 輸出的子節(jié)點幌衣。

按條件選取代碼

構(gòu)建工具的靜態(tài)代碼分析工具能夠從它創(chuàng)建的包中移除無用的代碼矾削。命名的條件塊是使用 dojo 框架的 has 模塊定義的,并且可以在 .dojorc 中靜態(tài)設(shè)置為 true 或 false豁护,然后在構(gòu)建階段移除哼凯。

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 功能將構(gòu)建生產(chǎn)版本dist 模式)設(shè)置為 true。構(gòu)建系統(tǒng)使用 @dojo/framework/has 將代碼標(biāo)記為無法訪問楚里,并在構(gòu)建時移除這些無用的代碼挡逼。

比如,上述代碼將重寫為:

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';

然后腻豌,構(gòu)建工具的無用分支移除工具將移除無用的代碼家坎。

Uglify 輸出

console.log('Starting in production');
export const mode = 'dist';

任何沒有被靜態(tài)斷言的功能都不會被重寫。這就允許在運行時來確定是否存在這個功能吝梅。

已提供的功能

構(gòu)建系統(tǒng)已提供以下功能(feature)虱疏,用于幫助識別特定的環(huán)境或操作模式。

功能標(biāo)記 描述
debug 提供了一種為代碼創(chuàng)建代碼路徑的方法苏携,該代碼路徑僅在調(diào)試或者提供更強(qiáng)的診斷時有用做瞪,在為 生產(chǎn) 構(gòu)建時是不需要的。默認(rèn)為 true右冻,但在構(gòu)建生產(chǎn)版本時應(yīng)該靜態(tài)地配置為 false装蓬。
host-browser 確定當(dāng)前環(huán)境下 global 上下文中是否包含 windowdocument 對象,因此通成磁ぃ可以安全地假設(shè)代碼運行在瀏覽器環(huán)境下牍帚。
host-node 嘗試檢測當(dāng)前環(huán)境是不是 node 環(huán)境。
build-time-render 在構(gòu)建期間渲染時由 BTR 系統(tǒng)靜態(tài)定義乳蛾。

外部依賴

通常不能被打包的非模塊化庫或者獨立的應(yīng)用程序暗赶,如果需要引入到 dojo 應(yīng)用程序中,則可以通過提供一個 requiredefine 實現(xiàn)肃叶,并在項目的 .dojorc 文件中做一些配置蹂随。

要配置外部依賴項,則需要為 build-app 配置對象設(shè)置 externals 屬性因惭。externals 是一個對象岳锁,包含以下兩個屬性:

  • outputPath: 一個可選屬性,指定一個將文件復(fù)制到何處的輸出路徑蹦魔。
  • dependencies: 一個必填的數(shù)組激率,定義哪些模塊應(yīng)該通過外部加載器加載,以及在構(gòu)建時應(yīng)該包含哪些文件版姑。每個記錄可以是以下兩種類型之一:
    • 一個字符串柱搜,表示應(yīng)該使用外部加載器加載此路徑及其所有子路徑。
    • 一個對象剥险,為需要復(fù)制到構(gòu)建版應(yīng)用程序的依賴提供附加配置項聪蘸。此對象具有以下屬性:
屬性 類型 可選 描述
from string 相對于項目根目錄的路徑,指定位于何處的文件夾或目錄要復(fù)制到已構(gòu)建應(yīng)用程序中表制。
to string 一個路徑健爬,表示將 from 路徑下的依賴復(fù)制到何處的目標(biāo)路徑。默認(rèn)情況下么介,依賴會被復(fù)制到 ${externalsOutputPath}/${to}娜遵;如果沒有設(shè)置 to,依賴會被復(fù)制到 ${externalsOutputPath}/${from}壤短。如果路徑中包含 . 字符或者路徑表示的是一個文件夾设拟,則需要以正斜杠結(jié)尾慨仿。
name string 在應(yīng)用程序代碼中引用的模塊 id 或者全局變量名。
inject string, string[], or boolean 此屬性表示這個依賴定義的(或者包含的)纳胧,要在頁面中加載的腳本或樣式文件镰吆。如果 inject 的值為 true,那么就會在頁面中加載 tofrom 指定位置的文件跑慕。如果依賴的是文件夾万皿,則 inject 可以被設(shè)置為一個或者一組字符串,來定義一個或多個要注入的文件核行。inject 中的每個路徑都應(yīng)該是相對于 ${externalsOutputPath}/${to}${externalsOutputPath}/${from}(具體取決于是否指定了 to)牢硅。
type 'root' or 'umd' or 'amd' or 'commonjs' or 'commonjs2' 強(qiáng)制模塊用指定的方法解析。如果是 AMD 風(fēng)格芝雪,則必須使用 umdamd减余。如果是 node 風(fēng)格則必須使用 commonjs,并且值為 root 時以全局的方式訪問對象绵脯。

例如佳励,以下配置會將 src/legacy/layer.js 注入到應(yīng)用程序頁面中;注入定義了 MyGlobal 全局變量的文件蛆挫;聲明模塊 ab 為外部依賴赃承,且要委托給外部層;然后復(fù)制 node_modules/legacy-dep 下的文件悴侵,并將其中的幾個文件注入到頁面中瞧剖。所有文件都將被復(fù)制到 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 中抓于,這跟其它依賴項是一樣的。

因為這些文件位于主構(gòu)建(main build)之外浇借,所以在生產(chǎn)構(gòu)建中不會執(zhí)行版本控制或哈希處理(在 inject 中指定資源的鏈接除外)捉撮。可以在 to 屬性中指定版本號妇垢,將依賴復(fù)制到對應(yīng)版本的文件夾下巾遭,這樣就能避免緩存不同版本的文件。

脫離 Dojo 構(gòu)建管道

Dojo 的構(gòu)建管道為項目提供了一個端到端的工具鏈闯估,但是灼舍,在極少數(shù)情況下,可能需要自定義工具鏈涨薪。只要將項目脫離 Dojo 的構(gòu)建管道骑素,就可以自定義工具鏈。

將項目脫離構(gòu)建管道刚夺,是一個不可逆的献丑、單向過程末捣,它會導(dǎo)出 Webpack、Intern 以及 dojo 命令使用的其他項目的底層配置文件创橄。如果提供的生成工具無法提供所需的功能或特性塔粒,推薦的方法是 fork 選定的構(gòu)建命令,然后往工具中添加額外的功能筐摘。Dojo 的 CLI 本質(zhì)上是專門按模塊化設(shè)計的,考慮到了這個用例船老。

要將一個項目脫離出 dojo 構(gòu)建管道咖熟,請使用 dojo eject 命令,它將提示你確實已明白過程是不可逆的柳畔。這個導(dǎo)出過程將所有已安裝的 dojo 命令中導(dǎo)出的配置信息存到 config 文件夾中馍管。這個過程也會安裝一些項目需要的附加依賴。

現(xiàn)在項目已經(jīng)是一個 webpack 項目薪韩∪贩校可以通過修改 config/build-app/base.config.js 來更改構(gòu)建配置。

然后俘陷,可以通過運行 webpack 的構(gòu)建命令并提供配置項來觸發(fā)一個構(gòu)建罗捎。此外,使用 webpack 的 env 標(biāo)記(例如 --env.mode=dev)來指定模式拉盾,默認(rèn)為 dist桨菜。

./node_modules/.bin/webpack --config=config/build-app/ejected.config.js --env.mode=[mode]
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捉偏,隨后出現(xiàn)的幾起案子倒得,更是在濱河造成了極大的恐慌,老刑警劉巖夭禽,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霞掺,死亡現(xiàn)場離奇詭異,居然都是意外死亡讹躯,警方通過查閱死者的電腦和手機(jī)菩彬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜀撑,“玉大人挤巡,你說我怎么就攤上這事】崧螅” “怎么了矿卑?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長沃饶。 經(jīng)常有香客問我母廷,道長轻黑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任琴昆,我火速辦了婚禮氓鄙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘业舍。我一直安慰自己抖拦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布舷暮。 她就那樣靜靜地躺著态罪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪下面。 梳的紋絲不亂的頭發(fā)上复颈,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音沥割,去河邊找鬼耗啦。 笑死,一個胖子當(dāng)著我的面吹牛机杜,可吹牛的內(nèi)容都是我干的帜讲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼叉庐,長吁一口氣:“原來是場噩夢啊……” “哼舒帮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起陡叠,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤玩郊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后枉阵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體译红,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年兴溜,在試婚紗的時候發(fā)現(xiàn)自己被綠了侦厚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡拙徽,死狀恐怖刨沦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情膘怕,我是刑警寧澤想诅,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響来破,放射性物質(zhì)發(fā)生泄漏篮灼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一徘禁、第九天 我趴在偏房一處隱蔽的房頂上張望诅诱。 院中可真熱鬧,春花似錦送朱、人聲如沸娘荡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽它改。三九已至,卻和暖如春商乎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背祭阀。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工鹉戚, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人专控。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓抹凳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伦腐。 傳聞我的和親對象是個殘疾皇子赢底,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容