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

2018年9月19日水曜日

Next.js 7

投稿者

26回のカナリアリリースと340万回のダウンロードを経て、本番環境対応のNext.js 7を発表できることを誇りに思います。このバージョンには以下の機能が含まれています。

最後に、全面刷新されたNextjs.orgでこのニュースを共有できることを嬉しく思います。

DXの改善

Next.jsの主な目標の1つは、**可能な限り最高の開発者体験**で最高のプロダクションパフォーマンスを提供することです。このリリースでは、ビルドおよびデバッグパイプラインに多くの大幅な改善がもたらされました。

コンパイル速度

webpack 4、Babel 7、およびコードベースでの多くの改善と最適化のおかげで、Next.jsは開発中に最大57%速く起動するようになりました。

新しいインクリメンタルコンパイルキャッシュのおかげで、コードの変更が40%速くビルドされるようになりました。

これらは、収集したいくつかの例です。

6.07.0差分
起動時間(基本的なアプリケーション)1947ms835ms57% 高速化
コード変更(基本的なアプリケーション)304ms178ms42% 高速化

ボーナスとして、開発およびビルド時に、webpackbarにより、リアルタイムフィードバックが向上しました。

React Error Overlayによるエラーレポートの強化

正確で役立つエラーのレンダリングは、優れた開発およびデバッグ体験にとって重要です。これまで、エラーメッセージとそのスタックトレースをレンダリングしていました。今後は、react-error-overlayを利用してスタックトレースを強化します。

  • サーバーとクライアントのエラーに対する正確なエラーロケーション
  • コンテキストを提供するためのソースのハイライト
  • 完全でリッチなスタックトレース

これは、エラーの「以前」と「以後」の比較です。

The previous overlay left, react-error-overlay right
左は以前のオーバーレイ、右はreact-error-overlayです。

ボーナスとして、react-error-overlayを使用すると、特定のコードブロックをクリックするだけでテキストエディタを開くことができます。

Webpack 4

Next.jsは、最初のリリースから、コードのバンドルと豊富なプラグインおよび拡張機能のエコシステムの再利用のためにwebpackによって動作してきました。Next.jsが最新のwebpack 4によって動作するようになったことを発表できることを嬉しく思います。webpack 4には、数多くの改善とバグ修正が含まれています。

その中で、以下の機能が得られます。

  • .mjsソースファイルサポート
  • コード分割の改善
  • ツリーシェイキング(未使用コードの削除)サポートの強化

もう1つの新機能はWebAssemblyサポートです。Next.jsはWebAssemblyをサーバーレンダリングすることもできます。以下はです。

注意: このアップグレードは完全に後方互換性があります。ただし、next.config.jsを介してカスタムwebpackローダーまたはプラグインを使用している場合は、それらをアップグレードする必要があるかもしれません。

CSSインポート

webpack 4では、バンドルからCSSを抽出するための新しい方法であるmini-extract-css-pluginが導入されました。

@zeit/next-css@zeit/next-less@zeit/next-sass、および@zeit/next-stylusmini-extract-css-pluginによって動作するようになりました。

これらのNext.jsプラグインの新しいバージョンは、CSSインポートに関連する20個の既存の問題を解決しました。例えば、動的import()でのCSSのインポートがサポートされるようになりました。

components/my-dynamic-component.js
import './my-dynamic-component.css';
 
export default function MyDynamicComponent() {
  return <h1>My dynamic component</h1>;
}
pages/index.js
import dynamic from 'next/dynamic'
 
const MyDynamicComponent = dynamic(import('../components/my-dynamic-component'))
 
export default function Index() {
  return () {
    <div>
      <MyDynamicComponent/>
    </div>
  }
}

大きな改善点として、pages/_document.jsに以下を追加する必要がなくなりました。

<link rel="stylesheet" href="/_next/static/style.css" />

代わりに、Next.jsはCSSファイルを自動的に挿入します。本番環境では、Next.jsはCSS URLにコンテンツハッシュを自動的に追加するため、変更があった場合でも、エンドユーザーが古いバージョンのファイルを取得してしまうことを防ぎ、不変の永続的なキャッシュを導入できます。

要するに、Next.jsプロジェクトで.cssファイルをインポートするために必要なことは、next.config.jswithCSSプラグインを登録するだけです。

const withCSS = require('@zeit/next-css');
module.exports = withCSS({
  /* my next config */
});

標準化された動的インポート

Next.jsは、バージョン3からnext/dynamicによる動的インポートをサポートしています。

この技術の早期導入者として、import()を処理するための独自のソリューションを記述する必要がありました。

その結果、Next.jsはwebpackが後から導入したサポートから乖離し始め、一部の機能が不足していました。

このため、Next.jsはwebpackが導入したいくつかのimport()機能をサポートしていませんでした。

例えば、特定のファイルの命名やバンドルをマニュアルで行うことはできませんでした。

import(/* webpackChunkName: 'my-chunk' */ '../lib/my-library');

別の例として、next/dynamicモジュールにラップされていないimport()の使用が挙げられます。

Next.js 7以降、デフォルトのimport()の動作には一切干渉しません。これは、import()の全機能がすぐに利用できることを意味します。

この変更は後方互換性も完全に保たれています。動的コンポーネントの使用は、これまでと同じくらい簡単です。

pages/index.js
import dynamic from 'next/dynamic';
 
const MyComponent = dynamic(import('../components/my-component'));
 
export default function Index() {
  return (
    <div>
      <MyComponent />
    </div>
  );
}

この例は、my-componentの新しいJavaScriptファイルを作成し、<MyComponent />がレンダリングされたときにのみロードします。

最も重要なのは、レンダリングされない場合、<script>タグは初期HTMLドキュメントペイロードに含まれないことです。

コードベースをさらに簡素化し、優れたReactエコシステムを活用するために、Next.js 7ではnext/dynamicが(いくつかのマイナーな変更を加えて)バックグラウンドでreact-loadableを利用するように書き直されました。これにより、動的コンポーネントのために2つの優れた新機能が導入されました。

  • next/dynamictimeoutオプションを使用したタイムアウト
  • next/dynamicdelayオプションを使用したローディングコンポーネントの遅延。この遅延により、インポートが非常に速い場合などに、ローディングコンポーネントがローディング状態をレンダリングする前にx時間待機できます。

Babel 7

Next.js 6は、Babel 7がベータ版であった頃に導入しました。それ以来、Babel 7の安定版がリリースされ、Next.js 7はこのバージョンを使用しています。

変更点の全リストについては、Babelのリリースノートを参照してください。

主な機能の一部は次のとおりです。

  • TypeScriptサポート:Next.jsでは、@zeit/next-typescriptを使用できます。
  • フラグメント構文<>サポート
  • babel.config.jsサポート
  • overridesプロパティ:プリセット/プラグインをファイルまたはディレクトリのサブセットにのみ適用する

Next.jsプロジェクトにカスタムBabel設定がない場合、破壊的な変更はありません。

カスタムBabel設定がある場合は、関連するカスタムプラグイン/プリセットを最新バージョンにアップグレードする必要があります。

Next.js 6より前のバージョンからアップグレードする場合、優れたbabel-upgradeツールを実行できます。

Babel 7へのアップグレードに加えて、Next.js Babelプリセット(next/babel)は、NODE_ENVtestに設定されている場合、デフォルトでmodulesオプションをcommonjsに設定するようになりました。

この設定オプションは、Next.jsプロジェクトでカスタム.babelrcを作成する唯一の理由であることがよくありました。

.babelrc
{
  "env": {
    "development": {
      "presets": ["next/babel"]
    },
    "production": {
      "presets": ["next/babel"]
    },
    "test": {
      "presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]]
    }
  }
}

Next.js 7では、これは次のようになります。

.babelrc
{
  "presets": ["next/babel"]
}

この時点で、.babelrcは削除できます。Next.jsは、Babel設定がない場合にnext/babelを自動的に使用します。

初期HTMLペイロードの削減

Next.jsはHTMLをプリレンダリングするため、ページを<html><head><body>、およびページをレンダリングするために必要なJavaScriptファイルを含むデフォルト構造にラップします。

この初期ペイロードは以前は約1.62kBでした。Next.js 7では初期HTMLペイロードを最適化し、現在は1.5kBで7.4%削減されており、ページがより軽量になりました。

6.07.0差分
ドキュメントサイズ(サーバーレンダリング)1.62kb1.50kb7.4% 小型化

サイズを削減した主な方法は次のとおりです。

  • __next-error divが削除されました。
  • インラインスクリプトは最小化されました。将来のリリースでは完全に削除される予定です。
  • 使用されていない__NEXT_DATA__プロパティはコンパイル時に削除されました。例えば、nextExportおよびassetPrefixプロパティなどです。

静的CDNサポート

Next.js 5では、assetPrefixサポートを導入しました。これは、Next.jsが特定の場所、通常はCDNからアセットを自動的にロードする方法です。このオプションは、CDNがプロキシをサポートしている場合にうまく機能します。次のようなURLをリクエストします。

https://cdn.example.com/_next/static/<buildid>/pages/index.js

通常、CDNはファイルがキャッシュされているかどうかを確認し、そうでなければオリジンから直接リクエストします。

アセットのプロキシは、まさにEdge Networkが動作する方法です。

ただし、一部のソリューションでは、ディレクトリをCDNに事前にアップロードする必要があります。これを行う際の問題は、Next.jsのURL構造が.nextフォルダ内のフォルダ構造と一致しなかったことです。例えば、以前の例では

https://cdn.example.com/_next/static/<buildid>/pages/index.js
// mapped to:
.next/page/index.js

Next.js 7では、.nextのディレクトリ構造をURL構造に合わせて変更しました。

https://cdn.example.com/_next/static/<buildid>/pages/index.js
// mapped to:
.next/static/<buildid>/pages/index.js

プロキシ型のCDNの使用をお勧めしますが、この新しい構造により、別のタイプのCDNのユーザーは.nextディレクトリをCDNにアップロードできます。

Styled JSX v3

Next.jsにデフォルトで含まれているCSS-in-JSソリューションであるstyled-jsx 3が、React Suspenseに対応できるようになったことを嬉しく思います。

しばしば不明瞭だったのは、コンポーネントスコープの一部ではない子コンポーネントをスタイルする方法でした。例えば、親コンポーネント内で使用する場合にのみ特定のスタイルが必要な子コンポーネントをインクルードした場合などです。

pages/index.js
const ChildComponent = () => (
  <div>
    <p>some text</p>
  </div>
);
 
export default function Index() {
  return (
    <div>
      <ChildComponent />
      <style jsx>{`
        p {
          color: black;
        }
      `}</style>
    </div>
  );
}

上記のコードはpタグを選択しようとしていますが、これは機能しません。styled-jsxのスタイルは現在のコンポーネントにスコープされており、子コンポーネントに漏れ出さないからです。これを回避する1つの方法は:globalメソッドを使用することでしたが、これはpタグのプレフィックスを削除することで実現できます。しかし、これは新しい問題を引き起こします。それは、スタイルがページ全体に漏れ出すことです。

styled-jsx 3では、この問題は新しいAPIcss.resolveを導入することで解決されました。これは、指定されたstyled-jsx文字列のclassName<style>タグ(stylesプロパティ)を生成します。

pages/index.js
import css from 'styled-jsx/css';
 
const ChildComponent = ({ className }) => (
  <div>
    <p className={className}>some text</p>
  </div>
);
 
const { className, styles } = css.resolve`
  p {
    color: black;
  }
`;
 
export default function Index() {
  return (
    <div>
      <ChildComponent className={className} />
      {styles}
    </div>
  );
}

この新しいAPIにより、カスタムスタイリングを子コンポーネントに透過的に渡すことができます。

これはstyled-jsxのメジャーバージョンアップであるため、styles-jsx/cssを使用している場合、バンドルサイズを改善するための破壊的な変更が1つあります。styled-jsx 2では、外部スタイルの「スコープ付き」バージョンと「グローバル」バージョンを生成していましたが、これは「スコープ付き」バージョンのみが使用されている場合でも「グローバル」バージョンが含まれていました。

styled-jsx 3では、バンドルサイズを最適化するために、グローバルスタイルはcssではなくcss.globalでタグ付けする必要があります。

すべての変更については、リリースノートを参照してください。

AppとPages間のSSRにおけるReact Context

Next.js 7以降、pages/_app.jsとページコンポーネントの間で新しいReact Context APIをサポートするようになりました。

以前は、サーバーサイドでページ間でReact Contextを使用することはできませんでした。その理由は、webpackがrequire.cacheではなく内部モジュールキャッシュを保持していたためです。カスタムwebpackプラグインを作成し、この動作を変更してページ間でモジュールインスタンスを共有するようにしました。

これにより、新しいReact Contextの使用を可能にするだけでなく、ページ間でコードを共有する際のNext.jsのメモリフットプリントを削減できます。

6.07.0差分
メモリ使用量57.5MB48.1MB-16% メモリ削減

nextjs.org

Next.js 7のリリースと合わせて、完全に再設計されたnextjs.orgをローンチします。

ブログ

現在お読みになっているブログ記事は、すでにnextjs.orgの新しいブログセクションの一部です。このブログは、新しいバージョンのお知らせなど、Next.jsに関連するコミュニケーションの新しい拠点となります。

The new nextjs.org
新しいnextjs.org

インスピレーションを得る

Next.jsを使用するアプリの数は増え続けているため、これらの美しいアプリすべてを1つの概要に表示する方法が必要でした。新しい/showcaseページをご覧ください。

Get inspired on nextjs.org/showcase
nextjs.org/showcaseでインスピレーションを得てください。

この新しいショーケースでは、Next.jsで構築された新しいアプリを継続的に追加できます。

ぜひ/showcaseにアクセスしてインスピレーションを得るか、Next.jsを使用しているアプリを送信してください!

コミュニティ

最初のリリース以来、Next.jsはフォーチュン500企業から個人のブログまで、あらゆるものに使用されています。Next.jsの採用の成長を見るのは非常にエキサイティングです。

  • 現在、12,500以上の公開インデックスドメインでNext.jsが使用されています。
  • 500人以上の貢献者が少なくとも1つのコミットを貢献しました。
  • GitHubでは、プロジェクトは29,000回以上スターされています。
  • 最初のリリース以来、2200件近くのプルリクエストが提出されました。

Next.jsコミュニティには約2000人のメンバーがいます。参加しましょう!