疑難排解
如果您遇到困難,請嘗試在 Rollup Discord 上討論問題,或在 Stackoverflow 上發布問題。如果您發現錯誤,或 Rollup 無法滿足您的需求,請嘗試 提出問題。最後,您也可以嘗試在 Twitter 上聯絡 @RollupJS。
避免 eval
您可能已經知道「eval
很邪惡」,至少根據某些人的說法。但對於 Rollup 來說,它特別有害,因為它的運作方式與其他模組打包器不同,其他模組打包器會將每個模組包覆在一個函式中,但 Rollup 會將您的所有程式碼放在同一個範圍內。
這樣做更有效率,但這表示只要您使用 eval
,共享範圍就會「受到污染」,而使用不同的打包器,沒有使用 eval 的模組則不會受到污染。縮小程式無法混淆受污染程式碼中的變數名稱,因為它無法保證要評估的程式碼不會參照那些變數名稱。
此外,它會造成安全風險,因為惡意模組可以使用 eval('SUPER_SEKRIT')
存取另一個模組的私人變數。
幸運的是,除非你真的打算讓評估的程式碼存取區域變數(這種情況下你可能做錯了!),你可以用兩種方法達成相同的結果
eval2 = eval
只要「複製」eval
,就能提供一個執行完全相同動作的功能,但它會在全域範圍而不是區域範圍執行
var eval2 = eval;
(function () {
var foo = 42;
eval('console.log("with eval:",foo)'); // logs 'with eval: 42'
eval2('console.log("with eval2:",foo)'); // throws ReferenceError
})();
new Function
使用 Function 建構函式 從提供的字串產生一個函式。同樣地,它會在全域範圍執行。如果你需要重複呼叫函式,這比使用 eval
快很多。
樹狀搖晃似乎沒有作用
有時候,你會在套件中看到不該存在的程式碼。例如,如果你從 lodash-es
匯入一個工具程式,你可能會期待只會取得讓該工具程式運作所需的最低限度程式碼。
但是,Rollup 必須保守地處理要移除的程式碼,才能保證最終結果可以正確執行。如果一個匯入的模組似乎對你正在使用的模組部分或全域環境有副作用,Rollup 會採取安全措施,並包含這些副作用。
由於在 JavaScript 等動態語言中進行靜態分析很困難,因此偶爾會出現誤判。Lodash 是模組的一個好例子,它看起來有很多副作用,即使在它沒有副作用的地方。你通常可以透過匯入子模組來減輕這些誤判(例如,import map from 'lodash-es/map'
而不是 import { map } from 'lodash-es'
)。
Rollup 的靜態分析會隨著時間而改進,但它永遠不會在所有情況下都完美無缺,這只是 JavaScript 的特性。
錯誤:"[name] 未由 [module] 匯出"
偶爾您會看到類似這樣的錯誤訊息
'foo' 未由 bar.js 匯出 (由 baz.js 匯入)
匯入宣告必須在匯入的模組中具有對應的匯出宣告。例如,如果您在模組中有 import a from './a.js'
,而 a.js 沒有 export default
宣告,或 import {foo} from './b.js'
,而 b.js 沒有匯出 foo
,Rollup 無法套件化程式碼。
此錯誤經常發生在由 rollup-plugin-commonjs 轉換的 CommonJS 模組中,此套件已不建議使用且不再維護。請使用 @rollup/plugin-commonjs。
錯誤:"this 未定義"
在 JavaScript 模組中,this
在頂層 (即在函式外) 為 undefined
。因此,Rollup 會將任何 this
參照改寫為 undefined
,以便產生的行為與模組原生支援時發生的行為相符。
偶爾會有正當理由讓 this
表示其他意思。如果您在套件中收到錯誤,可以使用 options.context
和 options.moduleContext
來變更此行為。
警告:"Sourcemap 可能不正確"
如果您使用套件產生 Sourcemap (sourcemap: true
或 sourcemap: 'inline'
),但您使用了一個或多個在轉換時未產生 Sourcemap 的外掛程式轉換程式碼,您會看到此警告。
通常,只有在使用 sourcemap: false
設定外掛程式(外掛程式,而非套件)時,外掛程式才會略過原始碼地圖,因此您只需要變更此設定即可。如果外掛程式未產生原始碼地圖,請考慮向外掛程式作者提出問題。
警告:「將 [module] 視為外部相依性」
預設情況下,Rollup 只會解析相對應的模組 ID。這表示像這樣的匯入陳述…
import moment from 'moment';
…不會導致 moment
包含在您的套件中,而是會在執行階段所需的外部相依性。如果您希望如此,您可以使用 external
選項取消此警告,這會明確表達您的意圖
// rollup.config.js
export default {
entry: 'src/index.js',
dest: 'bundle.js',
format: 'cjs',
external: ['moment'] // <-- suppresses the warning
};
如果您確實想要在您的套件中包含模組,您需要告訴 Rollup 如何尋找它。在多數情況下,這是使用 @rollup/plugin-node-resolve 的問題。
某些模組(例如 events
或 util
)已內建至 Node.js。如果您想要包含這些模組(例如,讓您的套件在瀏覽器中執行),您可能需要包含 rollup-plugin-polyfill-node。
錯誤:「EMFILE:開啟過多檔案」
對於大型專案,您在 macOS 上以監控模式執行 Rollup 時可能會遇到 EMFILE 錯誤。如果您遇到此問題,停用 FSEvents 可能可以解決問題
// rollup.config.js
export default {
...,
watch: {
chokidar: {
useFsEvents: false
}
}
};
錯誤:JavaScript 堆積使用完畢
由於 Rollup 需要同時將所有模組資訊保留在記憶體中,才能分析與樹狀搖晃相關的副作用,因此有可能在套件化大型專案時達到 Node 的記憶體限制。如果發生這種情況,透過以下方式執行 Rollup,可以協助增加此限制
node --max-old-space-size=8192 node_modules/rollup/dist/bin/rollup -c
視需要增加 --max-old-space-size
。請注意,此數字可以安全地超過您的可用實體記憶體。在這種情況下,Node 會視需要開始將記憶體分頁到磁碟。
你可以透過使用動態載入來引入程式碼分割,只載入特定模組而非整個依賴項、停用原始碼地圖或增加交換空間大小來降低記憶體壓力。
錯誤:Node 試圖將你的設定檔載入為 CommonJS,即使它很可能是 ES 模組
預設情況下,Rollup 會使用 Node 的原生模組機制來載入你的 Rollup 設定。這表示如果你在設定中使用 ES 載入和匯出,你需要在你的 package.json
檔案中定義 "type": "module"
或為你的設定使用 .mjs
副檔名。另請參閱 設定檔 和 使用原生 Node ES 模組時的注意事項 以取得更多資訊。