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

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デルタ
起動時間(基本アプリケーション)1947ミリ秒835ミリ秒57% 高速化
コード変更(基本アプリケーション)304ミリ秒178ミリ秒42% 高速化

おまけとして、開発およびビルド時に、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では、mini-extract-css-pluginと呼ばれる、バンドルからCSSを抽出する新しい方法が導入されました。

@zeit/next-css@zeit/next-less@zeit/next-sass、および@zeit/next-stylusは、mini-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');

もう1つの例は、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ドキュメントのペイロードに含まれないということです。

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

  • next/dynamictimeoutオプションを使用したタイムアウト
  • next/dynamicdelayオプションを使用したローディングコンポーネントの遅延。この遅延により、インポートが非常に速い場合など、ローディング状態をレンダリングする前に、loadingコンポーネントが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"]
}

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

より小さな初期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__プロパティ(たとえば、nextExportassetPrefixプロパティ)が使用されていない場合は、コンパイルされません。

静的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に対応できます。

不明確なことが多かったことの1つは、子コンポーネントが現在のコンポーネントスコープの一部でない場合に、その子コンポーネントをスタイルする方法です。たとえば、親コンポーネント内で使用されている場合にのみ特定のスタイルが必要な子コンポーネントを含めた場合

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では、この問題は、新しいAPIであるcss.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でタグ付けする必要があります。これにより、styled-jsxはバンドルサイズを最適化できます。

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

Appとページ間での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の採用が拡大していることに非常に興奮しています。

  • 現在、Next.jsを使用している公開インデックス付きドメインは12,500以上あります。
  • 少なくとも1回のコミットを成功させたコントリビューターは500人以上います。
  • GitHubでは、プロジェクトは29,000回以上スターされています。
  • 最初のリリース以来、約2200件のプルリクエストが送信されました。

Next.jsコミュニティには2000人近くのメンバーがいます。ぜひご参加ください!