大亨升級為大大亨 Gatsby 3


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

攝影師:Rodolfo Clix,來源:Pexels

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 的方法是我最大的收獲。