亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

讀?VuePress(四)插件機(jī)制的設(shè)計(jì)

April / 4144人閱讀
前言

從 9 月份開始,vuepress 源碼進(jìn)行了重新設(shè)計(jì)和拆分。先是開了個(gè) next 分支,后來又合并到 master 分支,為即將發(fā)布的 1.x 版本做準(zhǔn)備。

最主要的變化是:大部分的全局功能都被拆分成了插件的形式,以可插拔的方式來支撐 vuepress 的運(yùn)作,這一點(diǎn)很像 webpack。

具體架構(gòu)如下:

從圖中我們可以看出,vuepress 被劃分成了兩個(gè)部分:前端部分和服務(wù)端(Node.js)部分。

    前端部分

1.1 UI,也就是站點(diǎn)主題使用的代碼。包括導(dǎo)航欄、側(cè)邊菜單、搜索框組件等。

1.2 當(dāng)前 Vue 實(shí)例的擴(kuò)展,提供了代碼注入(inject)、實(shí)例混入(mixin)、組件拓展(components)、路由拓展(routes)方式。

    服務(wù)端部分

2.1 構(gòu)建流程,這部分暴露出了 webpack、webpack-dev-server、markdown-it、動(dòng)態(tài)模塊的配置。

2.2 用戶文件,包括配置文件和 markdown 文件(文檔),這些文件相當(dāng)于站點(diǎn)的元數(shù)據(jù)。

2.3 主題,這部分被劃分為配置文件和布局組件。vuepress 提供了一份默認(rèn)的主題。

在這個(gè)架構(gòu)中,主題即插件。也就是說使用(開發(fā))一個(gè)主題和使用(開發(fā))一個(gè)插件的方式幾乎一致。

2.4 插件 API,這是今天我們重點(diǎn)介紹的部分,特別是插件機(jī)制的核心實(shí)現(xiàn)。

根據(jù)這個(gè)架構(gòu),vuepress 的插件便可以做很多事情了。具體用法可以參考文檔。

內(nèi)部插件和官方插件

讓我們先來了解一下 vuepress 的內(nèi)部插件和官方插件都有些什么,借助插件機(jī)制做了哪些事情。

內(nèi)部插件

    全局增強(qiáng):默認(rèn)用來實(shí)現(xiàn)全局應(yīng)用增強(qiáng)的邏輯。 它使用 enhanceAppFiles 指定增強(qiáng)全局應(yīng)用和主題的文件路徑。憑著這個(gè),vuepress 就能準(zhǔn)確地找到你全局增強(qiáng)或是主題的文件所在地。

    布局組件:默認(rèn)提供的布局組件。 它使用 clientDynamicModules 來實(shí)現(xiàn)動(dòng)態(tài)引入布局相關(guān)的組件。

    頁面組件:默認(rèn)提供的頁面組件(布局組件的子組件)。 它使用 clientDynamicModules 來實(shí)現(xiàn)動(dòng)態(tài)引入頁面相關(guān)的組件。

    根組件混入:默認(rèn)往根組件混入的邏輯。 它使用 clientDynamicModules 來實(shí)現(xiàn)動(dòng)態(tài)混入元信息。包括根組件的標(biāo)題、語言等。

    路由:默認(rèn)的生成路由邏輯。 它使用 clientDynamicModules 來實(shí)現(xiàn)動(dòng)態(tài)注冊路由。我們的 markdown 文件在轉(zhuǎn)換成 vue 組件后就是通過它自動(dòng)注冊到 vue-router 的。

    站點(diǎn)數(shù)據(jù):默認(rèn)的生成站點(diǎn)數(shù)據(jù)邏輯。 它使用 clientDynamicModules 來實(shí)現(xiàn)生成全局站點(diǎn)數(shù)據(jù)。我們在頁面里拿到的全局計(jì)算屬性 $site 就是這樣來的。

    模塊化轉(zhuǎn)化:將 cmd 代碼轉(zhuǎn)成 esm 代碼的邏輯。 還是用 clientDynamicModules 來實(shí)現(xiàn)將 cmd 代碼轉(zhuǎn)成 esm 代碼。主要是因?yàn)?ClientComputedMixin 這個(gè)類前后端代碼都要使用。

    樣式增強(qiáng) 全局樣式增強(qiáng)。使用 enhanceAppFiles 和 ready 鉤子來實(shí)現(xiàn)(主題樣式+用戶樣式+父主題樣式)。

    樣式覆蓋 全局樣式覆蓋,使用 ready 鉤子來實(shí)現(xiàn),覆蓋 config.styl 和父主題的 palette。

    dataBlock數(shù)據(jù)注入 解析 blockType=data 的數(shù)據(jù),使用 chainWebpack 和 enhanceAppFiles 來實(shí)現(xiàn),對 blockType=data 類型的數(shù)據(jù)注入到 markdown 生成的 vue 組件里去,每個(gè)組件可以訪問自己的 $dataBlock 屬性拿到。

官方插件

    活動(dòng)的標(biāo)題鏈接 它會(huì)在用戶滾動(dòng)頁面時(shí)自動(dòng)轉(zhuǎn)變側(cè)邊欄的高亮標(biāo)題。 它使用了 clientRootMixin 和 define 往根組件混入了滾動(dòng)邏輯:監(jiān)聽 onScroll 事件,獲取所有錨點(diǎn)元素并根據(jù)滾動(dòng)距離計(jì)算出高亮的錨點(diǎn)。

    回到頂部 使用了 enhanceAppFiles 和 globalUIComponents 注冊了一個(gè)全局組件:點(diǎn)擊后可以滾動(dòng)到頁面頂部。

    博客

    3.1 使用 extendPageData 創(chuàng)建標(biāo)簽頁和目錄頁

    3.2 使用 ready、clientDynamicModules、enhanceAppFile 創(chuàng)建頁面元數(shù)據(jù)。

    ga 谷歌分析站點(diǎn)的庫。使用了 define 和 enhanceAppFiles 初始化了 ga。

    國際化(廢棄) 可以讓你的站點(diǎn)擁有切換語言的能力。使用了 enhanceAppFiles 和 additionalPages 注冊了個(gè) I18n 布局組件。

    文檔的最近更新時(shí)間 可以讓每個(gè)文檔頁下面顯示最近的 git 提交時(shí)間。使用 extendPageData 拓展了 $page 的 lastUpdated 屬性。

    圖片預(yù)覽 集成了 medium-zoom。使用了 define、clientRootMixin 往根組件里混入了 zoom 的初始化和更新邏輯。

    分頁 讓共享側(cè)邊菜單欄的文檔擁有分頁切換的能力。使用了 enhanceAppFiles 定義了所有頁面的索引和順序。ready 定義了分頁的規(guī)則如排序規(guī)則等、clientDynamicModules 生成動(dòng)態(tài)模塊給前端代碼使用。

    pwa 集成 service-worker 功能 - 9.1. 使用 ready 開啟 serviceWorker 選項(xiàng) - 9.2. 使用 alias 實(shí)現(xiàn)用 vue 當(dāng)事件通道 - 9.3. 使用 define、globalUIComponents 注冊更新 PWA 應(yīng)用按鈕組件 - 9.4. 使用 enhanceAppFiles 注入 register-service-worker 的初始化和更新邏輯 - 9.5. 使用 generated 通過 workbox-build 完成 sw 功能

    注冊全局 Vue 組件 使用 enhanceAppFiles 把一個(gè)文件夾中的 vue 組件文件都注冊好。

    搜索框 使用 alias 和 define 讓搜索框可以動(dòng)態(tài)引入。

    進(jìn)度條 使用 clientRootMixin 和 enhanceAppFiles 集成 nprogress。

lerna

項(xiàng)目管理上,插件機(jī)制也使得原來的一個(gè)大項(xiàng)目拆成了 1 + N 的形式,package.json 也變得多了起來,為了管理這種項(xiàng)目,vuepress 引入了 lerna。

關(guān)于 lerna 的知識(shí),有興趣的讀者可以參考:lerna管理前端packages的最佳實(shí)踐。

核心實(shí)現(xiàn)

當(dāng)一系列插件要使用時(shí),需要通過 PluginAPI 和組成它的各種 Option 來實(shí)現(xiàn)。

整體流程大致如下:

這里我劃分成了兩個(gè)階段,用虛線分隔,一個(gè)是調(diào)用前階段,一個(gè)是調(diào)用后階段。插件們被調(diào)用前,是會(huì)被載入以及注冊的,之后化整為零,映射成若干個(gè) Option 實(shí)例。

源碼

    PluginAPI 類,這部分代碼包含了插件機(jī)制中的注冊調(diào)用實(shí)現(xiàn)。

    構(gòu)造(constructor):初始化選項(xiàng)、插件上下文、插件隊(duì)列(可注冊插件列表)、日志插件、初始化標(biāo)志位、插件解析器屬性,然后把選項(xiàng)們都裝載進(jìn)來(initializeOptions)。這里會(huì)把一個(gè)插件映射成若干個(gè) Option 實(shí)例。 例如,一個(gè)插件只有 ready、chainWebpack、additionalPages 三個(gè)選項(xiàng),則會(huì)得到三個(gè) Option 實(shí)例。

    使用(use),需要 _initialized 標(biāo)志為 false 才能調(diào)用,用于確認(rèn)哪些插件是可以被注冊的:

    對于非對象類型的插件,會(huì)調(diào)用 normalizePlugin 方法將之轉(zhuǎn)成對象

    期間會(huì)調(diào)用 _pluginResolver(ModuleResolver 實(shí)例) 來解析模塊

    用于解析模塊的 ModuleResolver 類,工作原理類似 webpack 的模塊解析。源碼

    這里值得一提的是 resolve 方法,它支持從非字符串包、npm 包、絕對路徑、相對路徑中解析模塊。

    相對路徑的模塊先使用 node 的原生 path.resolve 方法解析得到絕對路徑,然后交給解析絕對路徑模塊的方法處理。

    絕對路徑、非字符串包和 npm 包會(huì)用通用模塊 CommonModule 表示。

    通用模塊有四個(gè)屬性:entry、shortcut、name、fromDep。

    還會(huì)調(diào)用 flattenPlugin 拍平插件,主要是獲取配置。

    如果傳入配置是函數(shù),則返回調(diào)用后的結(jié)果,入?yún)椴寮x項(xiàng)、插件上下文、PluginAPI 實(shí)例。

    傳入的配置是對象,則返回一個(gè)拷貝后的對象。

    非 multiple 的插件,會(huì)根據(jù)插件名字去重。

    標(biāo)準(zhǔn)化后的插件,會(huì)加入到插件隊(duì)列中去。

    最后,存在插件中使用插件的情況時(shí),會(huì)調(diào)用 useByPluginsConfig 來實(shí)現(xiàn)。

    這里面的 normalizePluginsConfig 會(huì)將配置格式化成[[p1]、[p2]的形式]。

    初始化(initialize):先將 _initialized 標(biāo)志位置為 true,然后注冊所有可用的插件。

    在初始化之前,內(nèi)部插件的使用,會(huì)先于用戶的插件。

    注冊(applyPlugin):到這里,插件已經(jīng)被拆分成細(xì)化的選項(xiàng),按照信息類(pluginName、shortcut)、鉤子類(ready、compiled 等)、其他類(chainWebpack、chainMarkdown、enhanceAppFiles 等)按順序鏈?zhǔn)阶裕╮egisterOption)。

    此時(shí),一個(gè) Option 實(shí)例中已經(jīng)承載了若干個(gè)插件的邏輯了。

    enabledPlugins 和 disabledPlugins 兩個(gè)只讀屬性可以取啟用(可注冊)或禁用(不可注冊)的插件列表。

    getOption 可以取具體的一個(gè)選項(xiàng)實(shí)例,applyAsyncOption 和 applySyncOption 分別應(yīng)用異步選項(xiàng)和同步選項(xiàng)中的邏輯(回調(diào)函數(shù))。

選項(xiàng)和異步選項(xiàng),插件的本體

    Option 類 - 每個(gè)實(shí)例初始化 key(選項(xiàng)標(biāo)識(shí)) 和 items(這個(gè)選項(xiàng)所對應(yīng)的函數(shù)們) 屬性。

    重要方法:syncApply(也叫 apply),對之前保存在實(shí)例中的 items 遍歷調(diào)用 add 方法,如果 item 中的值是函數(shù),則執(zhí)行之取其返回值。

    在插件應(yīng)用選項(xiàng)時(shí)如果匹配成功,會(huì)調(diào)用 add 方法將選項(xiàng)映射成 1-n 個(gè)對象推入 items 屬性里。

    除了 add 還有 delete 和 clear 方法,不做贅述。(增刪清)

    另外有 values、entries 和 appliedValues 三個(gè)只讀屬性,用于獲取值、實(shí)體、已應(yīng)用的值。

    管道方法(pipeline),它將實(shí)例的 values 屬性柯里化成一個(gè)組合函數(shù),依次執(zhí)行。

    AsyncOption 類

    asyncApply 異步版syncApply,調(diào)用函數(shù)的時(shí)候使用了 await。

    parallelApply 如果說 pipeline 是串行,它就是并行:使用了 Promise.all

    pipeline 同理,調(diào)用函數(shù)的時(shí)候使用了 await。

特殊選項(xiàng)

    EnhanceAppFilesOption、ClientDynamicModulesOption、GlobalUIComponentsOption、DefineOption、AliasOption 類

    AliasOption

    在創(chuàng)建 webpack 配置的時(shí)候調(diào)用

    重寫 apply 方法:先調(diào)用 syncApply,然后將 appliedValues 取出,設(shè)置為 webpack 的 alias

    ClientDynamicModulesOption

    在 prepare 階段調(diào)用

    重寫 apply 方法:從 appliedItems 取出應(yīng)用的插件信息,遍歷寫入文件以待使用

    DefineOption

    類似 AliasOption,只不過是設(shè)置 webpack 的全局變量

    最后在 injections 插件(DefinePlugin)觸發(fā)時(shí)收集選項(xiàng)將 define 注入進(jìn)去

    EnhanceAppFilesOption

    在 prepare 階段調(diào)用

    重寫 apply 方法:從 appliedItems 取出插件信息,生成引入模塊或者注冊組件的代碼文件

    GlobalUIComponentsOption

    類似 ClientDynamicModulesOption,寫全局 ui 組件文件

調(diào)用函數(shù)型 Option 時(shí)機(jī)

    extendCli 創(chuàng)建 cli 命令時(shí)

    chainMarkdown 和 extendMarkdown 創(chuàng)建 MarkdownIt 實(shí)例時(shí)

    additionalPages 解析完所有頁面后 3、extendPageData additionalPages 執(zhí)行完之后,依賴 additionalPages 執(zhí)行完的結(jié)果

    ready 緊跟 additionalPages 之后

    clientDynamicModules、enhanceAppFiles、globalUIComponents 緊跟 ready 之后

    define、alias
    創(chuàng)建公共 webpack 配置后

    chainWebpack
    創(chuàng)建 dev webpack 配置后、創(chuàng)建 build webpack 配置后

    beforeDevServer
    webpack-dev-server 的 before 選項(xiàng)執(zhí)行后

    afterDevServer webpack-dev-server 的 after 選項(xiàng)執(zhí)行后

    generated build 完成后

    updated 文件更新后

    clientRootMixin
    clientDynamicModules 選項(xiàng)執(zhí)行時(shí)

編寫一個(gè) vuepress 插件

我也寫了一個(gè)小插件,它可以將你的 vuepress 站點(diǎn)下載成一個(gè) pdf 文件:vuepress-plugin-export-site

源碼

    使用 ready 選項(xiàng)

    借助 puppeteer 和 easy-pdf-merge 實(shí)現(xiàn):從上下文中拿到路由信息,然后使用 puppeteer 遍歷訪問并下載,最后合并成一個(gè)大 PDF。

    因?yàn)樾枰螺d chromium,所以國內(nèi)網(wǎng)絡(luò)受限。我們換成了 puppeteer-cn。

    easy-pdf-merge 如果在 windows 下運(yùn)行需要指定 jar 環(huán)境變量。

后記

我們熟悉的 webpack、vue 也有插件系統(tǒng),它們都有兩個(gè)共同的特點(diǎn):

    提供一個(gè)功能擴(kuò)展點(diǎn),讓插件能夠去擴(kuò)展它。

    提供一個(gè)功能注冊功能,讓插件注冊進(jìn)來。

其實(shí)插件機(jī)制也可以看做設(shè)計(jì)模式的一種體現(xiàn):抽離出變化的部分,保留不變的部分。這些變化的部分,便可以稱之為插件。

在我們造輪子的時(shí)候,如果輪子的功能越來越多,代碼越來越臃腫的話,引入插件機(jī)制會(huì)讓后續(xù)的開發(fā)更加靈活。

最后,幫插件機(jī)制的開發(fā)者真山同學(xué)宣傳一下,屆時(shí)會(huì)有更加精彩的 vuepress 分享:

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/6766.html

相關(guān)文章

  • 少女風(fēng)vue組件庫制作全攻略~~

    摘要:組件監(jiān)聽自定義事件。組件觸發(fā)自定義事件。生命周期鉤子函數(shù),后組件的所有的事件監(jiān)聽器會(huì)被移除。技術(shù)點(diǎn)總結(jié)組件設(shè)計(jì)的思想包括單數(shù)據(jù)流事件中心,核心是組件通信。完善給彈出日期面板和關(guān)閉日期面板增加組件自定義事件即調(diào)用觸發(fā)和事件。預(yù)覽 組件庫官網(wǎng) github地址 如果喜歡各位小哥哥小姐姐給個(gè)小星星鼓勵(lì)一下哈, 請勿在生產(chǎn)環(huán)境中使用,供學(xué)習(xí)&交流~~ showImg(https://user...

    springDevBird 評論0 收藏0
  • 基于 VuePress 定制個(gè)人博客網(wǎng)站

    摘要:簡單來說,是驅(qū)動(dòng)的靜態(tài)網(wǎng)站生成器。簡單易上手,同時(shí)也有足夠強(qiáng)大的定制能力,尤其對熟悉的前端開發(fā)人員而言。相比于知名的博客生成器來說,最大優(yōu)勢就是帶來的靈活性。本文就聊一聊基于的博客主題定制。VuePress 簡單來說,VuePress 是 Vue 驅(qū)動(dòng)的靜態(tài)網(wǎng)站生成器。VuePress 簡單易上手,同時(shí)也有足夠強(qiáng)大的定制能力,尤其對熟悉 Vue 的前端開發(fā)人員而言。相比于知名的博客生成器 H...

    FrancisSoung 評論0 收藏0
  • AntdSite - 一個(gè)基于React.Js靜態(tài)網(wǎng)站生成器

    摘要:前言簡介是一個(gè)基于的靜態(tài)網(wǎng)站生成器。后來我開始研究上了,開發(fā)組件就得有文檔呀,我在這期間陸續(xù)試了幾個(gè)基于的文檔生成器,像但是試用了下,感覺都不如順手。于是,就誕生了。文檔的界面設(shè)計(jì)來源于的官網(wǎng)。 前言 簡介 Antdsite 是一個(gè)基于 React.js 的靜態(tài)網(wǎng)站生成器。 它是由Gatsby Js驅(qū)動(dòng)的 使用 Ant Design設(shè)計(jì)構(gòu)建, 并且它的配置項(xiàng)借鑒了Vuepress ...

    jlanglang 評論0 收藏0
  • 這套VuePress主題你熟悉吧

    摘要:最近熬了很多個(gè)夜晚踩坑無數(shù)終于寫出了用驅(qū)動(dòng)的主題只需體驗(yàn)三分鐘,你就會(huì)跟我一樣,愛上這款主題已經(jīng)發(fā)布到請客官享用介紹的原主題是的數(shù)高達(dá)的有個(gè)它在靜態(tài)博客網(wǎng)站中的應(yīng)用處處可見在這里首先感謝原作者然而它的定位是僅支持等現(xiàn)代瀏覽器。 最近熬了很多個(gè)夜晚, 踩坑無數(shù), 終于寫出了用VuePress驅(qū)動(dòng)的主題. 只需體驗(yàn)三分鐘,你就會(huì)跟我一樣,愛上這款主題. vuepress-theme-ind...

    Jeffrrey 評論0 收藏0
  • vuepress搭建一個(gè)夠自己用博客

    原文博客 閑扯 很久以前,自己擁有一個(gè)用hexo搭建的靜態(tài)博客網(wǎng)站:ox:,記得當(dāng)時(shí)為了把它搞出來,廢了不少勁:anger:,然后后來又?jǐn)鄶嗬m(xù)續(xù)更改過一些配置和樣式,但是因?yàn)楦杏X各種麻煩,所以就放在github上積累和很多的塵土:cupid:,到現(xiàn)在也懶得在打掃了(其實(shí)是好久不用,有點(diǎn)忘了怎么用了:-1::poop:),前段時(shí)間在百度統(tǒng)計(jì)上看了看那個(gè)靜態(tài)網(wǎng)站的訪問人數(shù),發(fā)現(xiàn)已經(jīng)很久很久沒人訪問過了...

    Forelax 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<