26回のカナリアリリースと340万ダウンロードを経て、本番環境対応のNext.js 7を発表します。主な新機能は以下の通りです:
- 開発者体験(DX)の向上:57%高速な起動、42%高速な再コンパイル
- react-error-overlayによるより優れたエラー報告
- コンパイルパイプラインのアップグレード:Webpack 4とBabel 7
- 標準化されたダイナミックインポート
- 静的CDNサポート
- 縮小された初期HTMLペイロード
- AppとPages間のSSR対応React Context
さらに、このニュースを全く新しいNextjs.orgでお伝えできることを嬉しく思います。
開発者体験(DX)の向上
Next.jsの主要な目標の1つは、最高の開発者体験と共に最高の本番環境パフォーマンスを提供することです。このリリースでは、ビルドとデバッグパイプラインに多くの重要な改善がもたらされました
コンパイル速度
Webpack 4、Babel 7、およびコードベースへの多くの改善と最適化のおかげで、Next.jsの開発時起動時間が最大57%高速化しました。
新しい増分コンパイルキャッシュにより、コード変更後のビルド時間が40%高速化しています。
以下は収集した実際の計測値の例です:
6.0 | 7.0 | 差分 | |
---|---|---|---|
起動時間(基本アプリケーション) | 1947ms | 835ms | 57% 高速化 |
コード変更時(基本アプリケーション) | 304ms | 178ms | 42% 高速化 |
追加の利点として、開発とビルド時にwebpackbarのおかげでより良いリアルタイムフィードバックが得られるようになりました:
React Error Overlayによる改善されたエラー報告
正確で役立つエラーのレンダリングは、優れた開発とデバッグ体験にとって重要です。これまではエラーメッセージとそのスタックトレースを表示していましたが、今後はreact-error-overlay
を活用して以下の機能を追加します:
- サーバーとクライアントのエラーに対する正確なエラー位置
- コンテキストを提供するためのソースのハイライト
- 完全なリッチスタックトレース
以下は改善前後のエラー表示の比較です:
左が以前のオーバーレイ、右がreact-error-overlay
追加の利点として、react-error-overlay
では特定のコードブロックをクリックするだけでテキストエディタを簡単に開けるようになります。
Webpack 4
最初のリリース以来、Next.jsはコードのバンドリングと豊富なプラグイン・拡張エコシステムの再利用のためにwebpackを利用してきました。Next.jsが最新の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インポートがサポートされました:
import './my-dynamic-component.css';
export default function MyDynamicComponent() {
return <h1>My dynamic component</h1>;
}
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.js
でwithCSSプラグインを登録するだけです:
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()サポートがそのまま利用可能になります。
この変更も完全な後方互換性があります。ダイナミックコンポーネントの利用は以下のように簡単なままです:
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/dynamic
のtimeout
オプションを使用したタイムアウトnext/dynamic
のdelay
オプションを使用したローディングコンポーネントの遅延。この遅延により、例えばインポートが非常に速い場合に、ローディング状態をレンダリングする前に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_ENV
がtest
に設定されている場合、デフォルトでmodules
オプションをcommonjs
に設定するようになりました。
この設定オプションは、Next.jsプロジェクトでカスタム.babelrc
を作成する唯一の理由であることがよくありました:
{
"env": {
"development": {
"presets": ["next/babel"]
},
"production": {
"presets": ["next/babel"]
},
"test": {
"presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]]
}
}
}
Next.js 7では以下のようになります:
{
"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.0 | 7.0 | 差分 | |
---|---|---|---|
ドキュメントサイズ(サーバーレンダリング) | 1.62kb | 1.50kb | 7.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
// マッピング先:
.next/page/index.js
Next.js 7では、.next
のディレクトリ構造をURL構造に合わせて変更しました:
https://cdn.example.com/_next/static/<buildid>/pages/index.js
// マッピング先:
.next/static/<buildid>/pages/index.js
プロキシ型CDNの使用を推奨していますが、この新しい構造により、別のタイプのCDNのユーザーが.next
ディレクトリをCDNにアップロードできるようになります。
Styled JSX v3
styled-jsx 3の導入を嬉しく思います。Next.jsにデフォルトで含まれるCSS-in-JSソリューションがReact Suspenseに対応しました。
よく不明確だったのは、コンポーネントが現在のコンポーネントスコープの一部でない場合(例えば、親コンポーネント内でのみ特定のスタイルが必要な子コンポーネントを含めた場合)に子コンポーネントをスタイルする方法でした:
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
プロパティ)を生成します:
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とPages間のSSR対応React Context
Next.js 7から、pages/_app.js
とページコンポーネント間で新しいReact context APIをサポートします。
以前は、サーバーサイドでページ間でReact contextを使用することはできませんでした。その理由は、webpackがrequire.cacheの代わりに内部モジュールキャッシュを保持していたためです。この動作を変更してページ間でモジュールインスタンスを共有するカスタムwebpackプラグインを作成しました。
これにより、新しいReact contextの使用が可能になるだけでなく、ページ間でコードを共有する際のNext.jsのメモリ使用量も削減されます。
6.0 | 7.0 | 差分 | |
---|---|---|---|
メモリ使用量 | 57.5MB | 48.1MB | -16% メモリ削減 |
nextjs.org
Next.js 7のリリースと共に、完全に再設計されたnextjs.orgをローンチします。
ブログ
現在読んでいるこのブログ投稿は、すでにnextjs.orgの新しいブログセクションの一部です。このブログは、新しいバージョンの発表など、Next.jsに関連するコミュニケーションの新しい拠点となります。
新しいnextjs.org
インスピレーションを得る
Next.jsを使用したアプリケーションの数が増え続ける中、これらの素晴らしいアプリを一覧で表示する方法が必要でした。新しい/showcase
ページをご紹介します:
nextjs.org/showcaseでインスピレーションを得る
この新しいショーケースにより、Next.jsで構築された新しいアプリを継続的に追加できます。
Next.jsを使用したアプリを提出するか、/showcase
を訪れてインスピレーションを得てください!
コミュニティ
Next.jsは最初のリリース以来、フォーチュン500企業から個人ブログまであらゆる場面で使用されてきました。Next.jsの採用が拡大しているのを見て非常に興奮しています。
- 現在、Next.jsを使用している公開インデックス付きドメインは12,500以上あります。
- 500人以上のコントリビューターが少なくとも1つのコミットを行っています。
- GitHubでは、プロジェクトが29,000回以上スターされています。
- 最初のリリース以来、ほぼ2200のプルリクエストが提出されました。
Next.jsコミュニティには約2000人のメンバーがいます。参加しましょう!