Next.js 12にしました

公開 ( 更新)履歴 (6)

ファイル構造を修正してたらNext.js 12が出たので導入しました。更新自体はnpm i next@latestだけで問題なく動作しました。以下は追加でやったことの記録です。

next.config.mjsにする #link

ES Modulesで書けるようになったとのことでnext.config.jsをnext.config.mjsにしました。importのところを変えただけでwebpackのLoaderは相変わらずrequireされちゃうので.cjsのままです。

middlewareを使う #link

単純なAPIであればmiddlewareで返せそうだったのでサイトマップとフィードを返すところでやってみました。

これまでの実装 #link

要件は次の通りでした。

  1. サイトマップは/sitemap.xmlで提供する

  2. フィードは/feed.atomで提供する

これはpublicにファイルを置けば簡単なのですが、content-typeには; charset=utf-8をつけたいので以下のようにしました。

  1. /api/sitemapでサイトマップを返し/sitemap.xmlのrewriteをここに向ける

  2. /api/feedフィードを返し/feed.atomのrewriteをここに向ける

当時の実装:/next.config.js, /pages/api

middlewareの実装 #link

content-typeのわがままは要件であるとします。/pages/apiとrewriteを使うのは迂回をしている感じで具合が悪かったのでここをmiddlewareで解消することにしました。

_middleware.ts
  1. import {NextResponse} from 'next/server';
  2. import type {NextRequest} from 'next/server';
  3. export const middleware = (req: NextRequest) => {
  4. const {pathname} = req.nextUrl;
  5. switch (pathname) {
  6. case '/sitemap.xml':
  7. return respondSitemap();
  8. case '/feed.atom':
  9. return respondFeed();
  10. default:
  11. return undefined;
  12. }
  13. };
  14. const respondSitemap = () => new NextResponse(
  15. [...serializeSitemap()].join('\n'),
  16. {
  17. headers: {
  18. 'content-type': 'application/xml; charset=utf-8',
  19. 'cache-control': 'public, max-age=3600',
  20. },
  21. },
  22. );
  23. const respondFeed = () => new NextResponse(
  24. [...serializeFeed()].join('\n'),
  25. {
  26. headers: {
  27. 'content-type': 'application/atom+xml; charset=utf-8',
  28. 'cache-control': 'public, max-age=3600',
  29. },
  30. },
  31. );

これで/pages/apiとrewriteの設定は不要になりました。

コンテンツが静的なのでmiddlewareを活用している感じは薄いですが、例えばJWTの検証を挟むにはちょうどいいですね。