ブログに戻る
2019-04-16 (火)
投稿者: Connor Davis (@connordav_is), JJ Kasper (@_ijjk), Joe Haddad (@timer150), Luis Alvarez (@luis_fades), Tim Neutkens (@timneutkens)
今日は、Next.js で AMP ページを作成できるようになったことをお知らせします。
AMP とは
AMP はレンダリングのオーバーヘッドを最小化し、高速な Web サイトを構築するための規格です。AMP ページは主要な検索エンジンで強化された挙動でインデックスされ、例えば Google のモバイル検索結果に直接読み込まれて稲妻アイコンで示されます。
(例: Next.js の Google 検索結果)
AMP HTML は通常の HTML よりも厳格な仕様で、より確実なパフォーマンスとスケーラビリティを実現するためにいくつかの制約を課します。いくつかの HTML タグは AMP 固有のタグに置き換えられ、対応する HTML タグより良い振る舞いを提供します。例えば amp-img タグは、まだブラウザが srcset をサポートしていない場合でも完全な srcset サポートを提供します。
AMP ページは AMP をサポートする検索エンジンによって自動的に検出されます。これらの検索エンジンは一般に AMP Cache(例: Google や Bing)を実装しており、AMP Cache によって検索結果からページをより速くレンダリングできます。
Next.js における AMP
Next.js ではページ単位で AMP サポートを定義できるようになり、React コンポーネントの力を使って AMP ページを作成できるようになりました。AMP はインクリメンタルに採用できます。Next.js で AMP を有効にする方法は 2 種類あります: Hybrid AMP ページ と AMP-first ページです。
Hybrid AMP ページ
Hybrid AMP ページを使うと、従来のページに対応する AMP バージョンを持つことができ、検索エンジンはモバイル検索結果で AMP バージョンを表示しつつ、既存の(フル)ページも維持できます。これにより、アプリケーションに AMP を導入しつつ、メインのユーザー体験では Next.js のクライアントサイドルーティングなどの機能を活用できます。
Hybrid AMP ページを有効にするには withAmp 関数を使い、hybrid: true オプションを渡します。
pages/index.js
function HomePage () {
return <p>Welcome to AMP + Next.js.</p>;
}
export default withAmp(HomePage, { hybrid: true });
実運用で Hybrid AMP パターンが使われている例として Reddit があります。各スレッドは Google の AMP Cache に保存されており、モバイル Web 全体で高速なユーザー体験を提供しつつ、デスクトップやその後のナビゲーションでは Reddit のフルバージョンを提供しています。
(画像: Reddit が AMP を使って SEO を改善している例、AMP ビューアでの Reddit の画像)
AMP-first ページ
AMP-first ページは、サイトの主要なトラフィックおよび検索エンジンのトラフィックに対して配信されます。AMP-first を採用すると、デスクトップを含むメインサイトに AMP の高速な体験をもたらします。
AMP-first ページを実装するにはページを withAmp でラップします。
pages/index.js
import { withAmp } from 'next/amp';
function HomePage () {
return <p>Welcome to AMP + Next.js.</p>;
}
export default withAmp(HomePage);
Next.js のランタイムが不要な場合、AMP-first ページの採用は開発を高速化する助けになります。AMP-first では、ページを構築するために AMP 互換のコンポーネントのみを使用することが求められます。現在、AMP-first ページは nextjs.org/docs と nextjs.org/blog で本番運用されています。
コンポーネント内で AMP レンダリングを区別する
プロジェクト内の任意の React コンポーネントは useAmp を利用して AMP と非 AMP のレンダリングモードを判別できます。これにより、<img> と <amp-img> のロジックを共有する <Image> コンポーネントを実装できます。
components/image.js
import { useAmp } from 'next/amp';
export function Image({ src, width, height }) {
const isAmp = useAmp();
return isAmp ? (
<amp-img src={src} width={width} height={height} />
) : (
<img src={src} width={width} height={height} />
);
}
pages/index.js
import { withAmp } from 'next/amp';
import { Image } from '../components/image';
function HomePage() {
return (
<>
<p>Hello! Welcome to AMP + Next.js.</p>
<Image src="https://placehold.it/120" width="120" height="120" />
</>
);
}
export default withAmp(HomePage, { hybrid: true });
開発時の自動リロード
開発環境では、hot-module-replacement の代わりに現在見ているページの変更を追跡し、そのページが変更されたときのみページ全体をリロードします。フルリロードを使う理由は、常に AMP ページの最新のサーバーサイドレンダーを表示することを保証するためです。
AMP バリデーション
開発中に有効な AMP ページだけが出力されるよう、amphtml-validator で自動的に検証します。エラーや警告は Next.js を起動したターミナルに表示されます。ページは next export 実行時にも検証され、問題があればターミナルに出力されます。AMP のエラーがあると next export は失敗します(エクスポートされた出力が有効な AMP ではないため)。
Next.js で AMP を学ぶ
Next.js の使い方に加えて、Next.js で AMP を使う方法をまとめた新しいセクションを追加しました: Learn to use AMP with Next.js
または AMP の例から始めるには以下を実行してください:
npx create-next-app