通過 1 個月的咕咕咕,總算把博客初步搭建好了,按照慣例先丟個連接你們有興趣能夠來逛逛: blog.mytyiluo.cn。javascript
主要特色以下:css
以前其實一直用的是 GitBook,但說實話,GitBook 仍是更加適合書籍/教程等的寫做,對隨筆來講仍是感受少了點功能。並且官方也表示以後再也不維護命令行程序了,所以決定慢慢的從這平臺遷移出來。html
在這過程當中,有考慮過使用 Hexo 做爲博客引擎,想本身寫一套主題,但無奈不習慣它的模板語法,最終仍是選擇了放棄。java
而後,考慮到開發的難度和靈活性,決定使用基於 React 的靜態網頁引擎,也就是 GatsbyJS。node
其中,最吸引個人即是它對多數據源的內建支持,並以 GrapQL 的形式統一提供數據,很是符合我對後期拓展的預期。此外,豐富的社區插件倒算是額外的驚喜,特別是支持 TypeScript 和 Less 對開發帶來了極大的方便,支持響應式圖片和 PWA 也省去了我大量的精力。react
博客應該支持豐富的元信息,但大多數參數應該根據約定生成默認值;git
例如,博客標題通常會和文件名相同; 同一文件夾下的博客應該爲同一個主題;github
博客對各種代碼應該有良好的展現,且支持插入多媒體內容,例如:Gist,B 站視頻等;typescript
廢話了那麼多,仍是得講些技術性的話題。shell
關於 Gatsby 的參考資料其實並不須要太大,官方文檔再加官方教程已經足夠了。若涉及到插件的話,相應的文檔和源碼也均可以在 GitHub 找到。
默認 GraphQL 執行的結果類型,不出意外都是 any 。但既然在使用 Ts 了,我仍是但願它是強類型的變量。可問題是根據不一樣的查詢語句返回的類型也都不同,因此單獨爲每個查詢定義類型工程量太大(懶)。
解決方案就是採用現成的代碼生成器:
yarn add --dev @graphql-codegen/cli @graphql-codegen/typescript
在根目錄下添加配置文件 codegen.yml :
# 這裏端口爲 gatsby develop 的端口 schema: http://localhost:8000/___graphql generates: src/types.ts: plugins: - typescript # 默認類型爲 T | null | undefined # 這裏爲了偷懶就直接改成了 T config: avoidOptionals: true maybeValue: T
而後運行:
graphql-codegen --config codegen.yml
便可,咱們能夠在 src 文件夾中找到定義文件 types.ts 。
CSS Module 是 Gatsby 所支持的一種樣式表導入方式,其優勢是在獨立的 css/less 文件中編寫,能夠得到完美的 IDE 支持,且不一樣模塊之間的樣式不會相互干擾。
但當其導入 ts 文件中後,會被提示沒法解析類型。
我採用的解決方案相對暴力,在 src 文件夾下創建一個 global.d.ts 文件:
// 若你使用的不是less的話,改爲相應的後綴就行 declare module "*.less" { const content: { [className: string]: string }; export = content; }
若是 IDE 還不能識別其類型,能夠在根目錄的 tsconfig.json 中添加:
{ // ... "typeAcquisition": { "include": ["./src/global.d.ts"] } }
若還不行能夠嘗試重啓下 IDE。
默認的狀況下,CSS Module 生成的樣式名的格式爲:
[path][name]__[local]--[hash:base64:5]
顯然在多級目錄鑲嵌以後,其長度會是很是嚇人的,並且會影響傳輸效率(即便用 Gzip)。
總之,我但願這樣式名在生產環境下短一些,解決方案以下:
在 gatsby-config.js 中配置 gatsby-plugin-less 選項:
{ resolve: `gatsby-plugin-less`, options: { cssLoaderOptions: { minifyClassNames: true, localIdentName: process.env.NODE_ENV === "development" ? "[path][name]__[local]--[hash:base64:5]" : "[hash:base64:5]", }, }, }
sharp 是 gatsby-plugin-sharp 的依賴項,提供圖像編輯處理的能力。 經過分析其安裝過程和文檔,咱們能夠將問題定位到 libvips 上,sharp 在 build 階段會從 github 下載 libvips 的預編譯版本(大概 14MB),但因爲國內網速的緣由致使其加載時間過長甚至加載失敗。
那解決方案就是經過任意手段下載對應版本的 libvips 將其複製到對應的緩存目錄下,通常爲:
C:\Users\[你的用戶名]\AppData\Roaming\npm-cache\_libvips
考慮到 GA 在國內可能有些問題,這裏仍是選用了百度統計做爲統計分析平臺。同時,百度統計平臺還能夠主動將站點信息提交到百度搜索引擎,提升站點收錄的效率。
在 Gatsby 的社區插件中已經有實現了添加百度統計的插件,但我看了下它的源碼感受挺簡單的,且爲了方便以後再更換其餘統計平臺,這裏打算是本身實現一下。
首先,咱們須要註冊一個百度統計的帳號,而後在管理界面中獲取對應的代碼:
根據文檔說明,咱們須要將這段代碼添加到每一個頁面的<head>
中。
這裏,就須要用到 gatsby-ssr.js 中的接口 onRenderBody ,具體信息能夠查看文檔。 代碼以下:
// 由於在下方用到了JSX,因此須要導入React var React = require("react"); exports.onRenderBody = ({ setHeadComponents }) => { if (process.env.NODE_ENV === `production`) { setHeadComponents([ // 這裏的形式是爲了異步加載 <script key="baidu-analytics-script" dangerouslySetInnerHTML={{ __html: ` var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?ff306397dbce7dab4357bd037fa286ca"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); ` }} /> ]); } };
在我設置的字段中,每篇博客都會包含一個 tags,類型爲 string[]。在首頁中,我但願根據標籤計數的降序顯示計數大於 2 的標籤。
其實,這個問題就至關於處理鑲嵌數組,處理難度並不高,但此前每每須要寫很多的代碼,這裏基於 lodash 的 chain 實現了一個相對「簡潔」的版本:
// data 就是根據 GraphQL 獲得的數據 // const data = this.props.data.statistics.nodes; // // Scheme 定義以下: // statistics: allMarkdownRemark( // filter: { fields: { name: { ne: "README" }, posted: { ne: false } } } // ) { // nodes { // fields { // topic // tags // } // } // } const tags = _ // 包裝爲 chain 對象 .chain(data) // 只須要 tags 字段 .map(e => e.fields.tags) // 展開二維數組 .flatten() // 對標籤計數 // 這裏返回的爲對象 { tag: count } .countBy() // 篩選計數大於 2 的標籤 .pickBy((value, key) => value > 2) // 將對象轉爲數組 .map((value, key) => ({ tag: key, count: value })) // 根據計數降序排列 .orderBy("count", "desc") // 只須要 tag 字段 .map(e => e.tag) // 解除 chain 包裝 .value();
至此,主要記錄的是在開發階段遇到的一些坑和小技巧。下一篇,我想簡要敘述一下設計這個博客的思路,若是我還記得這個坑的話。