[英]Barrel files, webpack and jest
我對桶文件、webpack 和 jest 沒有什么疑問。 我從來沒有真正想過它們是如何工作的,現在我正在努力(開玩笑地)在一個更大的應用程序上編寫測試,而這個應用程序還沒有。
我在大文件夾(如components
)中有桶文件,它們看起來像這樣:
/組件/index.js
export { default as ComponentA } from './ComponentA';
export { default as ComponentB } from './ComponentB';
export { default as ComponentC } from './ComponentC';
通過這樣的設置,我可以像這樣輕松地導入這些組件:
import { ComponentA, Component C } from '/components';
而不是寫作
import Component A from '/components/ComponentA';
import Component C from '/components/ComponentC';
我的主要問題:在我的 webpack 捆綁文件中,是否會包含 ComponentB 文件只是因為我在components/index.js
中有它(但我並沒有真正使用它)?
在我開始開玩笑地編寫測試后,我想到了這一點,它開始向我拋出有關我尚未為其編寫測試的文件的錯誤。 我試圖搜索原因,我能找到的唯一原因是我從桶文件中導入了更大的文件(例如,我在構建頁面時從桶文件導入ComponentA
- 我現在正在嘗試測試)。
實際上是的,在桶文件中導入的所有文件當前都包含在 Jest 的導入中。 發生這種情況主要是因為 Jest 使用 CommonJS 並且不進行任何 tree-shaking(在這個用例中這實際上只會讓一切變得更慢)。
在處理大型項目時,使用桶文件時 Jest 測試套件運行速度越來越慢似乎很常見,這與在運行測試之前必須解析整個依賴樹這一事實有關。
對此的快速解決方案是在 package 中不使用桶文件進行導入,要么完全避免它們,要么使用 jest.mock 使用jest.mock
它們。
我個人建議通過使用依賴注入來完全避免在模塊上導入。 如果您真的想以jest.mock
方式 go ,您所要做的就是將它與工廠一起使用,就像這樣(來自 Jest 文檔):
jest.mock('../moduleName', () => {
return jest.fn(() => 42);
});
// This runs the function specified as second argument to `jest.mock`.
const moduleName = require('../moduleName');
moduleName(); // Will return '42';
是的,這將在導入之前神奇地替換導入的文件,完全避免桶文件問題。
再說一遍:我不喜歡魔術代碼,建議您改用依賴注入。
至少如果您使用 ts-jest 轉換,應該支持桶導入。 參考: https://github.com/kulshekhar/ts-jest/issues/1149
但我鼓勵類似的問題與桶類型定義 src/types/index.d.ts 通常在代碼庫中引用為 @/types
我最終配置了額外的 moduleNameMapper 定義
moduleNameMapper: {
// FIXES Could not locate module @/types mapped as: .../src/types.
'^@/types$': '<rootDir>/src/types/index.d',
},
希望這會對某人有所幫助:)
我遇到了同樣的問題: Jest拋出與我未使用的文件相關的錯誤,只是因為它們是在我正在測試的模塊使用的桶文件中導出的。 在我的例子中,問題是 Vuex 商店的測試開始中斷,因為模塊使用相同的商店(可能是由於循環依賴)。
prices.test.js
// the test imports a module
import prices from '@/store/modules/prices';
prices.js
// the module imports a module from a barrel file
import { isObject } from '@/common';
index.js
// this is the imported module
export { default as isObject } from './isObject';
// this is the other module that breaks my tests, even if I'm not importing it
export { default as getPageTitle } from './getPageTitle';
getPageTitle.js
// when the module uses the store, an error is thrown
import store from '@/store/store';
我認為在我的情況下問題是循環依賴,無論如何回答你的問題:是的,Jest 導入桶文件中的所有模塊,即使它們不是直接導入的。
在我的例子中,解決方案是將使用 Vuex 的模塊移動到一個單獨的文件夾,並僅為這些文件創建一個單獨的桶文件。
在不同的時刻,我發現Webpack默認情況下正在做同樣的事情。 我沒有在一個模塊很小並且沒有導入庫的項目中注意到它,但是在一個單獨的項目中我有模塊導入非常大的庫並且我注意到Webpack沒有進行 tree-shaking 並且沒有優化塊正如它應該做的那樣。
我發現Webpack以與Jest類似的方式導入桶文件中的所有庫。 好處是您可以通過禁用特定桶文件的副作用來停止此行為。
webpack.config.js
{
module: {
rules: [
// other rules...
{
test: [/src\/common\/index.ts/i],
sideEffects: false,
}
]
}
}
您可以使用Webpack Bundle Analyzer看到不同之處:當沒有關閉副作用時,來自一個特定文件夾的所有導入將具有相同的大小。 另一方面,當關閉副作用時,您會看到不同導入的大小不同。
當桶文件中的文件導入大型庫時,改進會更加明顯(tree-shaking 工作,優化塊)。
您可以在此處找到更多詳細信息: https ://github.com/vercel/next.js/issues/12557 和此處: Webpack doesn't split a huge vendor file when modules are exported and imported using index files 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.