摘要:在我轉(zhuǎn)前端以來(lái),一直想要實(shí)現(xiàn)一個(gè)愿望自己搭建一個(gè)可以自動(dòng)解析文檔的個(gè)人站今天終于實(shí)現(xiàn)啦,先貼上我的地址確認(rèn)需求其實(shí)一個(gè)最簡(jiǎn)單的個(gè)人站,就是許多的頁(yè)面,你只要可以用寫(xiě)出來(lái)就可以,然后掛到上。
在我轉(zhuǎn)前端以來(lái),一直想要實(shí)現(xiàn)一個(gè)愿望:
“自己搭建一個(gè)可以自動(dòng)解析Markdown文檔的個(gè)人站”
今天終于實(shí)現(xiàn)啦,先貼上我的blog地址
確認(rèn)需求其實(shí)一個(gè)最簡(jiǎn)單的個(gè)人站,就是許多的HTML頁(yè)面,你只要可以用HTML寫(xiě)出來(lái)就可以,然后掛到Github pages上。但這并不是我想要的。
也有許多的人會(huì)選擇用Vuepress,Hexo,Wordpress,Jekyll等等這樣的博客框架來(lái)搭建自己的博客,我也都嘗試過(guò),有很多的主題可以給你選擇,你甚至可以自己寫(xiě)一個(gè)主題或者修改其他人的主題讓你的博客變得獨(dú)一無(wú)二,但這也不是我想要的。
那,我想要的是什么呢?
用Markdown語(yǔ)法書(shū)寫(xiě)博客,支持代碼高亮。
博客所有頁(yè)面都是自定義樣式。
Markdown的YAML開(kāi)頭支持自定義字段,便于在頁(yè)面上展示。
在寫(xiě)博客的同時(shí)支持頁(yè)面更新,實(shí)時(shí)看到效果。
其他博客基本的功能。
其實(shí)上面很多的博客系統(tǒng),或者靜態(tài)博客生成器,都可以滿(mǎn)足上面大部分的條件,我沒(méi)有使用的原因主要是以下幾點(diǎn):
我很難把控整個(gè)流程,如果我在其他人的主題頁(yè)面想要增加一些功能,很吃力。
對(duì)博客的配置,都會(huì)有預(yù)料之外的效果。
一些主題也不完善,總是少了自己需要的功能,并且對(duì)于Markdown一些基本的功能的支持,也參差不齊。
頁(yè)面的構(gòu)造和樣式的調(diào)整,自由度不夠。
分析需求看到這些需求,其實(shí)重點(diǎn)不在于你要用什么框架來(lái)寫(xiě)。vue也好react也好甚至Jquery或者原生的JS,都可以。
重點(diǎn)在于你如何處理Markdown文件,把它轉(zhuǎn)換成你需要的對(duì)象,并且在你的頁(yè)面中,可以通過(guò)路由來(lái)控制頁(yè)面的內(nèi)容的切換。
簡(jiǎn)而言之,就是兩點(diǎn):
博客數(shù)據(jù)
頁(yè)面路由
當(dāng)你可以解決這兩個(gè)問(wèn)題,那就解決了所有的問(wèn)題,因?yàn)槭O碌木褪菙]頁(yè)面了,天高任你飛,和太陽(yáng)肩并肩。
數(shù)據(jù)的獲取或許也可以換一個(gè)小標(biāo)題,怎樣拿到Markdown里面的數(shù)據(jù),并且在頁(yè)面上讀取數(shù)據(jù)呢?
需要這個(gè)數(shù)據(jù)是因?yàn)榭紤]到,在首頁(yè)你可能需要展示所有的頁(yè)面分類(lèi),和所有的Tags,甚至所有的文章的標(biāo)題和內(nèi)容,因?yàn)槟阈枰鲆粋€(gè)博客的檢索?
我把以上提到的所有的博客框架的源碼看了一遍,想看看對(duì)他們是怎么處理這個(gè)問(wèn)題的。
然后在我首先在React-static的元am里面,找到了這個(gè):Jdown
這是一個(gè)解析Markdown的包,甚至一開(kāi)始我都是用這個(gè)來(lái)解析我的Markdown文件中的YAML標(biāo)簽的內(nèi)容,并且我還和包的作者DanWebb聊了很多關(guān)于搭建個(gè)人站的問(wèn)題。
直到我項(xiàng)目的最后才發(fā)現(xiàn),這個(gè)包使用起來(lái)會(huì)有一些問(wèn)題,對(duì)于一些過(guò)長(zhǎng)的中文,可能他會(huì)解析失敗,我也找不到規(guī)律,對(duì)于我來(lái)說(shuō),要去閱讀他的源碼來(lái)定位問(wèn)題,需要太多的時(shí)間,然后我想找一個(gè)替代的包,來(lái)實(shí)現(xiàn)同樣的功能。
然后我就找到了gray-matter
我用這個(gè)包成功的把Markdown文件的YAML頭解析為一個(gè)JSON對(duì)象。我是怎么做的呢?
在項(xiàng)目(打包/編譯)的JS中:
遍歷一個(gè)固定目錄(也就是我所有md文件存放的目錄),獲取到所有的以md結(jié)尾的文件對(duì)象。
對(duì)每個(gè)文件的YAML頭信息進(jìn)行轉(zhuǎn)換,拿到JSON對(duì)象。
對(duì)JSON對(duì)象的內(nèi)容進(jìn)行解析,例如取出所有的tag存放到同一個(gè)數(shù)組中(你也可以放在頁(yè)面上來(lái)做這件事)
把所有的頁(yè)面的JSON對(duì)象放在一個(gè)數(shù)組里,用nodeJS的fs模塊寫(xiě)入到一個(gè)data.js的文件中(這個(gè)你可以自己定義目錄)
至此,所有頁(yè)面獲取數(shù)據(jù)的過(guò)程就結(jié)束了。
在頁(yè)面上使用的時(shí)候,就只需要引入這個(gè)data.js的文件然后就可以拿到頁(yè)面的數(shù)據(jù)啦~
頁(yè)面路由是我們實(shí)現(xiàn)這個(gè)博客系統(tǒng)的關(guān)鍵,因?yàn)樵谏弦徊剑覀冎皇悄玫搅?b>YAML的信息,但是我們并沒(méi)有拿到這個(gè)文檔內(nèi)容,就算我們拿到了內(nèi)容,也需要我們把他解析為HTML之后,才可以展示出來(lái),那現(xiàn)在怎么做呢?
其實(shí)用過(guò)webpack的人都知道,webpack有一個(gè)loader,我們就是用到markdown的loader來(lái)做這樣一件事情,loader就像是一個(gè)翻譯工具,把源文件的內(nèi)容處理之后,返回新的結(jié)果,甚至可以多重翻譯之后再返回。那我們就需要用Markdown的loader.
那我們可以在路由中設(shè)置,把component設(shè)置成對(duì)應(yīng)的md文件,這時(shí)候Webpack就會(huì)使用loader來(lái)解析這個(gè)md文件,變成我們需要的HTML頁(yè)面,同時(shí)我們也可以在解析的過(guò)程中,加入自定義的語(yǔ)法,增強(qiáng)和自定義我們的markdown。
在router文件中的設(shè)置類(lèi)似于下面這樣
{ path: "/post/2018-05-20-first", component: () => import("../posts/2018-05-20-first.md") }
你以為就這樣簡(jiǎn)單的結(jié)束了嗎?
太天真了少年,因?yàn)閣ebpack是不支持import的動(dòng)態(tài)參數(shù)的,也就是說(shuō),頁(yè)面跑起來(lái)之后,想要通過(guò)YAML的信息,來(lái)拼接出router的值,是不可行的,就算你可以拿到文件名。
我們總不能寫(xiě)一篇文章,就往這個(gè)router里面加入一條記錄吧?
這一步也困擾了我很久,通過(guò)資料的搜集和查看其它人的源碼,我在Vuepress的源碼中找到了答案。尤大大是怎么做的呢?
有興趣的朋友可以閱讀一下Vuepress的源碼,關(guān)鍵文件的路徑是~/lib/prepare/codegen.js
代碼貼出來(lái)(關(guān)鍵的信息我已經(jīng)打上了注釋):
exports.genRoutesFile = async function ({ siteData: { pages }, sourceDir, pageFiles }) { function genRoute ({ path: pagePath, key: componentName }, index) { const file = pageFiles[index] const filePath = path.resolve(sourceDir, file) // 這一段實(shí)際上就是你的路由信息 let code = ` { name: ${JSON.stringify(componentName)}, path: ${JSON.stringify(pagePath)}, component: ThemeLayout, beforeEnter: (to, from, next) => { import(${JSON.stringify(filePath)}).then(comp => { Vue.component(${JSON.stringify(componentName)}, comp.default) next() }) } }` const dncodedPath = decodeURIComponent(pagePath) if (dncodedPath !== pagePath) { code += `, { path: ${JSON.stringify(dncodedPath)}, redirect: ${JSON.stringify(pagePath)} }` } if (//$/.test(pagePath)) { code += `, { path: ${JSON.stringify(pagePath + "index.html")}, redirect: ${JSON.stringify(pagePath)} }` } return code } const notFoundRoute = `, { path: "*", component: ThemeNotFound }` return ( // 這里你可以放入很多其他的需要在路由文件里面引入的信息 `import ThemeLayout from "@themeLayout" ` + `import ThemeNotFound from "@themeNotFound" ` + `import { injectMixins } from "@app/util" ` + `import rootMixins from "@app/root-mixins" ` + `injectMixins(ThemeLayout, rootMixins) ` + `injectMixins(ThemeNotFound, rootMixins) ` + `export const routes = [${pages.map(genRoute).join(",")}${notFoundRoute} ]` ) }
這個(gè)文件在做什么呢?既然import不支持動(dòng)態(tài)的參數(shù),那我們就直接生成一個(gè)router文件,然后使用這個(gè)router來(lái)配置我們的路由不就可以了嗎?
在自己的代碼里面,把這一步加入到解析markdown的YAML信息這個(gè)步驟里,這樣我在拿到了頁(yè)面基本信息的同時(shí),也進(jìn)行了路由的配置。
完成圖經(jīng)過(guò)一些頁(yè)面的設(shè)計(jì),終于完成啦,這里也貼一下blog的源碼,歡迎大家star
貼一波圖:
首頁(yè):
Contact 頁(yè)面:
Tags 頁(yè)面:
Post頁(yè)面:
寫(xiě)在最后這個(gè)blog系統(tǒng),也零零碎碎花了接近一個(gè)月的時(shí)間,終于是告一段落了,當(dāng)然這篇文章里面會(huì)有許多我沒(méi)有提到的部分,比如怎么部署到域名下啊,怎么打包編譯發(fā)布到github pages,怎么實(shí)現(xiàn)一些頁(yè)面的效果。
為什么我沒(méi)有寫(xiě)這些呢?因?yàn)檫@些都有許多現(xiàn)成的答案啦。
最后新人求一波關(guān)注啦~關(guān)于這個(gè)blog系統(tǒng),如果你有任何不清楚的地方,可以留下你的評(píng)論,或者與我聯(lián)系~
轉(zhuǎn)載請(qǐng)注明出處。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/52677.html
摘要:更新日志更新完成靜態(tài)頁(yè)面原型修復(fù)使用的正確姿勢(shì)更新添加靜態(tài)頁(yè)面更新添加使用方法請(qǐng)戳我主要作用就是在你開(kāi)發(fā)環(huán)節(jié)在后端同學(xué)還未開(kāi)發(fā)完成的情況下,提供一個(gè)。 底下評(píng)論說(shuō)是標(biāo)題黨,或者是光扔個(gè)github地址上來(lái)的同學(xué)我就不說(shuō)什么了。你們有看看倉(cāng)庫(kù)的提交記錄么?我還沒(méi)有吃撐到開(kāi)個(gè)倉(cāng)庫(kù)去騙star.我的出發(fā)點(diǎn)就是每天更新一部分代碼,教大家用我所提到的技術(shù)棧搭建一個(gè)blog,我的出發(fā)點(diǎn)就是這么簡(jiǎn)單...
摘要:前端的所使用的技術(shù)棧后端這個(gè)小項(xiàng)目才開(kāi)始,使用已經(jīng)搭建好了前端開(kāi)發(fā)環(huán)境及相應(yīng)的的配置。接下來(lái)我會(huì)帶著大家一起完成整個(gè)簡(jiǎn)書(shū)的開(kāi)發(fā)工作。 這是一個(gè)開(kāi)源的個(gè)人項(xiàng)目。 前端的所使用的技術(shù)棧: typescriptes6vue2vue-cliwebpack2axiosangular4angular-cli 后端: nodejsmongoDBejs 這個(gè)小項(xiàng)目才開(kāi)始,使用vue-cli已經(jīng)搭建好了...
摘要:終極解決方案所以我們要統(tǒng)一環(huán)境,直接使用渲染我們的組件,文檔可以參照音樂(lè)標(biāo)題歌手專(zhuān)輯時(shí)長(zhǎng)省去一些細(xì)節(jié)注意需要放在中,的透?jìng)饕膊灰耍@樣我們?cè)谕獠肯胧褂玫囊恍傩院褪录疟容^方便。 背景介紹 最近在做vue高仿網(wǎng)易云音樂(lè)的項(xiàng)目,在做的過(guò)程中發(fā)現(xiàn)音樂(lè)表格這個(gè)組件會(huì)被非常多的地方復(fù)用,而且需求比較復(fù)雜的和靈活。 預(yù)覽地址 源碼地址 圖片預(yù)覽 歌單詳情 showImg(https://se...
閱讀 1617·2021-11-22 14:45
閱讀 1063·2021-11-17 09:33
閱讀 3322·2021-09-02 09:48
閱讀 969·2019-08-30 15:54
閱讀 2767·2019-08-30 15:53
閱讀 2553·2019-08-30 12:54
閱讀 2241·2019-08-29 12:37
閱讀 2421·2019-08-26 13:58