コンテンツへスキップ
ブログに戻る

2020年5月11日(月)

Next.js 9.4

投稿者

本日、Next.js 9.4を発表できることを嬉しく思います。主な機能は以下の通りです。

高速リフレッシュ

高速リフレッシュは、Reactコンポーネントに加えた編集内容に対する即時的なフィードバックを提供する新しいホットリローディングエクスペリエンスです。Next.js 9.4以降のすべてのプロジェクトで、デフォルトで有効になっています。

ホットリローディングは以前から存在していましたが、従来は あまりにも脆弱であったため、ワークフローでデフォルトで有効にすることができませんでした。このため、Next.jsでは以前、アプリケーションの状態全体をリセットする粗雑なホットリローディングを実装していました。

以前のホットリローディングの実装は、コンパイルエラーやランタイムエラーに対して復元力がなく、CSSやJavaScriptの編集中にタイプミスをすると、アプリケーション全体が完全に再読み込みされていました。これは最適ではなく、作業の流れを中断していました。

Fast RefreshはReact自体に深く統合されているため(React Refresh経由)、Next.jsはReactコンポーネントツリーに対して予測可能な精密な更新を実行できます。

つまり、Next.jsは編集したファイル内のコードのみを更新し、そのコンポーネントのみを再レンダリングします。コンポーネントの状態は失われません。これには、スタイル(インライン、CSS-in-JS、またはCSS/Sassモジュール)、マークアップ、イベントハンドラー、およびエフェクト(useEffect経由)が含まれます。

コンパイラエラーとランタイムエラー(迅速な復旧を含む)、そして状態を保持する編集を含む編集セッション。

この機能の一環として、エラーオーバーレイを完全に再設計し、より役立つものにし、アプリケーションをタイプミスやランタイムエラーに対して復元力のあるものにしました。これには、以下が含まれますが、これらに限定されません。

  • 正確なエラー位置(コンパイル前のコードの元の行と列に解決済み)
  • 状況に関連するソースコードのスニペット(エディタでクリックして開く機能付き)
  • 構文エラーを修正した後、アプリケーションの状態を失うことなく開発セッションを再開
  • エラーを修正すると、未処理のランタイムエラーが自動的に無視される

この機能の実装にあたり、Dan Abramov氏から貴重な貢献と支援をいただいたことに感謝いたします。

インクリメンタルスタティックリジェネレーション(ベータ版)

Next.jsは9.3で静的サイト生成(SSG)の方法を導入しました。その明確な目標は、静的サイトの利点(常に高速、常にオンライン、グローバルに分散)を得ることですが、Next.jsで知られている動的データの優れたサポートも備えています。

両方の利点を活かすために、Next.jsはインクリメンタルスタティックジェネレーションをサポートしており、サイトをビルドした後に静的コンテンツを更新します。たとえば、9.3では、getStaticPathsfallback: trueオプションを導入し、ランタイムで新しいページを追加できるようにしました。

最近、Next.jsがこの方法で無限の数のページを静的にプリレンダリングする方法を示す例をまとめました。

本日、インクリメンタルスタティックリジェネレーション(ベータ版)も導入します。これは、トラフィックが流入するにつれてバックグラウンドで既存のページを再レンダリングすることで既存のページを更新するメカニズムです。stale-while-revalidateに触発されたこの機能は、トラフィックが中断されることなく、常に静的に提供され、新しくビルドされたページは生成が完了した後にのみプッシュされることを保証します。

pages/blog/[slug].js
export async function getStaticProps() {
  return {
    props: await getDataFromCMS(),
    // we will attempt to re-generate the page:
    // - when a request comes in
    // - at most once every second
    unstable_revalidate: 1,
  };
}

SSRとは異なり、インクリメンタルスタティックリジェネレーションは、静的サイトの利点を維持することを保証します。

  • レイテンシのスパイクなし。ページは常に高速に提供されます。
  • ページがオフラインになることはありません。バックグラウンドでのページの再生成に失敗した場合、古いページは変更されません。
  • データベースとバックエンドの負荷が低くなります。ページは同時に最大1回再計算されます。

インクリメンタル機能(ページの追加と遅延更新)とプレビューモードは、next startVercelエッジプラットフォームの両方で既に完全にサポートされています。

次は、追加の2つのインクリメンタルスタティックジェネレーション機能に対処するための補足的なRFCに取り組む予定です。

  • 複数のページ(ブログのインデックスや特定のブログ投稿など)の再生成と無効化
  • ユーザーのトラフィックに先立って、イベント(CMS Webhookなど)をリッスンして再生成する

CMSの例

次世代静的サイト生成の発表を受けて、ヘッドレスCMS APIからコンテンツを取得し、Next.js HTMLとしてレンダリングする現実世界のシナリオを共有したいと思います。

世界最高のCMSシステムの一部を作成者と連携しました。ContentfulDatoCMSPrismicSanity、そしてTakeShapeなどです。今後さらに追加される予定です。

これらの例は、使用できるだけでなく、100%オープンソースでMITライセンスを取得しており、利用可能なベストプラクティスを組み込んでいます。

DatoCMS achieves impeccable results due to their built-in image optimization support.
DatoCMSは、ビルトインのイメージ最適化サポートにより、完璧な結果を実現しています。

DatoCMSは、ビルトインのイメージ最適化サポートにより、完璧な結果を実現しています。

また、TinaCMSと協力して、CMSの刺激的な新しい方向性であるコンテンツのページ内編集に取り組んでいます。ガイドをご覧ください。プロジェクトへの実装方法について説明しています。

新しい環境変数サポート

Next.jsを使用している企業から寄せられたフィードバックの共通点は、環境変数がブラウザバンドルにインライン化される場合と、Node.js環境でのみ使用可能な場合が不明瞭であるということです。

本日、このプロセスを合理化する2つの完全に下位互換性のある機能を発表します。

まず、環境変数の前にNEXT_PUBLIC_というプレフィックスを付けることで、環境変数をブラウザに公開できるようになりました。その環境変数が使用されると、ブラウザのJavaScriptバンドルにインライン化されます。

next.config.jsを追加してenvキーを追加してこれらの変数を公開する必要がなくなりました。

pages/index.js
// The environment variable will be exposed to the browser
console.log('My Application Version', process.env.NEXT_PUBLIC_VERSION);
 
export default function HomePage() {
  return <h1>Hello World</h1>;
}

2つ目の変更点は、Next.jsがデフォルトで.envの読み込みをサポートするようになったことです。これにより、開発環境と本番環境の環境変数を簡単に定義できます。

.envの読み込みについて詳しくは、環境変数のドキュメントをご覧ください。

これらの新機能により、以下の規則に従うことで、環境変数の使用が簡素化されます。

  • 環境変数は、デフォルトではNode.js環境でのみ使用できます。
  • NEXT_PUBLIC_で始まる環境変数は、ブラウザに公開されます。

組み込みFetchサポートの改善

Next.js 9.1.7で、ブラウザにおけるfetch() APIのポリフィルを発表しました。今回、このポリフィルはNode.js環境にも拡張されました。

実際には、Next.jsがすべての環境でfetch()を自動的に提供するため、サーバーサイドのfetchポリフィル(例えばisomorphic-unfetchnode-fetchなど)を使用する必要がなくなりました。

例えば、ビルド時にNext.jsによって実行されるgetStaticPropsを使用する場合

pages/blog.js
export async function getStaticProps() {
  // fetch no longer needs to be imported from isomorphic-unfetch
  const res = await fetch('https://.../posts');
  const posts = await res.json();
 
  return {
    props: {
      posts,
    },
  };
}
 
function Blog({ posts }) {
  // Render posts...
}
 
export default Blog;

Web Vitalsレポートの統合

先週、Google ChromeチームがCore Web Vitalsを発表しました。Core Web Vitalsは、Web上で優れたUXを提供するための重要な品質指標であり、有名なLighthouseレポートの基盤となっています。

これらの指標を把握しておくことは、ウェブサイトやWebアプリケーションを可能な限り高速化したい場合(これはNext.jsの中心的な目標の1つです)に非常に役立ちます。

Chromeチームは、開発者がページのパフォーマンスに関する視覚的なフィードバックを得ることができるCore Web Vitals Chrome拡張機能をリリースしました。

本番環境のWebアプリケーションを構築する際には、サイトが訪問者や(潜在的な)顧客にとってどの程度のパフォーマンスを発揮しているかを知ることも重要です。変更が対象のオーディエンスに意図した影響を与えているかどうかを確認するために、これらの指標の改善や悪化を時間とともに追跡したい場合もあるでしょう。

アナリティクスサービスへのCore Web Vitalsのレポート作成を支援するために、Googleとの共同でpages/_app.jsからエクスポートできるreportWebVitalsという新しいメソッドを導入しました。

pages/_app.js
// Will be called once for every metric that has to be reported.
export function reportWebVitals(metric) {
  // These metrics can be sent to any analytics service
  console.log(metric);
}
 
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}
 
export default MyApp;

このメソッドをアナリティクスサービスと組み合わせて使用するには、ドキュメントの「アナリティクスへの結果の送信」セクションを参照してください。Core Web Vitalsについてさらに詳しく知りたい場合は、web.dev/vitalsを参照してください。

絶対インポートとエイリアス

大規模なプロジェクトに取り組んでいる場合、一部のimport文が../../../スパゲティに悩まされることがあります。

import Button from '../../../../components/button';

このような場合、相対インポートではなく、**絶対インポート**を使用することをお勧めします。componentsディレクトリがルートにあると仮定すると、import文は次のようになります。

import Button from 'components/button';

Next.js 9.4では、JavaScriptとTypeScriptの両方のプロジェクトで絶対インポートの設定が非常に簡単になりましたことをお知らせします。必要なのは、jsconfig.json(JSプロジェクト)またはtsconfig.json(TSプロジェクト)baseUrl設定を追加することだけです。

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "."
  }
}

これにより、.(ルートディレクトリ)からの絶対インポートが可能になります。また、VSCodeなどのエディターと統合され、コードナビゲーションなどのエディター機能がサポートされます。

注記: 以前、絶対インポートを有効にするためにWebpackモジュールエイリアス設定を変更したことがある場合は、その設定を削除できます。

さらに、Next.js 9.4はpathsオプションもサポートしており、カスタムモジュールエイリアスを作成できます。例えば、以下のようにすることで、components/design-systemの代わりに@/design-systemを使用できます。

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/design-system/*": ["components/design-system/*"]
    }
  }
}

エイリアスは次のように使用できます。

// Imports 'components/design-system/button'
import Button from '@/design-system/button';

pathsを指定する場合は、baseUrlを指定する必要があります。pathsオプションの詳細については、TypeScriptのドキュメントを参照してください。

Sassサポートの設定

Next.js 9.3で組み込みSassサポートが開始された際、一部のユーザーからSassコンパイラの設定(例えばincludePathsの設定)をしたいというフィードバックがありました。

next.config.jssassOptionsキーを使用することで、これが可能になりました。

next.config.js
const path = require('path');
 
module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
};

ログ出力の改善

コマンドライン出力をより一貫性のあるものにするために再設計し、デプロイメントURL、開発サーバーの起動待ちなど、重複したデータの出力量を減らしました。また、メッセージタイプのスペースを統一することで、行間が不規則にずれることがなくなりました。

9.4より前のバージョンでnext devを実行する場合

9.4でnext devを実行する場合

コミュニティ

Next.jsの採用拡大を大変嬉しく思っています。

  • 1066名を超える独立した貢献者にご参加いただきました。
  • GitHubでは、このプロジェクトは48,000回以上スターされています。

GitHub DiscussionsでNext.jsコミュニティに参加しませんか。Discussionsは、他のNext.jsユーザーとつながり、質問をすることができるコミュニティスペースです。

Next.jsを使用している場合は、プロジェクトのURLをコミュニティで共有してください。

コミュニティの皆様、そしてこのリリースの形成に貢献してくれた外部からのフィードバックと貢献に感謝いたします。