点击页面元素,这个Vite插件竟然帮我打开了Vue组件文件!超级好用!
大家好,我是若川。持續組織了8個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12?參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》?包含20余篇源碼文章。歷史面試系列
前言
這兩天肝了個Vite插件,本文主要跟大家分享一下它的功能和實現思路.如果你覺得它對你有幫助,請給一個star支持作者 💗.
介紹
vite-plugin-vue-inspector的功能是點擊頁面元素,自動打開本地IDE并跳轉到對應的Vue組件.類似于Vue DevTools的 Open component in editor功能。(若川批注:關于原理可以看我寫過的文章:據說 99% 的人不知道 vue-devtools 還能直接打開對應組件文件?本文原理揭秘)
用法
vite-plugin-vue-inspector支持Vue2 & Vue3,并且只需要進行簡單的配置就可以使用.
Vue2
//?vite.config.tsimport?{?defineConfig?}?from?"vite" import?{?createVuePlugin?}?from?"vite-plugin-vue2" import?Inspector?from?"vite-plugin-vue-inspector"export?default?defineConfig({plugins:?[createVuePlugin(),Inspector({vue:?2,}),], })Vue3
//?vite.config.tsimport?{?defineConfig?}?from?"vite" import?Vue?from?"@vitejs/plugin-vue" import?Inspector?from?"vite-plugin-vue-inspector"export?default?defineConfig({plugins:?[Vue(),?Inspector()], })IDE也要進行配置,這里就不啰嗦了, 👉 傳送門.
實現思路
看到這里,如果你覺得這個插件索然無味的話先別跑,插件沒意思,看看怎么寫插件還是有點意思的嘛 ! 接下來跟大家介紹一下這個插件的實現思路.
我們先來分析一下實現這個功能我們需要有哪些元素 :
Open IDE: 打開編輯器功能.
Web層: 提供該功能所需的頁面元素及交互功能.
Server層: 用戶交互時傳遞數據到Server層,由Server層調用Open IDE功能.
DOM=>Vue SFC映射關系: 告訴OPen IDE打開哪個文件并定位到對應的行列.
明確我們需要什么元素,我們就可以進一步來梳理它的實現方式,直接曬圖:
vite-plugin-step.drawio (2).png實現細節
接下來,我們來看具體的實現細節.在這之前,我們先簡單看下我們需要用到的幾個Vite插件API:
function?VitePluginInspector():?Plugin?{return?{name:?"vite-plugin-vue-inspector",//?應用順序enforce:?"pre",//?應用模式?(只在開發模式應用)apply:?"serve",//?含義:?轉換鉤子,接收每個傳入請求模塊的內容和文件路徑//?應用:?在這個鉤子對SFC模版進行解析并注入自定義屬性transform(code,?id)?{},//?含義:?配置開發服務器鉤子,可以添加自定義中間件//?應用:?在這個鉤子實現Open?Editor調用服務configureServer(server)?{},//?含義:?轉換index.html的專用鉤子,接收當前HTML字符串和轉換上下文//?應用:?在這個鉤子注入交互功能transformIndexHtml(html)?{},} }解析SFC模版 & 注入自定義屬性
這部分的實現主要分為兩步:
SFC Template => AST
獲取元素所在組件的行和列的編號
獲取自定義屬性插入的位置
注入自定義屬性
file (SFC路徑,用于跳轉到指定文件)
line (元素所在行編號,用于跳轉到指定行)
column (元素所在列編號,用于跳轉到指定列)
title (SFC名稱,用于展示)
注入后的DOM元素長這樣 :
<h3?data-v-inspector-file="/xxx/src/Hi.vue"???data-v-inspector-line="3"?data-v-inspector-column="5"?data-v-inspector-title="Hi.vue"> </h3>Open Editor Server服務
前面我們提到了創建Server服務的思路是在vite的configureServer的鉤子函數注入中間件:
//?vite.config.tsfunction?VitePluginInspector():?Plugin?{return?{name:?"vite-plugin-vue-inspector",configureServer(server)?{//?注冊中間件//?請求Query參數解析中間件?server.middlewares.use(queryParserMiddleware)//?Open?Edito服務中間件server.middlewares.use(launchEditorMiddleware)},} }//?middleware.ts//?請求Query參數解析中間件? export?const?queryParserMiddleware:?Connect.NextHandleFunction?=?(req:?RequestMessage?&?{query?:?object},_,next, )?=>?{if?(!req.query?&&?req.url?.startsWith(SERVER_URL))?{const?url?=?new?URL(req.url,?"http://domain.inspector")req.query?=?Object.fromEntries(url.searchParams.entries())}next() }//?Open?Editor服務中間件 export?const?launchEditorMiddleware:?Connect.NextHandleFunction?=?(req:?RequestMessage?&?{query?:?{?line:?number;?column:?number;?file:?string?}},res,next, )?=>?{//?只處理Open?Editor接口if?(req.url.startsWith(SERVER_URL))?{//?解析SFC路徑,行號,列號const?{?file,?line,?column?}?=?req.queryif?(!file)?{res.statusCode?=?500res.end("launch-editor-middleware:?required?query?param?\"file\"?is?missing.")}const?lineNumber?=?+line?||?1const?columnNumber?=?+column?||?1//?見下方鏈接launchEditor(file,?lineNumber,?columnNumber)res.end()}else?{next()} }關于launchEditor的具體邏輯我直接fork了react-dev-utils的實現,它支持很多IDE (vscode,atom,webstorm...),它的大致原理就是通過維護一些進程映射表和環境變量,然后通過調用Node.js的子進程喚醒IDE:
child_process.spawn(editor,?args,?{?stdio:?'inherit'?});交互功能注入
這個功能的實現原理其實就在transformIndexHtml注入功能所需要的html,scripts,styles.
//?vite.config.tsfunction?VitePluginInspector():?Plugin?{return?{transformIndexHtml(html)?{return?{html,tags:?[{tag:?"script",children:?...,injectTo:?"body",},?{tag:?"script",attrs:?{type:?"module",},children:?scripts,injectTo:?"body",},?{tag:?"style",children:?styles,injectTo:?"head",}],}}} }關于交互的頁面實現有很多種,最簡單的無非就是編寫原生js,這樣我們無需任何編譯就可以直接注入到html中,但是用原生js來寫頁面真的是慢又不好維護,于是我選擇了Vue進行開發,使用Vue就意味著要進行編譯才能在瀏覽器中跑起來.為了這個所謂的研發體驗,又折騰了一波,大概過程就是通過compile-sfc等包編譯出render函數,樣式代碼等,為了兼容Vue2,我又引入了祖傳的vue-template-compiler...噼里啪啦噼里啪啦..感興趣的童鞋可以點傳送門詳看. (u1s1,還是有點意思的!!) 當然了,這部分的編譯都是在插件打包時完成的,用戶在使用插件的時候并不會有這部分的運行時開銷.
致謝
這個項目的靈感來自于react-dev-inspector,使用React的童鞋可以看看.
結語
在做這個插件的時候也踩了一些坑,通過查看vue,vite等源碼排查解決.這里給想看源碼的童鞋一個建議,從實踐和帶著問題的角度出發,也許會有更好的效果和更深刻的印象 (教訓) :)
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經堅持寫了8年,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助3000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
掃碼加我微信 ruochuan02、拉你進源碼共讀群
今日話題
略。分享、收藏、點贊、在看我的文章就是對我最大的支持~
總結
以上是生活随笔為你收集整理的点击页面元素,这个Vite插件竟然帮我打开了Vue组件文件!超级好用!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【热点】React18正式版发布,未来发
- 下一篇: uniwebview按钮被无形遮挡问题