Next.js@9.2 がリリースされたのでこの blog へ適応して要点などまとめておきました。

表題の通り、Next.js 9.2 がリリースされました。

Next.js 9.2

変更点は主に下記のようです。

Global Stylesheet のサポート

これまでは CSS の import をする場合は @zeit/next-css を利用する必要がありましたが、標準でサポートしてくるようになりました。

共通の CSS は pages/_app.js にて下記のように import すれば build 時に共通 asset として吐き出してくれます。

// pages/_app.js
import '../styles.css'

コンポーネントレベルでの CSS Module のサポート

[name].module.css という名前で生成した CSS ファイルを import することで、CSS Modules を実現できる。

// src/components/Links/index.module.css
.ul {
  display: flex;
  justify-content: center;
}
.li {
  display: inline-block;
  margin-right: 15px;
}
// src/components/Links/index.js
import Link from "next/link";
import styles from "./index.module.css";
export default () => {
  return (
    <div>
      <ul className={styles.ul}>
        <li className={styles.li}>
          <Link href="/">
            <a>top</a>
          </Link>
        </li>
        <li className={styles.li}>
          <Link href="/about">
            <a>about me</a>
          </Link>
        </li>
        <li className={styles.li}>
          <Link href="/blog">
            <a>posts</a>
          </Link>
        </li>
      </ul>
    </div>
  );
};

module scope の CSS はスプリットされ、<link preload as="style" として別々にロードされる。

FP を速くするためにページごとに最小限の CSS がロードされるようにしてくれている。

Network

Element

もちろん、unique な class 名が付与されるので、styled-component と同じ理屈で普遍的な名前をつけてしまっても名前空間のコンフリクトの心配はない。

Code-Spliting 戦略の改善

9.2 以前では TTI までに必要な bundle がいくつか存在していたが、この読み込みがあまり賢いものではなかった。

その module が各 page で 50% 以上使用されていれば common.js へブチ込むし、未満なら page 固有へ割り当てたりみたいな感じだったらしい。

この辺りが Chrome チームのサポートとかを受けながらかなり改善したらしい。

開発者として知っておかないといけないかというとそうでもない知識に分類されるので、「code-spliting がマシになったのね」くらいの認識でいいと思う。

気になった人は blog を詳しく読もう。

一応 build の差分を載っけておく。

9.17 の build

> next build

Creating an optimized production build

Compiled successfully.

Automatically optimizing pages

Page                                                                        Size
┌ ○ /                                                                       402 B
├ ○ /about                                                                  446 B
├ ● /blog                                                                   488 B
└ ● /blog/2020/write-notes-until-develop-with-Next.js-and-depploy-with-now  604 B
+ shared by all                                                             71.6 kB
  ├ chunks/commons.js                                                       66 kB
  ├ runtime/main.js                                                         4.88 kB
  └ runtime/webpack.js                                                      746 B

λ  (Lambda)  server-side renders at runtime (uses getInitialProps or getServerProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

9.2 の build

> next build

Creating an optimized production build

Compiled successfully.

Automatically optimizing pages

Page                                                                        Size     First Load
┌ ○ /                                                                       412 B       73.6 kB
├   /_app                                                                   269 B       54.9 kB
├ ○ /about                                                                  453 B       73.7 kB
├ ● /blog                                                                   495 B       73.7 kB
└ ● /blog/2020/write-notes-until-develop-with-Next.js-and-depploy-with-now  611 B       73.8 kB
+ shared by all                                                             54.9 kB
  ├ static/_buildManifest.js                                                294 B
  ├ static/pages/_app.js                                                    269 B
  ├ chunks/commons.888ebf.js                                                8.59 kB
  ├ chunks/framework.94bc9f.js                                              40.5 kB
  ├ runtime/main.6d7d62.js                                                  4.59 kB
  └ runtime/webpack.b65cab.js                                               746 B

λ  (Lambda)  server-side renders at runtime (uses getInitialProps or getServerProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)

First Load というカラムが増えているよう。

これはおそらく TTI までに必要な load size の目安ということだと思う。

ワイルドカード的なダイナミックルート

/pages/[slug].js という形で、Next.js でもダイナミックルートを扱えるようになったのだが、ワイルドカード的な使い方は用意されていなかった。

それが 9.2 からは [...name] という構文を使用して、ワイルドカード的なダイナミックルート(公式はキャッチオールダイナミックルートと呼んでいる)を利用できるようになった。

例えば、pages/post/[...slug].js は /post/a、/post/a/b、/post/a/b/c をキャッチできるようになる、というような感じ。

軽く検証してみると、query とかはこんな感じになるらしい。

// src/pages/post/[...slug].js
function App() {}
App.getInitialProps = function({ query }) {
  console.log(query);
  return {};
};
export default App;

この状態で /post/dep1/dep2/dep3 へアクセスすると log には下記のように出ていた。ヒエラルキーの降順で配列で渡されるよう。

{ slug: [ 'dep1', 'dep2', 'dep3' ] }