成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

讀?VuePress(四)插件機制的設計

April / 4074人閱讀
前言

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

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

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

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

    前端部分

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

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

    服務端部分

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

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

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

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

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

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

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

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

內(nèi)部插件

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

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

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

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

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

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

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

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

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

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

官方插件

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

    回到頂部 使用了 enhanceAppFiles 和 globalUIComponents 注冊了一個全局組件:點擊后可以滾動到頁面頂部。

    博客

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

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

    ga 谷歌分析站點的庫。使用了 define 和 enhanceAppFiles 初始化了 ga。

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

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

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

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

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

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

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

    進度條 使用 clientRootMixin 和 enhanceAppFiles 集成 nprogress。

lerna

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

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

核心實現(xiàn)

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

整體流程大致如下:

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

源碼

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    標準化后的插件,會加入到插件隊列中去。

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

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

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

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

    注冊(applyPlugin):到這里,插件已經(jīng)被拆分成細化的選項,按照信息類(pluginName、shortcut)、鉤子類(ready、compiled 等)、其他類(chainWebpack、chainMarkdown、enhanceAppFiles 等)按順序鏈式注冊(registerOption)。

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

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

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

選項和異步選項,插件的本體

    Option 類 - 每個實例初始化 key(選項標識) 和 items(這個選項所對應的函數(shù)們) 屬性。

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

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

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

    另外有 values、entries 和 appliedValues 三個只讀屬性,用于獲取值、實體、已應用的值。

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

    AsyncOption 類

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

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

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

特殊選項

    EnhanceAppFilesOption、ClientDynamicModulesOption、GlobalUIComponentsOption、DefineOption、AliasOption 類

    AliasOption

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

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

    ClientDynamicModulesOption

    在 prepare 階段調(diào)用

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

    DefineOption

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

    最后在 injections 插件(DefinePlugin)觸發(fā)時收集選項將 define 注入進去

    EnhanceAppFilesOption

    在 prepare 階段調(diào)用

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

    GlobalUIComponentsOption

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

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

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

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

    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 選項執(zhí)行后

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

    generated build 完成后

    updated 文件更新后

    clientRootMixin
    clientDynamicModules 選項執(zhí)行時

編寫一個 vuepress 插件

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

源碼

    使用 ready 選項

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

    因為需要下載 chromium,所以國內(nèi)網(wǎng)絡受限。我們換成了 puppeteer-cn。

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

后記

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

    提供一個功能擴展點,讓插件能夠去擴展它。

    提供一個功能注冊功能,讓插件注冊進來。

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

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

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

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

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

相關(guān)文章

  • 少女風vue組件庫制作全攻略~~

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

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

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

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

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

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

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

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

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

    Forelax 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<