大亨升級為大大亨 Gatsby 3

蟲探理查
11分鐘風格

Gatsby 3 有一個很重大的改變,有關圖片的語法都改變了。原有的 project 如果升級到 gatsby 3 圖片語法沒有跟著改的話,有可能沒問題、也可能會不能跑了,或出現一些錯誤。因為我的 project 有些奇怪的錯誤,所以我乾脆就把我的 blog 圖片語法做個升級,這就是所謂的有拜有保佑吧,咦?

攝影師:Rodolfo Clix,來源:Pexels
攝影師:Rodolfo Clix,來源:Pixels

plugin 升級

gatsby 2 相片的 plugin 用的是gatsby-image,升級的時候可以先移除,然後改用gatsby-plugin-image,並一併升級相片有關的plugins:

    npm uninstall gatsby-image
    npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-transformer-sharp

原本 gatsby 2 不管靜態或是動態圖檔,都是在檔案開頭匯入import Img from 'gatsby-image'的 Img 這個 component 來設定相片。

gatsby 3 則是改成靜態圖檔匯入import { StaticImage } from "gatsby-plugin-image",動態圖檔匯入import { GatsbyImage } from "gatsby-plugin-image"

優點

為什麼要升級 gatsby 3? gatsby 3為什麼相片要用新語法?我個人覺得新語法有兩個優點:

  1. 原本 gatsby 2 的靜態圖檔都需要透過 garaphQL 提供來源,gatsby 3 新語法用 StaticImage 這個 component 就可以把 url 或是 ralative path 放入 property 中直接使用,確實方便多了。
  2. 原本 gatsby 2 中,動態圖檔不管 graphQL 或是 component 的 property 中都需要設定一些 option,現在只需要在 graphQL 中設定就好了,語法是有簡潔一點啦。

靜態圖檔

升級靜態圖檔,需要注意到以下幾個重點:

  1. 靜態圖檔<StaticImage />不再需要跟graphQL要資料了。
  2. <StaticImage src="trex.png" width={width} heignt={width/2} />這樣的 component,和 html 的<img />用法機乎一樣。
  3. <StaticImage />依然可以享受 gatsby 的 lazy load,自動產生適合大小的圖檔等功能。
  4. 如果遠端檔案變了,不會自動立即更新,rebuild 後才會更新。
  5. gatsby 的 document 裡面,關於 option 的部份,是選 string 的部份,不要選 enum 。
  6. <StaticImage />的 props 不能從別的檔案、function、component 傳來。

我的圖是從 CMS 傳來的,常從 property 傳來傳去,所以所以我其實不太常使用<StaticImage />,比較常使用<GatsbyImage />

動態圖檔

動態圖檔語法改變蠻大的,一個最大的重點是 graphQL 裡面的語法:

    fixed {
        ...GatsbyImageSharpFixed
    }

改成:

    gatsbyImageData(layout: FIXED)

或是:

    gatsbyImageData(
        width: 200
        placeholder: BLURRED
        formats: [AUTO, WEBP, AVIF]
    )

使用 component 的語法變成這樣<GatsbyImage image={data.file.childImageSharp.gatsbyImageData} />

我們可以觀察到,原本 gatsby 2 裡面 component 的 options,都改到 graphQL裡面了,在 gatsby 3 裡面,component 裡不需要設定什麼 property 了。

這裡可以注意一下,gatsby 官方 document 列出來的 option 裡面的值,要用大寫的 enum value,這是給 graphQL 用的,小寫是給 component 的 property 用的。

其它method

getImage()

要用這個 method 的話,可以在檔案開頭匯入import { getImage } from 'gatsby-plugin-image',這個 method 的功能主要是 <GatsbyImage image={data.file.childImageSharp.gatsbyImageData} />裡面的data.file.childImageSharp.gatsbyImageData可以替換成getImage(data.file.childImageSharp)

換成這種語法,其實只是如果 gatsbyImageData 的值是 null 的情況下,getImage()會送出 undefined,而不會讓整個 app 掛掉,其實和childImageSharp?.gatsbyImageData語法意義一樣,不用getImage()語法也沒差。

getSrc()

getImage()很像,主要是不需要用到 gatsby 一些處理相片的功能,只需要直接取得圖片網址,讓類似 SEO 這種 component 可以用,目的也是預防噴 null 出來出錯。

    import { getSrc } from "gatsby-plugin-image"
    const HomePage = ({ data }) => {
        const imagePath = getSrc(data.file)
        return (
            <>
                <SEO imageSrc={imagePath} />
            </>
        )
    }

實例

可以點「原本」和「改成」看原始檔:

原本:

            images {
              fluid {
                ...GatsbyContentfulFluid
              }

改成:

    images {
        gatsbyImageData(
            width: 800
            placeholder: BLURRED
            aspectRatio:1.5
        )
    }

原本:

    <TagCard
        slug={slug.toLowerCase()}
        key={`tag-${slug.toLowerCase()}`}
        iceFireNumber={iceFireNumber}
        postTitle={title}
        publishedDate={publishedDate}
        excerpt={excerpt}
        timeToRead={(timeToRead * 1.5)}
        imageSrc={element.images[0].fluid}
    />

改成:


    const image = getImage(element.images[0]);
    return (
    <TagCard
        slug={slug.toLowerCase()}
        key={`tag-${slug.toLowerCase()}`}
        iceFireNumber={iceFireNumber}
        postTitle={title}
        publishedDate={publishedDate}
        excerpt={excerpt}
        timeToRead={(timeToRead * 1.5)}
        image={image}
    />

原本:

    import Img from 'gatsby-image'

改成:

    import { GatsbyImage } from 'gatsby-plugin-image'

原本:

    <Link to={`/blog/${slug}/`}>
        <Img className="db" fluid={{ ...imageSrc, aspectRatio: 1.5 }} />
    </Link>

改成:

    <Link to={`/blog/${slug}/`}>
        <GatsbyImage className="db" image={image} alt={postTitle} />
    </Link>

怎麼讀 document

詳細升級步驟可以參考官網高品質 document,以上只是我摘錄和補充一些我覺得比較重要的訊息,接下來分享一點這次升級的心得。

做一個 Gatsby 的開發者,不免要常常讀 Gatsby 的 document,事實上 Gatsby 的 document 品質非常好,不說附上實用的範例程式碼,甚至有的地方還附上影片教學。儘管如此,總還是會是覺得讀 gatsby 的 document 很花時間。

我之前讀 document 的方式,就是邊讀邊做,首先把 document 看懂,然後跟著一步一步做,中間會需要跳去別的 document 或是去 google 資料,然後寫程式碼實作,然後再回去看 document 繼續實作,成功做出來了之後,再做筆記。

這樣的流程有一個小小的缺點是,做到一半再回去查 document 的時候我覺得很花時間,原因如下:

  1. document 是英文的,總是比看中文慢。
  2. document 太詳細記載各種情況了,實際上我可能只需要用到 2、3 種情況。
  3. document 的記載邏輯和自己的尋找邏輯不見得一致。

所以這次升級 gatsby 3 我做了一個小小的改變,我先看 document 先不寫 code,直接把我覺得會用到的部份先摘錄做出一份筆記,等於我先做出一份我自己版本的 document,然後等一下開始寫 code 的時候,再照我自己版本的 document 進行。

我發現這樣小小的改變,竟然大大簡省了我看 document 的時間,因為我看得是我自己中文版本的 document,而且裡面只記載了我會用到的 2、3 種狀況,更重要的是這份特製的 document 記載的邏輯就會是我記東西和我搜尋的邏輯,所以我肉搜(肉眼搜尋)起來超快。

這中間會遇到一個小問題,因為讀 document 的時候沒有實做,偶爾會對原本 document 的理解會有錯誤,那並沒有關係,發現這種情況,就修改一下自己版本的 document 就好了,而且最後升級完畢的時候,整理筆記也會快速很多。

這次升級成 gatsby 3,反而這個讀 document 的方法是我最大的收獲。

五月 14, 2021 更新