當前位置:網站首頁>vitest支持cjs的workaround(TypeScript產物commonjs場景)
vitest支持cjs的workaround(TypeScript產物commonjs場景)
2022-05-14 14:35:31【咲奈】
前言
開門見山,首先 vitest 是一個 esm first 的測試工具,所以他的定比特應該是 純 esm
/ 純 cjs
的場景,不像 jest 可以通過一些 transform
插件支持混雜場景。
什麼是混雜場景,比如我們使用 typescript 編寫 esm 格式的 source ,但是把產物編譯為 commonjs 格式,最後給 node 調用,這在 Native ESM 普及之前是 node 庫的基本操作。
當然現在有 type: "module"
帶來了 typescript 編譯的 esm 格式包和真正的 Native ESM 包。
我們這裏不就 esm 話題展開聊,關鍵在於這種源碼 esm 產物 cjs 是一種 混雜 場景。
這就違背了 vitest 的設計,不在 vitest 的概念內,所以自然無法使用 vitest 。
在混雜場景下,我不建議使用 vitest ,而使用 jest ,但如果非要使用 vitest 怎麼辦呢?我們有一種 workaround 的方法。
該方法的靈感和現在社區熱導入 ts 文件的做法一致,也是 esno
/ swno
/ esbuild-jest
等庫的底層原理。
底層邏輯剖析
在了解解法前,我們先簡單剖析一下 vitest 不支持的底層邏輯。
由於 vitest 在底層使用 vite 的 esbuild 能力 transform ts 文件,所以關鍵在 esbuild 的配置。
當使用 cjs 作為產物的場景時
// vitest.config.ts
import {
defineConfig } from 'vitest/config'
export default defineConfig({
esbuild: {
target: 'node14',
format: 'cjs'
},
})
當我們把所有 transform 的 format 都定為 cjs
時,這將導致 *.test.ts
轉換為 cjs 格式,這就意味著最終 *.test.ts
內會出現 ts 文件的導入:
// before: test file
// example.test.ts
import {
method } from './some-file'
// after: transformed result
// example.test.js
const {
method } = require('./some-file')
注:以上轉換為偽代碼描述,並非真實結果。
其中 method
是 some-file.ts
文件的一個變量,關鍵在於 require()
是無法正常導入一個 .ts
文件的,由此將引發:
Error: Cannot find module ‘./some-file’
Require stack:
- …
當使用 esm 作為產物的場景時
// vitest.config.ts
import {
defineConfig } from 'vitest/config'
export default defineConfig({
esbuild: {
target: 'node14',
},
})
默認情况 vitest 是 esm 優先,所以我們的 test file *.test.ts
和相關導入的 .ts
文件會原模原樣使用 esm 格式來處理,但別忘了我們使用 typescript 的產物是 cjs 格式,最終運行時是 cjs 而不是 esm ,這就導致了兩者的概念發生沖突,將導致測試不符合預期,最終失敗。
關於此處的錯誤可能是千人千面的,大多可能和 cjs 的導入報錯相關,比如 TypeError: default is not a function
等。
解法
剖析完底層邏輯,我們來看解法。
在上文的剖析中,既然 require()
不能導入 .ts
文件,那麼我們讓他支持就好了。
在每次啟動測試前人為 hook require.extensions
來支持 .ts
文件導入:
// hook.ts
import {
EsbuildPhoenix } from '@xn-sakina/phoenix'
// 這個類實現了 hook 對 .ts 文件的 require 導入並進行熱轉換
new EsbuildPhoenix({
target: 'es2019'
})
vitest 配置:
// vitest.config.ts
import {
defineConfig } from https://github.com/vitest-dev/vitest
export default defineConfig({
test: {
setupFiles: ['./hook']
},
esbuild: {
target: 'node14',
format: 'cjs'
},
})
由此,我們便可以 workaround 掉這個問題。
進一步思考,還有什麼沒考慮到的?
性能和
ts-jest
/esbuild-jest
等 jest transform 插件實現思路一致,那麼速度和 vitest 誰快?hook
require
的一個邊緣情况是存在require.cache
,如何應對?如何應對
.tsx
的 jsx element 場景?其他 edge case 是否都能無傷應對?
在此解法下,我順利跑通了兩大組非 jsx 測試,還是比較滿意的。
但綜合來看,仍然存在一些謎點待驗證,我們還不能認為他是萬能的解法。
總結
Migrating from jest
雖然 vitest 在混合場景可圈可點,但在這一切之前,我們還需要注意 migrating from jest 的方法,關於這一點,官方文檔 有所描述,可以看到需要應對的點還是有不少的。
React strategy
值得注意的是,我還是建議在業務 React Project 場景使用 RTL ,因為更成熟,但簡單的 libs jsx 場景可以使用 react-test-renderer
,這也是 vitest 推薦的做法。
Use native esm
同時,當你准備好擁抱 native esm 時,vitest 將是你不二的選擇,你也可以在官方倉庫 examples 找到更多的用例和打開姿勢。
版權聲明
本文為[咲奈]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/134/202205141432588203.html
邊欄推薦
猜你喜歡
隨機推薦
- 不均衡樣本集的重采樣
- uni-app技術分享| uni-app轉小程序-實時消息
- SQL中某個字段大於等於且不等於某值該如何寫
- 【Leetcode】442. 數組中重複的數據
- 2022年為什麼降薪也要跳槽?機會比漲薪很重要?
- 工作流結合動態錶單的工作流程
- 為什麼要使用.NET5?.NET5是未來!
- (pycharm)安裝nltk包
- 安裝Apache
- 利用循環輸入輸出數組(簡便易學)利用循環設置函數
- 雲原生時代的搜索服務算力管理
- 證券投資基金的監管
- ArrayList循環删除元素的常見問題及解决方法
- Stack Overflow 上最熱門的 10 個 Kotlin 問題
- 555 定時器的時間計算
- 二叉樹的最近公共祖先
- 模擬卷Leetcode【普通】931. 下降路徑最小和
- C語言 數組(一維數組 · 二維數組)
- NFC之華為AIPASS認證:測試用例簡介
- 622. 設計循環隊列
- VMware虛擬機 之 NAT模式詳解
- 【Devops】kubernetes網絡
- 新式茶飲“拿捏”年輕人,“八馬茶業”們的出路在哪?
- 機器學習之金融風控
- 1.67版本vscode括號著色(Bracket Pair Colorizer)取消
- MySQL日期查詢使用的方法函數
- HugeGraph客戶端APP開發(一)
- [.Net]使用Soa庫+Abp搭建微服務項目框架(五):服務發現和健康監測
- 添加虛擬內存,不添加硬盤的方式
- Redis源碼學習(25),雙端鏈錶學習,adlist.h
- 虛幻5新特性之EnhancedInput
- 緩存命中錶示什麼?
- sencha touch 在線實戰培訓 第一期 第四節
- “我們從 Google 離職了”
- yolov5訓練測試與源碼解讀
- 原生JS 實現輪播圖效果
- 邏輯回歸 解决報錯:ValueError: Solver lbfgs supports only ‘l2‘ or ‘none‘ penalties, got l1 penalty.
- Oracle OCI 計算、存儲、網絡工具旨在降低雲複雜性
- Go項目實戰之日志必備篇[開源十年項目第11次更新]
- Shell脚本變量和運算符