OpenZeppelin Defender Autotask 遇到 js bundle 檔案大小問題該如何解決

Peter Lai
Taipei Ethereum Meetup
5 min readMay 11, 2023
圖片作者:https://unsplash.com/@altumcode

前言

前陣子再使用 OpenZeppelin Defender Autotask 遇到 js bundle 檔案太大無法上傳的問題,後來找到解決方式就寫篇文章分享。

Defender Autotask 是 OpenZeppelin 的一個 serverless 程式服務,可以設定定時任務或是 webhook 去執行,像是領取 vault 的利息,或是資料結算等等。

文章中使用的範例是以檢查 git commit 和 Google Sheet API串接為主,如果程式有用到非環境有的套件很容易超過檔案限制,希望這篇文章有幫助。

Autotask 執行環境

在開始前我們要先看一下他程式的執行環境

  • node 16
  • 256mb RAM
  • 5 分鐘的 timeout 的限制
  • 程式檔案大小 5 mb。

一般來說 serverless 的程式大小都會有限制

預先安裝好的套件有

“@datadog/datadog-api-client”: “¹.0.0-beta.5”,
“@gnosis.pm/safe-core-sdk”: “⁰.3.1”,
“@gnosis.pm/safe-ethers-adapters”: “⁰.1.0-alpha.3”,
“axios”: “0.21.2”,
“axios-retry”: “3.1.9”,
“defender-admin-client”: “1.37.0-rc.2”,
“defender-autotask-client”: “1.37.0-rc.2”,
“defender-autotask-utils”: “1.34.0”,
“defender-kvstore-client”: “1.37.0-rc.2”,
“defender-relay-client”: “1.37.0-rc.2”,
“defender-sentinel-client”: “1.37.0-rc.2”,
“ethers”: “5.5.3”,
“fireblocks-sdk”: “².3.2”,
“graphql”: “¹⁵.5.1”,
“graphql-request”: “3.4.0”,
“web3”: “1.3.6”

預先安裝好的套件可以從外部引入,像是 ethers, axios, web3,這種外部引入的模組在 rollup config 可以手動設定為 external,編譯時就就不會放進 output

由於 Autotask 是沒有外部引入 googleapis 套件,所以沒辦法透過將 googleapis 設為 external 的方式來減少。

範例程式

先上範例程式連結,程式裡對 google 服務端主要就是取得 jwt token 並讀取以及寫入 google sheet,列出幾個一開始編譯的時候踩到了幾個雷:

  • Unknown node: protocol
    nodejs 從某個版本開始,新增了 node: protocol 引入 node 本身的套件,node:path 就是 path 這個原生套件。有些外部套件後來也採用 node: 引入 node 相關的套件,原先有個 builtin-modules 就是回傳 node 原生模組的列表,因為該套件沒有更新這個部分,還是可以在 builtins 前面加上 node:
const nodePrefixedBuiltins = builtins.concat(builtins.map(x => ‘node:’ + x))
  • Out of memory
    因為一開始給 node 記憶體不夠大有遇到,這邊可以更改 build 執行的指令
node --max-old-space-size=8192 node_modules/.bin/rollup -c

rollup 常見的問題列表

一開始沒有調整上述的程式範例,編譯完檔案大小約是 22.7 MB,於是就因為檔案太大而上傳失敗。

減少 js bundle 大小

這邊先嘗試壓縮整個程式,剛好有 rollup terser 的套件可以做到這件事,壓縮完後檔案大小是 8.1 MB,檔案還是太大無法上傳。

再來嘗試將 script 改寫,把原先讀取的 module 改成讀取需要的資源(static import),這樣可以利用 rollup treeshake 避免 bundle 時放入不需要的 module。

treeshake 是指移除 import / export 沒有用到的程式碼,以便減少檔案的大小,目前 webpack / rollup 都有支援,想深入瞭解的可以看這個連結

例如:

import { google } from ‘googleapis’
let client = new google.auth.JWT(…)
let sheet = google.sheets(‘v4’)

調整後

import { sheets } from ‘googleapis/build/src/apis/sheets’
import { JWT } from 'google-auth-library'
let client = new JWT(...)
let sheet = sheets('v4')

build 完後檔案大小只剩 801 KB,終於可以上傳到 Defender Autotask。

網路上還有查到一些奇技淫巧,諸如刪除 types 或是 .d.ts 等檔案,不過測試過後檔案大小不會減少很多。
有聽過用 .yarnclean 移除不需要用的 module,但其實 import 那邊調整過,搭配 treeshake 就不會引入其他的 module。

結論

先前做自動放貸機器人時就有遇到檔案大小不過的問題,但因為移除套件直接串接 api 就解決了,於是就沒深入研究,這次再遇到發現有另一種處理方式,記錄下來可以幫助到也愛用 serverless 服務的同學。

參考

--

--