Next.js11で静的HTMLを生成しようとすると next/image や <img> タグに関するエラーが発生した

## 何をしようとしているのか


フロントエンドをNext.js11で開発しています。
最終的には静的HTMLを生成し、Google Cloud Storage (GCS) にホスティングして配信します。

Next.jsによる静的HTMLの生成とGCSによる静的ウェブサイトのホスティングについては以下のサイトを参考に行っています。

- [Advanced Features: 静的HTMLのエクスポート | Next.js](https://nextjs-ja-translation-docs.vercel.app/docs/advanced-features/static-html-export)
- [静的ウェブサイトのホスティング &nbsp;|&nbsp; Cloud Storage &nbsp;|&nbsp; Google Cloud](https://cloud.google.com/storage/docs/hosting-static-website?hl=ja)

## 何があったのか

Next.jsで静的HTMLを生成する際にエラーが発生しました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">`next build && next export` で静的サイトを生成する時にnext/imageを使ってるとエラーになる。でもNext.js11ではimgタグを使うとビルドのときにエラーになる。imgタグ使ってeslintの設定変えるしかないのか？ <a href="https://t.co/c0g45tmpEQ">pic.twitter.com/c0g45tmpEQ</a></p>&mdash; スギヤマトシキ (@llwz886q) <a href="https://twitter.com/llwz886q/status/1431223229201276934?ref_src=twsrc%5Etfw">August 27, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

詳しくは以下のとおりです。

### next/image を使った


サイトにロゴを設置するために、

```tsx:src/components/logo.tsx
import Image from 'next/image'

const Logo = () =>  (
  <Image
    src="/logo.svg"
    alt="logo"
    width={128}
    height={128}
 />
)

export default Logo
```

↑ このようなファイルを作成しました。
ローカル環境では `next dev` を実行しており、問題なくロゴが表示されています。

静的HTMLを生成するために `next build && next export` を実行すると、



![Image Optimization using Next.js' default loader is not compatible with `next export`](https://i.gyazo.com/8c25109c57bd6e9dbf415d80089eb844.png)
↑ [エラー](https://nextjs.org/docs/messages/export-image-api) が発生しました。

確かに [Basic Features: Image Optimization | Next.js](https://nextjs.org/docs/basic-features/image-optimization) には

> The next/image component's default loader is not supported when using next export. However, other loader options will work.

と書かれています。


### img タグを使った

そこで今度は `next/image` ではなく `<img>` タグを使用して、

```tsx:src/components/logo.tsx
const Logo = () =>  (
  <img
    src="/logo.svg"
    alt="logo"
    width="128"
    height="128"
 />
)

export default Logo
```

`logo` コンポーネントを↑このように書き換えました。
再度 `next build && next export` を実行すると、
![Do not use img](https://i.gyazo.com/69822907b53b5e734c20ecf50d33f1e2.png)
[`<img>` タグの代わりに `next/image` を使うように、というエラー](https://nextjs.org/docs/messages/no-img-element) が発生しました。

[Error: Do not use &lt;img&gt;. Use Image from &#39;next/image&#39; instead. - Next.js using html tag &lt;img /&gt; ( with styled components ) - Stack Overflow](https://stackoverflow.com/questions/68203582/error-do-not-use-img-use-image-from-next-image-instead-next-js-using-ht#answer-68224530) によると、

> From Next.js 11, ESLint is supported out-of-the-box and a new set of rules is now provided, including the @next/next/no-img-element rule.

ということで、

```diff_json:.eslintrc
{
  "extends": ["next", "next/core-web-vitals"],
+  "rules": {
+    "@next/next/no-img-element": "off"
+  }
}

```

とすることで `<img>` タグが使えるようになります。

## おわりに
### 静的HTMLを生成する際に `next/image` を使えなくても画像を最適化するにはどうすればよいか？

[Image optimization for static NextJS sites](https://blog.whereisthemouse.com/image-optimization-for-static-nextjs-sites) を参考にして [next-optimized-images](https://github.com/cyrilwanner/next-optimized-images) を使用しました。

```
yarn add next-optimized-images imagemin-svgo
```
↑パッケージをインストールして（svgのみ最適化の対象とする例）、

```diff_jsx:next.config.js
+ const withOptimizedImages = require('next-optimized-images')

- module.exports = {
+ module.exports = withOptimizedImages({
   reactStrictMode: true,
   trailingSlash: true,
+  handleImages: ['svg'],
- }
+ })
```
`next.config.js` を↑このように修正し、`next build && next export` を実行して完成です。

## 参考
- [Advanced Features: 静的HTMLのエクスポート | Next.js](https://nextjs-ja-translation-docs.vercel.app/docs/advanced-features/static-html-export)
- [Basic Features: Image Optimization | Next.js](https://nextjs.org/docs/basic-features/image-optimization)
- [Error: Do not use &lt;img&gt;. Use Image from &#39;next/image&#39; instead. - Next.js using html tag &lt;img /&gt; ( with styled components ) - Stack Overflow](https://stackoverflow.com/questions/68203582/error-do-not-use-img-use-image-from-next-image-instead-next-js-using-ht#answer-68224530)
- [Image optimization for static NextJS sites](https://blog.whereisthemouse.com/image-optimization-for-static-nextjs-sites)
- [静的ウェブサイトのホスティング &nbsp;|&nbsp; Cloud Storage &nbsp;|&nbsp; Google Cloud](https://cloud.google.com/storage/docs/hosting-static-website?hl=ja)