JavaScript
TypeScript
vue.js
nuxt.js

Nuxt.js 2.4 に更新するためにやったこと


Nuxt.js 2.4 で変わったこと

公式リリースノートより一部抜粋していきます。

(※スクリーンショットはそれぞれ公式より引用させていただいております。)

image.png

ref: https://github.com/nuxt/nuxt.js/releases/tag/v2.4.0


TypeScriptに対応


  • やったね!! 公式に TypeScript サポートが開始されました

  • 内部的には ts-loaderfork-ts-checker-webpack-plugin が使用されています


  • :warning: Nuxt.js 内部の Webpack は js から優先的に依存を解決しようとするので同名の js と ts が存在する場合は注意


    • 必要な場合は module か config で extendBuild の仕組みを使用して Webpack に設定されている定義順を入れ替えましょう



image


prefetch に対応

ref: https://nuxtjs.org/api/components-nuxt-link


  • nuxt-link を使用している場合、dev.to みたいにページの先読みがされるようになりました。

  • 実装は google/quicklink.js を参考にしたそうです。

  • 意図的に prefetch を無効化するときは nuxt-link に no-prefetch を設定しましょう。

image


Store が HMR に対応


  • Hot Module Replacement に Vuex が対応し、ストアのコードをいじっても初期化されなくなりました

image


Vetur サポートの強化


  • VSCode で Vetur を使用している場合、Nuxt オリジナルの関数やメンバーが補完されるようになりました

image


生成されるBundleの省サイズ化


  • bundle が小さくなることはいいこと!

モード
v2.4以前
v2.4以降
サイズ差

Dist
8.2M
7.2M
-1M / 12%

Dev
281 MB (RSS: 439 MB)
237 MB (RSS: 354 MB)
-44M / 16% (RSS: -85M / 19%)

Start
106 MB (RSS: 169 MB)
71.7 MB (RSS: 137 MB)
-34M / 32% (RSS: -32M / 19%)



その他にもいろいろ!


  • nuxt-link が n-link で使えるようになりました

  • 内部で使用される Webpack のバージョンが新しくなりました

  • プラグインの読み込み時に拡張子ベースで Server Only / Client Only を設定できるようになりました

  • 開発モードでデフォルトのポートが使用中の場合ランダムなポートを変わりに使用するようになりました

この他にもたくさん機能追加、改修がされています

ref: https://github.com/nuxt/nuxt.js/releases/tag/v2.4.0



アップグレードまでの道

担当しているプロジェクトで Nuxt.js v2.4 にするに当たり実施した改修などなどをご紹介します。


前提知識

プロジェクトの構成は下記のようになっています。


  • 使用しているパッケージ


    • TypeScript 3.1.x

    • Nuxt.js v2.3.x

    • Express 4.16.x

    • Vuetify 1.4.x



  • nuxt.config を含む全てのスクリプトを TypeScript で記載


普段どおりのアップデート方法

パッケージ更新を普段の運用に組み込んでいて、下記のように実施しています。

基本的に package-lock.json を一度破棄して、最初から生成し直し依存パッケージをすべて更新しています。

# ロックを解除

rm -rf node_modules package-lock.json

# パッケージを更新できるものはすべて更新
ncu -a

# 型定義ファイルの追加を検知
typesync

# オリャー!!
npm install


Nuxt.js 2.4 にして起こった問題

普段であれば、上記の手順であとは動作チェックと細かい追従対応を行い対応を完了していますが、今回は少し大きめに変更を加える必要がありました。


  • 今まで通っていたビルドが大量にimportエラーを吐いてコケた

  • 今まで問題のなかった箇所でSSRでDOMの不整合が発生するようになった

  • .nuxt/router.js 内部での Unexpected token error


エラーの例


Nuxt.js が出力するファイルで構文エラーが起こった例

image.png

今まで使用できていた画像を参照できなくなった例

image.png



大量に起こったimportエラーについて


原因


  • 正体は単一ファイルコンポーネント(SFC)の style ブロック内部のurl('~/assets/hoge.svg')

  • 画像の読み込みが v2.3 までと微妙に異なる様子...


解決策


  • 【解決策】CSS 内部では ~assets を使いましょう

  • 英語版マニュアルに下記のように記載があります



  • 日本語版マニュアルにもちょっと控えめに書いてありました


    • > css-loader のアップグレードにより、Nuxt v2.0 から CSS のデータ型 では、~assets(スラッシュなし)を使わなければなりません。例:background: url("~assets/banner.svg")




SSRのDOMの不整合


原因


  • 正直良くわかりませんでした。。。

  • SSR の差分検知のロジックに変化があったか、そもそもいままでの書き方が悪かった可能性が高い


  • vue-server-renderer の更新で直るかもしれない(?)

image.png


解決策


  • 【解決策】必要に応じて<no-ssr>を使いましょう

  • DOMの不整合が起きている箇所のうち、差分検知ができている場合は、開発モードの場合のみヒントになる情報が検証ツールで出ています。

  • CSSのセレクタやDOMの構造を頼りに問題箇所を特定して根本的に直すか、工数的に難しい場合などは<no-ssr>を活用しましょう。


.nuxt/router.js の Unexpected token error


原因

これが一番困った...

下記のIssueをにたどり着きどうやら npm のバグによるものらしく、パッケージの依存解決に失敗する場合がある様子。

流れとしては、下記のような感じ


  • Webpack v4.29 が依存している acorn というパッケージが更新された

  • Nuxt.js v2.4 は Webpack v4.29 をに依存している

  • npm のバグにより Webpack と acorn の依存をうまく解決できないのが問題らしいとのこと

この問題は Issue のリストに上げたように Nuxt.js 側でも報告されていて、yarn でパッケージを取得している場合は発症しないことがわかっていました。


解決策


  • 【解決策】acorn 6.0.5 以上をインストールする

公式の案内は下記のように acorn を更新し、 npm dedupe すると良いと案内がありましたが、こちらでは解決しませんでした。

image.png

rm -rf node_modules package-lock.json

npm install
npm update acorn --depth 20
npm dedupe

npm install している途中で、peerDependencies が欠けている警告が出ていたので試しに acorn を明示的にインストールすると問題は解決できました。

image.png

解決したあとで確認すると、同様の解決手法が Nuxt.js の Issue に追記されていました。

ref: https://github.com/nuxt/nuxt.js/issues/4839#issuecomment-458720610



その他対応したところ


PostCSS の設定が配列からオブジェクトが推奨に変更

v2.0 以降で対応の必要があります。

nuxt.config の build.postcss の設定が配列からオブジェクトに変更されており、オブジェクトで宣言するとデフォルトの設定といい感じにマージしてくれます。

一方で配列で定義すると Nuxt.js で設定されている cssnano などの仕組みが上書きされて消えてしまうので注意が必要です。

日本語版マニュアルは配列で設定する方法が乗っているのですが英語版ですと更新されているようでした

image.png


TypeScript の対応方法の追従

module/typescript.js などを用意して、旧来の手法でTypeScriptを使用していた場合は Nuxt.js が持っているTypeScript対応の仕組みと重複するので、必要に応じて削除や調整が必要です。



まとめ

:tada: 「ねんがんの Nuxt.js v2.4 に なったぞ! ▼」


  • ハマりポイントとしては以上のような依存関係のものが大きかったです。

  • 対応策を探す上で、マニュアルやリリースノートを確認することが重要になってきますが、日本語翻訳に頼り切るのではなく、英語のIssueやPRなどの1次情報も目を通していくお気持ちが大切でした。