用Nuxt.js改寫舊的專案


離上一篇 “關於我寫的乃木坂部落格備份站” 已經過了將近一年,當時的文章最後提到的幾個未來計畫要做的項目中其中一項:將整個網站用 Nuxt.js 改寫,終於於近期完成任務並上線了。

改寫的過程

有關 Nuxt.js 的基礎知識,我主要參考自這一篇文章:

SSR — Nuxt.js 超入門

理解 asyncData

從舊的 Vue.js 程式轉換成 Nuxt.js ,我卡最久的工作之一就是理解哪些事情要改在 asyncData() 去執行。
他是一個很神奇的設計,無論是在後端預先渲染還是前端正式執行的時候,都會呼叫到這個方法,所以我原本使用 http 連線去下載 json 檔的作法並不可行。

最後是參考官方的討論串:What is the best way to load json.
在程式裡面下判斷式,如果在後端就用 fs.readFile(),如果在前端則使用 fetch()

async asyncData(){
  let data;
  if(process.server){
    data= JSON.parse(await fs.readFile('xxx.json'));
  }else{
    data = await(await fetch('/xxxx.json')).json();
  }
}

理解的過程,你會需要不斷翻閱的官方文件:
Nuxt Lifecycle - NuxtJS

生成靜態網站

如果你建立專案的時候什麼設定都沒有改,那你最後建置出來的成品不會是一個靜態網站,而是一個要用 node.js 執行的伺服器程式。直到你在 nuxt.config.jstarget 指定成 static 他才會改輸出靜態網站:

export default {
  target: "static", // default is 'server'
};

改過之後你每次部署都要先執行 build,接著再執行 generate,這樣你才會在 ./dist 資料夾看到成果。

不過很不幸的如果你的程式有用到動態路由,那動態路由的頁面會全部消失,因為程式不知道你到底有哪些頁面要生成,你需要自己在 nuxt.config.js 裡面把路由表生成出來

export default {
  generate: {
    routes() {
      return ["page1", "page2"]; //自己生成這個陣列
    },
  },
};

生成陣列的方法可以獨立成一支程式,下一段還用的到。

有關靜態網站的官方文件:Static Hosting - NuxtJS

Sitemap

官方有套件 @nuxtjs/sitemap 可以使用,安裝好之後他就會自動生成 sitemap,但會遇到跟上面一樣的問題,動態路由記得要自己宣告。

301 轉址

我這次改寫的過程,一併更改了網址的路徑,他給我帶來了兩個額外的麻煩,仔細想想有點後悔當初為何改這樣的設計。

舊網址:/nanase.nishino/index.html
新網址:/mb/nanase.nishino/

第一個麻煩就是這裡要提到的,我需要為了 SEO 把舊的流量留住,不能出現 404 畫面,所以我在原本對應的路由上新增一支程式,透過在 html head 區塊塞資料的方式完成轉址

<head>
  <meta http-equiv="refresh" content="0; url=NEW_URL" />
  <link rel="canonical" href="NEW_URL" />
</head>

meta :讓網頁載入的時候就馬上重新導向至新網址
link :跟搜尋引擎宣告新網址才是標準網址

多虧這個是 Nuxt 的專案,所以我可以在新的 head() 區塊完成以上宣告。

第二個麻煩是部落格內文的圖片相對路徑全錯,這個我就比較土法煉鋼,直接用正規表達式把路徑全改了…

新增的功能

這次改版不單純只是搬遷,我還額外補上了幾個小東西

1.內文搜尋

搜尋功能因為我自己覺得只靠前端完成應該會嚴重拖累效能所以遲遲沒有設計,實際做好之後的成果還不錯,雖然確實會卡頓一下,但應該還在可以被接受的程度?

原理也很單純,在輸入搜尋關鍵字之後,程式會去把所有的部落格文章用 DOMParser 把純文字的部分取出,然後就用字串比對的方式生成結果。

getInnerText(html) {
  let dom = this.domParser.parseFromString(html, "text/html");
  return dom.activeElement.innerText;
}

另外是搜尋結果會高亮顯示,此功能仰賴第三方套件 mark.js 完成

2.分享


這次做了兩個分享鈕,第一個沒什麼好說的,分享至 Twitter,這部分遵照官方文件生成一個帶指定參數的 intent url 就可以了。比較有趣的是第二顆分享鈕。

他會觸發系統原生的分享畫面,截圖是 Windows 10 的,你如果用手機瀏覽的話,會顯示 Android 或 iOS 作業系統本身的分享介面,類似下圖。

圖片來源 - Microsoft Docs

這是 Web Share API 提供的功能,讓你可以透過簡單的 js 程式去觸發:

let data = {
  title: this.title,
  url: this.url,
};
await navigator.share(data);

剩餘的目標

除了改寫之外,當時還列了幾個其他的目標:

後記

感謝每個使用過這個專案的使用者,知道有人在瀏覽、看到有人分享,都是讓我繼續維護這個專案的動力來源。即使你們大部分都是日文使用者根本看不懂這篇文章,但還是謝謝:)

最後附上專案連結,喜歡的話賞個星星吧
janelin612/n46-crawler: Nogizaka46 Blog Crawler - 乃木坂 46 卒業成員部落格備份工具

Hi 喜歡這篇文章的話 可以按個讚或請我喝杯咖啡
Buy me a coffeeBuy me a coffee