iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
1
Modern Web

從 0 開始建一個 Static Site Generator系列 第 14

Day 14: 用 Helmet 管理 head 的內容

這系列的程式碼在 https://github.com/DanSnow/ironman-2020/tree/master/static-site-generator

抱歉上一篇結尾時又記錯了,這篇要來處理 html 中的 head 的部份,這次會用到一個叫 react-helmet 的套件,它可以在 Client 端管理 head 的內容,但同時也可以在 Server 端幫你搜集元件所要求的設定,讓你可以在 Server 端渲染出元件要的標題等等的,這次來幫文章頁面加上修改網頁標題的功能

這次新增一個檔案在 generator/index.js ,注意,不是在 src 下喔, src 下已經被拿來放 Server 端的 code 了,這次的 index.js 是之後要拿來放提供給使用者用的 API 的部份,目前檔案的內容很簡單,就是把 Helmet export 出去而已:

export { Helmet } from 'react-helmet'

就算是使用第三方套件的東西,也重新從我們的套件 export 出去,而使用者則用我們 export 的版本,這樣就可以確保使用者用的跟我們用的是同一個版本了

然後在 Article.js 加上修改標題的部份:

export function Article({ article = getArticle() }) {
  const { title, content } = article

  return (
    <article>
      <Helmet>
        <title>My Blog - {title}</title>
      </Helmet>
      <h1 className="text-4xl text-center font-bold mb-8">{title}</h1>
      <p className="text-gray-700">{content}</p>
    </article>
  )
}

另外在 src/app/AppProvider.js 的部份加上預設的 Helmet 的標題:

export function AppProvider({ store, location, children, title }) {
  return (
    <Provider store={store}>
      <Helmet>
        <title>{title}</title>
      </Helmet>
      <StaticRouter location={location}>{children}</StaticRouter>
    </Provider>
  )
}

這樣就把 title 完全交給 Helmet 管理了,但也因為這樣,我們的 html template 的部份也要修改:

<html>
  <head>
    <%~ it.title %>
  </head>
</html>

接著這邊就是重點了,因為要讓 Helmet 先收集元件要求的值,所以 renderToString 的部份要先執行:

async function renderHTML(location) {
  // 省略

  const defaultTitle = config.title || pkg.name || 'My Static site'
  const output = renderToString(
    <AppProvider store={store} location={location} title={defaultTitle}>
      {renderRoutes(routes, notFound)}
    </AppProvider>
  )

  // 這可以清空 Helmet 的內部狀態,並回傳到目前搜集到的值
  const helmet = Helmet.renderStatic()

  const template = await templatePromise
  return render(template, {
    title: helmet.title.toString(),
    output,
  })
}

這樣就可以試試看了,頁面的標題應該會隨著文章的標題改變了,不過 Helmet 還可以用來管理其它的值,這邊我就直接加上去而不在這邊說明了,而且如果都由 Helmet 來管理 head 的內容,那在 my-blog 裡也沒有必要用自訂的 html template 來加上 tailwindcss 的 css 了

下一篇才是 Universal Javascript


上一篇
Day 13: html 樣版與 eta.js
下一篇
Day 15: Universal Javascript
系列文
從 0 開始建一個 Static Site Generator30

尚未有邦友留言

立即登入留言