0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js 13以降でViewportをオブジェクトで書く理由

Posted at

はじめに

最近、Next.js 13以降のApp Routerでviewportの設定について調べていたら、まだ従来のmetaタグで書いてた自分に気づいた😅

<!-- 今までやってた方法 -->
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0">

でも実際は、Next.jsではオブジェクトで書く方が推奨されてるらしい。

export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,
  userScalable: false,
}

なんで今までこれを知らなかったんだろう...ということで、調べてみたら納得できる理由があったのでまとめる。

なぜオブジェクト形式が良いのか

1. 型安全性が効く

これは大きい。TypeScriptを使ってる意味がある。

// ✅ TypeScriptで型チェックされる
export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,  // プロパティ名をtypoしたらコンパイルエラー
}

// ❌ 文字列なのでtypoに気づきにくい
content="width=device-width,initial-scale=1.0,maxmium-scale=1.0"
//                                              ↑ 気づかないtypo

実装するときは、実行時エラーよりコンパイル時エラーの方が圧倒的に楽。

2. 設定が読みやすい

一目で何を設定してるかわかる。

// ✅ 何を設定してるか一目瞭然
export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,
  userScalable: false,
  themeColor: '#000000',
}

// ❌ 長い文字列で何設定してるかパッと見わからない
content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,theme-color=#000000"

コードレビューの時も、オブジェクト形式の方が変更点が分かりやすい。

3. メタデータを一箇所で管理できる

Next.jsの設計思想に沿ってる。

// ✅ layout.tsxで一元管理
export const metadata: Metadata = {
  title: "My App",
  description: "...",
  // その他のメタデータ
}

export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
}

// ❌ メタデータが分散
export const metadata: Metadata = { ... }
// + どこか別の場所にviewportのmetaタグ

4. Next.jsの自動最適化が効く

これは知らなかった。Next.jsが裏で色々やってくれてる。

  • 重複排除: 同じメタデータが複数定義されても自動で重複を排除
  • 順序最適化: SEOに最適な順序でHTMLに挿入
  • エラーハンドリング: 不正な値を自動検出

5. フレームワークの規約に従う

これは大事な考え方だと思う。

フレームワークが「こうやって書いてね」と言ってるなら、それに従った方が長期的に保守しやすい。チーム開発でも一貫性が保てる。

実際の書き方

Before(従来の方法)

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="ja">
      <head>
        <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0" />
      </head>
      <body>{children}</body>
    </html>
  )
}

After(推奨される方法)

import type { Metadata, Viewport } from "next"

export const metadata: Metadata = {
  title: "My App",
  description: "...",
}

export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,
  userScalable: false,
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="ja">
      <body>{children}</body>
    </html>
  )
}

スッキリした!

よく使うViewportの設定

// 基本的な設定
export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
}

// iOSでinputフォーカス時のズームを防ぐ
export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,
  userScalable: false,
}

// PWA対応も含める場合
export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 1,
  userScalable: false,
  themeColor: '#000000',
}

まとめ

今まで何も考えずに従来のmetaタグでやってたけど、Next.js 13以降のApp Routerを使うならオブジェクト形式にした方が良いことがわかった。

理由をまとめると:

  • 型安全性: TypeScriptの恩恵を受けられる
  • 可読性: 設定内容が分かりやすい
  • 保守性: 一箇所で管理できる
  • 最適化: Next.jsの自動最適化が効く
  • 一貫性: フレームワークの規約に従える

「フレームワークの規約に従う」というのが一番しっくりきた。


参考: Next.js 13 Viewport API

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?