告別手動引入依賴:unplugin-auto-import 插件助你提升編碼體驗

模塊化已經(jīng)是現(xiàn)代 Web 開發(fā)必不可少的開發(fā)方式较屿,頻繁引入依賴包是一個常見的操作。但是卓练,手動引入依賴包往往繁瑣吝镣,尤其是當依賴包數(shù)量較多時,會顯著降低開發(fā)效率昆庇。

unplugin-auto-import?插件末贾,可以幫助我們在項目中,自動導入常用的使用的第三方庫的 API整吆,就可以方便我們開發(fā)拱撵,提升開發(fā)效率。

使用效果

以 Vue 為例表蝙,在沒有使用自動導入前拴测,需要手寫以下的?import?語句:

import{computed,ref}from'vue'constcount=ref(0)constdoubled=computed(()=>count.value*2)

使用?unplugin-auto-import?插件后:

constcount=ref(0)constdoubled=computed(()=>count.value*2)

使用方法

基本使用

unplugin-auto-import?是基于?unplugin?寫的,支持 Vite府蛇、Webpack集索、Rollup、esbuild 多個打包工具。

vite 的使用方式如下:

// vite.config.tsimportAutoImportfrom'unplugin-auto-import/vite'exportdefaultdefineConfig({plugins:[AutoImport({imports:[// 預設],}),],})

使用預設

unplugin-auto-import?插件一般配合預設進行使用务荆,預設負責告訴插件應該自動引入哪些內(nèi)容

目前支持:

Vue

vue-router

@vueuse/core

react

react-router

……妆距,更多請查看這里

預設的配置方式

AutoImport({imports[// 預設'vue','vue-router',// 自定義預設{'@vueuse/core':[// 命名導入'useMouse',// import { useMouse } from '@vueuse/core',// 設置別名['useFetch','useMyFetch'],// import { useFetch as useMyFetch } from '@vueuse/core',],'axios':[// 默認導入['default','axios'],// import { default as axios } from 'axios',],'[package-name]':['[import-names]',// alias['[from]','[alias]'],],},// example type import{from:'vue-router',imports:['RouteLocationRaw'],type:true,},],})

有多種方式設置預設:

字符串語法,最終會被轉(zhuǎn)換成內(nèi)置的預設(對象語法寫的)

對象語法

key 為包名

value 為數(shù)組函匕,對應的是各個自動引入的變量的名稱娱据。同時可以設置引入方式(命名導入/默認導入),

對于?Typescript 類型的自動引入盅惜,則需要用以下方式:

{from:'vue-router',imports:['RouteLocationRaw'],type:true},

我們來看看 Vue 的預設是怎么寫的中剩,完整代碼在這里,下面是節(jié)選的代碼:

exportconstCommonCompositionAPI:InlinePreset['imports']=[// 聲明周期抒寂,節(jié)選'onActivated','onBeforeMount',// reactivity,節(jié)選'computed','ref','watch',// 組件 API结啼,節(jié)選'defineComponent','h','inject','nextTick',// Typescript 類型,接續(xù)那...['Component','Ref','VNode'].map(name=>({name,type:true}))]exportdefaultdefineUnimportPreset({from:'vue',imports:[...CommonCompositionAPI,]})

Vue 預設里屈芜,本質(zhì)就是使用對象語法郊愧,定義了 Vue 需要被自動導入的內(nèi)容。

編碼問題

要想在項目中優(yōu)雅地使用自動導入沸伏,還要解決以下兩個編碼的問題:

TS 類型丟失,會導致 TS 編譯報錯

Eslint 報錯:變量未定義

TS 類型

如果使用 Typescript动分,需要設置?dts?為 true

AutoImport({dts:true// or a custom path})

插件會在項目根目錄生成類型文件?auto-imports.d.ts?毅糟,確保該文件在?tsconfig?中被?include

auto-imports.d.ts?有什么作用?

我們來看看它的內(nèi)容(有節(jié)選):

export{}declareglobal{consth:typeofimport('vue')['h']constreactive:typeofimport('vue')['reactive']constref:typeofimport('vue')['ref']constwatch:typeofimport('vue')['watch']constwatchEffect:typeofimport('vue')['watchEffect']// 省略其他內(nèi)容}

unplugin-auto-import?插件會根據(jù)預設內(nèi)容澜公,生成對應的全局類型聲明

有了這些全局類型聲明姆另,我們就能夠像全局變量那樣使用?ref?等 Vue API,不需要先?import?對應的內(nèi)容坟乾,TS 編譯也不會報錯迹辐。

Eslint

如果使用了 eslint,需要設置?eslintrc?字段

AutoImport({eslintrc:{enabled:true,},})

插件會在項目根目錄生成類型文件?.eslintrc-auto-import.json?甚侣,確保該文件在?eslint?配置中被?extends:

// .eslintrc.jsmodule.exports={extends:['./.eslintrc-auto-import.json',],}

.eslintrc-auto-import.json?有什么作用明吩?

我們來看看它的內(nèi)容(有節(jié)選):

{"globals":{"h":true,"reactive":true,"ref":true,"watch":true,"watchEffect":true,}}

unplugin-auto-import?插件會根據(jù)預設內(nèi)容,生成對應的 eslint 配置文件殷费,該文件定義了?h印荔、ref?這些為全局變量,不需要引入就能直接使用详羡。這樣 ESlint 就不會報變量沒有定義的錯誤了仍律。

實現(xiàn)原理

從?v0.8.0?來開始,unplugin-auto-import?基于?unimport?開發(fā)实柠,所有的轉(zhuǎn)換能力水泉,都是?unimport?提供的,unplugin-auto-import?可以理解成為一個提供了更友好的 API 和功能的包裝層〔菰颍基本上所有新功能都會在?unimport?中開發(fā)钢拧。

那核心的實現(xiàn),我們直接去看?unimport?就好了畔师。

eslint 配置的生成是由?unplugin-auto-import?提供

unimport

我們直接看看插件代碼

exportconstdefaultIncludes=[/\.[jt]sx?$/,/\.vue$/,/\.vue\?vue/,/\.svelte$/]exportconstdefaultExcludes=[/[\\/]node_modules[\\/]/,/[\\/]\.git[\\/]/]exportdefaultcreateUnplugin<Partial<UnimportPluginOptions>>((options={})=>{constctx=createUnimport(options)constfilter=createFilter(toArray(options.includeasstring[]||[]).length?options.include:defaultIncludes,options.exclude||defaultExcludes)constdts=options.dts===true?'unimport.d.ts':options.dtsreturn{name:'unimport',// 在用戶插件執(zhí)行完之后執(zhí)行enforce:'post',// 過濾文件娶靡,默認只處理 、js看锉、jsx姿锭、ts、tsx伯铣、vue呻此、svelte 文件// 默認排除 node_modules 下的文件transformInclude(id){returnfilter(id)},// 轉(zhuǎn)換文件邏輯asynctransform(code,id){consts=newMagicString(code)// 注入 import 語句awaitctx.injectImports(s,id)if(!s.hasChanged()){return}return{code:s.toString(),map:s.generateMap()}},// 構建開始時,生成 ts 類型聲明文件asyncbuildStart(){awaitctx.init()// 生成 Typescript 全局類型聲明if(options.dts){returnfs.writeFile(dts,awaitctx.generateTypeDeclarations(),'utf-8')}}}})

插件用基于?unplugin?寫的腔寡,用?unplugin?寫的插件焚鲜,能用在 Vite、Webpack放前、Rollup忿磅、esbuild 多個打包工具,即unplugin?抹平了打包工具間的一些差異凭语。

unimport?插件主要的處理邏輯如下:

過濾出需要處理的文件葱她,對文件進行轉(zhuǎn)換,注入 import 語句

生成 ts?類型聲明文件

unimport?為什么需要在其他插件后執(zhí)行似扔?

因為有些代碼需要先經(jīng)過處理吨些,才會變成 js,例如 Vue 文件炒辉。

測試用例

我們直接使用?unimport?提供的示例豪墅,其中一個文件為:

import{Ref}from'vue'exportconstmultiplier=ref(2)exportfunctionuseDoubled(v:Ref<number>){returncomputed(()=>v.value*multiplier.value)}exportfunctionbump(){multiplier.value+=1}constlocalA='localA'constlocalB='localB'export{localA,localBaslocalBAlias}

我們通過?vite-plugin-inspect?插件,可以看到該文件被轉(zhuǎn)換的過程:

被?esbuild?轉(zhuǎn)換

被?unimport?插件轉(zhuǎn)換

可以看出?unbuild?插件自動加入了 import 語句

被?import-analysis?插件處理

將 Vue 改為一個可以訪問的路徑黔寇,讓 vue 的相關文件在 dev 環(huán)境下能夠被正常訪問到偶器。

如何注入 import 語句

注入 import 語句,是?unimport?的核心邏輯缝裤,主要有以下幾個步驟:

初始化預設

掃描文件

注入 import

初始化預設

將字符串的內(nèi)置預設状囱,標準化為對象語法

將所有配置對象合并成一個?importMap?對象

importMap 數(shù)據(jù)結構如下:

{reactive:{from:'vue,? ? ? ? name: 'reactive'? ? ? ? as: 'reactive'? ? },? // 轉(zhuǎn)換成 import { reactive } from 'vue'? ? ref: {? ? ? ? from: 'vue,name:'ref? ? ? ? as: 'ref},// 轉(zhuǎn)換成 import { ref } from 'vue'// ……}

有了?importMap?對象,就可以快速判斷一個標志符倘是,是否需要轉(zhuǎn)換了

掃描和注入

查找所有可能需要注入的標志符

import{Ref}from'vue'exportconstmultiplier=ref(2)exportfunctionuseDoubled(v:Ref<number>){returncomputed(()=>v.value*multiplier.value)}exportfunctionbump(){multiplier.value+=1}constlocalA='localA'constlocalB='localB'export{localA,localBaslocalBAlias}

以上述文件為例亭枷,從中找出沒有先定義再使用的標志符,排除 js 關鍵字(function 等)

可以查找到有以下的標志符搀崭,未被定義卻使用了

ref

computed

并且這兩個標志符都在?importMap?中能找到叨粘,這標明這兩個標志符猾编,需要注入 import

因此會注入以下代碼:

import{ref,computed}from'vue';

總結

并非所以依賴都適合自動導入,項目內(nèi)的代碼可能就不一定適合自動引入

因為自動引入后升敲,就能像全局變量那樣直接使用答倡,但從開發(fā)的角度就會丟失依賴鏈路,雖然另外生成了 Typescript 聲明文件驴党,IDE 能夠正常識別瘪撇, 但對于新加入項目的同學來說,他們不一定知道是自動引入港庄,因此可能會降低了一些可讀性倔既。

因此我們要有權衡。

那么鹏氧,什么樣的內(nèi)容適合自動引入渤涌?被廣泛認知和使用、不用關注實現(xiàn)把还、不變的內(nèi)容

這些內(nèi)容不關注實現(xiàn)实蓬,不會影響可讀性,不會影響開發(fā)吊履,不會對開發(fā)者心智造成影響安皱。

這類內(nèi)容,就適合自動引入艇炎。例如我們例子中的 Vue composition API酌伊,就已經(jīng)成為一種 Vue 開發(fā)者共識了。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末冕臭,一起剝皮案震驚了整個濱河市腺晾,隨后出現(xiàn)的幾起案子燕锥,更是在濱河造成了極大的恐慌辜贵,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件归形,死亡現(xiàn)場離奇詭異托慨,居然都是意外死亡,警方通過查閱死者的電腦和手機暇榴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門厚棵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蔼紧,你說我怎么就攤上這事婆硬。” “怎么了奸例?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵彬犯,是天一觀的道長向楼。 經(jīng)常有香客問我,道長谐区,這世上最難降的妖魔是什么湖蜕? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮宋列,結果婚禮上昭抒,老公的妹妹穿的比我還像新娘。我一直安慰自己炼杖,他們只是感情好灭返,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嘹叫,像睡著了一般婆殿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上罩扇,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天婆芦,我揣著相機與錄音,去河邊找鬼喂饥。 笑死消约,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的员帮。 我是一名探鬼主播滥崩,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼愈案,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起做修,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎莉掂,沒想到半個月后皇型,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡型檀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年冗尤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胀溺。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡裂七,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仓坞,到底是詐尸還是另有隱情背零,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布无埃,位于F島的核電站徙瓶,受9級特大地震影響蝎困,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜倍啥,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一禾乘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧虽缕,春花似錦始藕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剩胁,卻和暖如春诉植,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昵观。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工晾腔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人啊犬。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓灼擂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親觉至。 傳聞我的和親對象是個殘疾皇子剔应,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容