Hooks

簡介

Cordova Hooks 代表特殊的腳本,可以由應用程式和外掛開發人員,甚至是您自己的建置系統加入,以客製化 cordova 命令。

Cordova hooks 允許您在 cordova 命令周圍執行特殊活動。例如,您可能有一個自訂工具,用於檢查 javascript 檔案中的程式碼格式。而且,您希望在每次建置之前執行此工具。在這種情況下,您可以使用 'before_build' hook,並指示 cordova 執行時在每次建置之前調用自訂工具。

Hooks 可能與您的應用程式活動相關,例如 before_buildafter_build 等。或者,它們可能與您應用程式的外掛相關。例如,諸如 before_plugin_addafter_plugin_add 等 hooks 適用於外掛相關活動。這些 hooks 可以與您應用程式中的所有外掛相關聯,也可以僅限於一個外掛。

Cordova 支援以下 hook 類型

Hook 類型 相關的 Cordova 命令 描述
before_platform_add cordova platform add 在新增平台之前和之後執行。
after_platform_add
before_platform_rm cordova platform rm 在移除平台之前和之後執行。
after_platform_rm
before_platform_ls cordova platform ls 在列出已安裝和可用的平台之前和之後執行。
after_platform_ls
before_prepare cordova prepare
cordova platform add
cordova build
cordova run
在準備您的應用程式之前和之後執行。
after_prepare
before_compile cordova compile
cordova build
在編譯您的應用程式之前和之後執行。
after_compile
before_deploy cordova emulate
cordova run
在部署您的應用程式之前執行。
before_build cordova build 在建置您的應用程式之前和之後執行。
after_build
before_emulate cordova emulate 在模擬您的應用程式之前和之後執行。
after_emulate
before_run cordova run 在執行您的應用程式之前和之後執行。
after_run
before_serve cordova serve 在提供您的應用程式之前和之後執行。
after_serve
before_clean cordova clean 在清除您的應用程式之前和之後執行。
after_clean
before_plugin_add cordova plugin add 在新增外掛之前和之後執行。
after_plugin_add
before_plugin_rm cordova plugin rm 在移除外掛之前和之後執行。
after_plugin_rm
before_plugin_ls cordova plugin ls 在列出您應用程式中的外掛之前和之後執行。
after_plugin_ls
before_plugin_install cordova plugin add 在安裝外掛(到平台)之前和之後執行。plugin.xml 中的外掛 hooks 僅針對正在安裝的外掛執行
after_plugin_install
before_plugin_uninstall cordova plugin rm 在解除安裝外掛(從平台)之前執行。plugin.xml 中的外掛 hooks 僅針對正在安裝的外掛執行

定義 hooks 的方法

Config.xml

可以使用 <hook> 元素在專案的 config.xml 中定義 Hooks,例如

<hook type="before_build" src="scripts/appBeforeBuild.bat" />
<hook type="before_build" src="scripts/appBeforeBuild.js" />
<hook type="before_plugin_install" src="scripts/appBeforePluginInstall.js" />

<platform name="android">
    <hook type="before_build" src="scripts/android/appAndroidBeforeBuild.bat" />
    <hook type="before_build" src="scripts/android/appAndroidBeforeBuild.js" />
    <hook type="before_plugin_install" src="scripts/android/appAndroidBeforePluginInstall.js" />
    ...
</platform>

外掛 hooks (plugin.xml)

作為外掛開發人員,您可以使用 plugin.xml 中的 <hook> 元素定義 hook 腳本,如下所示

<hook type="before_plugin_install" src="scripts/beforeInstall.js" />
<hook type="after_build" src="scripts/afterBuild.js" />

<platform name="android">
    <hook type="before_plugin_install" src="scripts/androidBeforeInstall.js" />
    <hook type="before_build" src="scripts/androidBeforeBuild.js" />
    ...
</platform>

before_plugin_installafter_plugin_installbefore_plugin_uninstall 外掛 hooks 將專門針對正在安裝/解除安裝的外掛觸發。

Hooks 執行順序

基於 Hooks 定義

對於給定 hook 的 hook 腳本,會按照它們檔案中的出現順序,依序執行,其中來自 config.xml 的應用程式 hooks 會在來自 plugins/.../plugin.xml 的外掛 hooks 之前執行。

基於內部執行順序

hooks 的內部執行順序是固定的。

範例 1 (cordova platform add)

如果存在與 before_platform_addafter_platform_addbefore_prepareafter_preparebefore_plugin_installafter_plugin_install 相關的 hooks(並假設您在專案中安裝了一個外掛),則新增一個新的平台將會按照以下順序執行 hooks

before_platform_add
    before_prepare
    after_prepare
    before_plugin_install
    after_plugin_install
after_platform_add
範例 2 (cordova build)

如果存在與 before_prepareafter_preparebefore_compileafter_compilebefore_buildafter_build 相關的 hooks - 執行建置命令將會按照以下順序執行 hooks

before_build
    before_prepare
    after_prepare
    before_compile
    after_compile
after_build

腳本介面

Javascript

如果您使用 Node.js 編寫 hooks,則應使用以下模組定義

module.exports = function(context) {
    ...
}

以下範例展示了 context 物件的內容

{
  // The type of hook being run
  hook: 'before_plugin_install',

  // Absolute path to the hook script that is currently executing
  scriptLocation: '/foo/scripts/appBeforePluginInstall.js',

  // The CLI command that lead to this hook being executed
  cmdLine: 'cordova plugin add plugin-withhooks',

  // The options associated with the current operation.
  // WARNING: The contents of this object vary among the different
  // operations and are currently not documented anywhere.
  opts: {
    projectRoot: '/foo',

    cordova: {
      platforms: ['android'],
      plugins: ['plugin-withhooks'],
      version: '0.21.7-dev'
    },

    // Information about the plugin currently operated on.
    // This object will only be passed to plugin hooks scripts.
    plugin: {
      id: 'plugin-withhooks',
      pluginInfo: { /* ... */ },
      platform: 'android',
      dir: '/foo/plugins/plugin-withhooks'
    }
  },

  // A reference to Cordova's API
  cordova: { /* ... */ }
}

您也可以使用 context.requireCordovaModule 以以下方式在您的腳本中要求額外的 Cordova 模組

const cordovaCommon = context.requireCordovaModule('cordova-common');

您可以使用 Promises 使您的腳本非同步。以下範例僅等待一秒鐘,然後列印等待所花費的毫秒數

module.exports = context => {
    return new Promise(resolve => {
        const start = Date.now();
        setTimeout(() => resolve(Date.now() - start), 1000);
    }).then(msWaited => {
        console.log(`${context.scriptLocation} waited ${msWaited} ms`);
    });
};

非 Javascript

非 javascript 腳本透過 Node child_process spawn 從專案的根目錄執行,並將根目錄作為第一個引數傳遞。所有其他選項都使用環境變數傳遞給腳本

環境變數名稱 描述
CORDOVA_VERSION Cordova-CLI 的版本。
CORDOVA_PLATFORMS 命令適用的平台之逗號分隔清單(例如:android、ios)。
CORDOVA_PLUGINS 命令適用的外掛 ID 之逗號分隔清單(例如:cordova-plugin-file-transfer、cordova-plugin-file)。
CORDOVA_HOOK 正在執行的 hook 的路徑。
CORDOVA_CMDLINE 傳遞給 cordova 的確切命令列引數(例如:cordova run ios --emulate)。

如果腳本傳回非零的結束代碼,則父 cordova 命令將會中止。

注意:我們強烈建議使用 Node.js 編寫您的 hooks,以便它們是跨平台的,請參閱上面的 Javascript 章節。

Windows 特性

如果您在 Windows 上工作,並且您的 hook 腳本不是 *.bat 檔案,Cordova CLI 將會預期 shebang 行作為腳本的第一行。這樣它就知道它需要使用哪個直譯器來啟動腳本。Python 腳本的 shebang 行可能如下所示

#!/usr/bin/env python

範例用法

此範例示範 Cordova hooks 的用法,以追蹤 Android 平台產生的 .apk 檔案大小到主控台輸出。

建立空白的 Cordova 應用程式,並在 config.xml 中新增以下定義,以告知 Cordova 在每次平台建置後執行 afterBuild.js 腳本。

<hook type="after_build" src="scripts/afterBuild.js" />

建立 scripts/afterBuild.js 檔案並新增以下實作。我們使用 fs.stat 方法的非同步版本來示範如何在 hooks 中使用非同步函式。

const fs = require('fs');
const util = require('util');
const stat = util.promisify(fs.stat);

module.exports = function(ctx) {
    // Make sure android platform is part of build
    if (!ctx.opts.platforms.includes('android')) return;

    const platformRoot = path.join(ctx.opts.projectRoot, 'platforms/android');
    const apkFileLocation = path.join(platformRoot, 'build/outputs/apk/android-debug.apk');

    return stat(apkFileLocation).then(stats => {
      console.log(`Size of ${apkFileLocation} is ${stats.size} bytes`);
    });
};

範例中的參數 ctx 由 Cordova 傳遞,並表示執行內容,例如腳本完整路徑、目標平台、命令列引數等,並公開其他輔助功能。有關更多詳細資訊,請參閱上面的 腳本介面 章節。

您現在可以新增 android 平台並執行建置。

cordova platform add android
..
cordova build
..
Size of path\to\app\platforms\android\build\outputs\apk\android-debug.apk is 1821193 bytes