国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

April / 4070人閱讀
前言

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

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

具體架構如下:

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

    前端部分

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

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

    服務端部分

2.1 構建流程,這部分暴露出了 webpack、webpack-dev-server、markdown-it、動態模塊的配置。

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

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

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

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

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

內部插件和官方插件

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

內部插件

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

    布局組件:默認提供的布局組件。 它使用 clientDynamicModules 來實現動態引入布局相關的組件。

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

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

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

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

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

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

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

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

官方插件

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

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

    博客

    3.1 使用 extendPageData 創建標簽頁和目錄頁

    3.2 使用 ready、clientDynamicModules、enhanceAppFile 創建頁面元數據。

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

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

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

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

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

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

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

    搜索框 使用 alias 和 define 讓搜索框可以動態引入。

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

lerna

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

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

核心實現

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

整體流程大致如下:

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

源碼

    PluginAPI 類,這部分代碼包含了插件機制中的注冊調用實現。

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

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

    對于非對象類型的插件,會調用 normalizePlugin 方法將之轉成對象

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

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

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

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

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

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

    還會調用 flattenPlugin 拍平插件,主要是獲取配置。

    如果傳入配置是函數,則返回調用后的結果,入參為插件選項、插件上下文、PluginAPI 實例。

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

    非 multiple 的插件,會根據插件名字去重。

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

    最后,存在插件中使用插件的情況時,會調用 useByPluginsConfig 來實現。

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

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

    在初始化之前,內部插件的使用,會先于用戶的插件。

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

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

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

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

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

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

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

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

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

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

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

    AsyncOption 類

    asyncApply 異步版syncApply,調用函數的時候使用了 await。

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

    pipeline 同理,調用函數的時候使用了 await。

特殊選項

    EnhanceAppFilesOption、ClientDynamicModulesOption、GlobalUIComponentsOption、DefineOption、AliasOption 類

    AliasOption

    在創建 webpack 配置的時候調用

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

    ClientDynamicModulesOption

    在 prepare 階段調用

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

    DefineOption

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

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

    EnhanceAppFilesOption

    在 prepare 階段調用

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

    GlobalUIComponentsOption

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

調用函數型 Option 時機

    extendCli 創建 cli 命令時

    chainMarkdown 和 extendMarkdown 創建 MarkdownIt 實例時

    additionalPages 解析完所有頁面后 3、extendPageData additionalPages 執行完之后,依賴 additionalPages 執行完的結果

    ready 緊跟 additionalPages 之后

    clientDynamicModules、enhanceAppFiles、globalUIComponents 緊跟 ready 之后

    define、alias
    創建公共 webpack 配置后

    chainWebpack
    創建 dev webpack 配置后、創建 build webpack 配置后

    beforeDevServer
    webpack-dev-server 的 before 選項執行后

    afterDevServer webpack-dev-server 的 after 選項執行后

    generated build 完成后

    updated 文件更新后

    clientRootMixin
    clientDynamicModules 選項執行時

編寫一個 vuepress 插件

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

源碼

    使用 ready 選項

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

    因為需要下載 chromium,所以國內網絡受限。我們換成了 puppeteer-cn。

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

后記

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

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

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

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

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/6766.html

相關文章

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

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

    springDevBird 評論0 收藏0
  • 基于 VuePress 定制個人博客網站

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

    FrancisSoung 評論0 收藏0
  • AntdSite - 一個基于React.Js靜態網站生成器

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

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

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

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

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

    Forelax 評論0 收藏0

發表評論

0條評論

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