🚴‍♂️

Nativescript8移行はWebpack5がよいらしい

2022/06/25に公開

Webpackを4から5にする

環境

Nativescript-vueにてiOSアプリを開発中。

  • Nativescript 8.2.3
  • Node.js 14.17.6
  • npm 6.14.15
  • Xcode 13.4.1

なぜWebpack5にするのか

Nativescript 8.1のリリース情報に、「Webpack 5にするとめっちゃ速なります!」とあるし、Nativescript公式ドキュメントのWebpackの項もすでに「@nativescript/webpack version5.0.0以上について書いてます!」と言っている。これからNativescript 8 関連でググるときに、Webpackのバージョンの差で色々話が食い違ってくる懸念もあるので、早めに対応しておいたほうが良さそうなのだ。

やりかた

インストールとwebpack.config.jsの初期化までは@nativescript/webpack@5.0.0: A new era!に書いてる方法でできると思う。なんとなく一歩ずつやってみたかったので、そういう方は以下をどうぞ。

@nativescript/webpackの最新版をダウンロードする

プロジェクト内のpackage.jsonで、
"@nativescript/webpack": "^5.0.6",
と最新版にバージョンを書き換えたうえで、プロジェクト内のnode-modulesをトラッシュして、npm iして入れ直す。

個人的にはインストールする前に、npm -@nativescript/webpackを見て、今日も元気にみんなにダウンロードされているか、最新バージョンはいくつかを確認すると安心できる。

ここでns run iosとかでrunすると、以下のようにconfigurationエラーが起こる。

No configuration!
Executing webpack failed with exit code 0.

というのも、Webpack 4から5への変更はかなり大きいアップデートみたいで、configurationをしてくれているwebpack.config.js内の内容もガッツリ書き換える必要があるみたい。

webpack.config.jsをWebpack5用に初期化する

Webpackのconfigurationを書き直す。

webpack.config.js
const MODE = 'development' // 書かなくても動くがwarningが出るので、書いといたほうが安心。
  // 'development': 開発用、'production':本番用
const webpack = require('@nativescript/webpack')

module.exports = env => {
  webpack.init(env)
// 追記事項を書いていくところ
  return webpack.resolveConfig()

昔より短くなってスッキリ。

エントリーのパスの書き方が変わるみたいなので、package.jsonも少し書き直す。
"main"のところに、はじめに参照するファイルを指定していると思うが、そこにsrc/を追加する。
例えば

package.json
  "main": "src/main.js",

こんな感じ。

まだtns-core-modulesの記述がある場合、@nativescript/coreへの読み替えを指定する

tns-core-modulesはNativescript 7 で@nativescript/coreに吸収されたのだが、たまにプラグインの中にtns-core-modulesの記述があったりする。そういう場合はWebpack上で、「tns-core-modulesが来たら、@nativescript/coreで読み替えて探してね」という指定ができる。
みんな大好きNativescript-vueの守り神rigor さんに書き方を教わった。

webpack.config.js
  const MODE = 'development' 
+ const { resolve } = require('path')
  const webpack = require('@nativescript/webpack')

  module.exports = env => {
    webpack.init(env)
+    webpack.chainWebpack((config) => {
+      config.resolve.alias.set(
+        'tns-core-modules',
+         '@nativescript/core'
+      )
  return webpack.resolveConfig()

pollyfills関連のモジュールを入れる

Webpack -resolve.fallbackにあるとおり、以下のモジュールが見つからないというエラーが出る場合は、手動で入れないといけない。
ns run iosしながら、Module not found: Error: Can't resolve "○○"というエラーの〇〇の部分を確認しながら、モジュールインストールとwebpack.config.jsの追記をしていけばいいと思う。だるいけど…。

webpack.config.js
  module.exports = env => {
    webpack.init(env)
    webpack.chainWebpack((config) => {
      config.resolve.alias.set(
        'tns-core-modules',
         '@nativescript/core'
      )
+    const fallback = config.resolve.get('fallback')
+    config.resolve.set(
+      'fallback',
+      webpack.Utils.merge(fallback || {}, {
+        http: require.resolve('stream-http'),
+        https: require.resolve('https-browserify'),
+        tty: require.resolve('tty-browserify'),
+        stream: require.resolve('stream-browserify'),
+        os: require.resolve('os-browserify/browser'),
+        zlib: require.resolve('browserify-zlib'),
+        assert: require.resolve('assert/'),
+        util: require.resolve('util/'),
+        url: require.resolve('url/'),
+      })
+    )
  })

まだModule not found: Error: Can't resolve "○○"がでる場合

なにかの弾みでパッケージやプラグインがなくなったり、違うところに移動したりしている可能性があるので、ググって再インストールする。
私は、Module not found: Error: Can't resolve 'rxjs' と出たので、npm i rxjsしたら解消した。

その他(追記)

他にも修正点、追加でwebpack.config.jsに書くべきこと、などあれば、コメントしてもらえると助かります。(勉強になります。)

Discussion