2021.04.08
React Native とFlutter におけるWeb アプリ開発
こんにちは。次世代システム研究室のT.M です。
はじめに
React Native やFlutter はクロスプラットフォームのアプリケーションフレームワークとして有名です。クロスプラットフォームのフレームワークとしてどちらが良いかを判断するために、前回の記事では、React Native とFlutter のandroid アプリにおけるパフォーマンス比較を行いました。そもそも、クロスプラットフォームは、android とiOS だけでなく、Web やWindows / MacOS を指す言葉です。そこで、本稿ではWeb アプリケーションの開発について比較を行います。
React Native
React Native では、標準ではandroid / iOS アプリの開発しか行うことができません。同一ソースコードでのWeb アプリを開発するためには、React Native for Web を利用する必要があります。
React Native for Web では、以下のライブラリが必要です。
npm install react-dom react-native-web
また、React Native のコードをWeb 用のコードにトランスパイルする必要があります。今回はwebpack を利用します。
npm install --save-dev babel-loader url-loader webpack webpack-cli babel-plugin-react-native-web
Web アプリのためには、index.html が必要です。web というディレクトリを用意して、そこに配置します。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello, world!</title> </head> <body> <div id="root"></div> <script src="bundle.web.js"></script> </body> </html>
android / iOS アプリには、index.js が必要であり、そこでルートとなるApp コンポーネントの登録をします。Web アプリでは、同様にApp コンポーネントの登録が必要ですが、それだけではなく、index.html のroot エレメントにそのコンポーネントを紐づける必要があります。この紐付けは、Web のみに必要なものなので、Web だけで処理をするindex.web.js を作成します。
import React from 'react'; import { AppRegistry, StyleSheet, Text, View } from 'react-native'; import App from './src/App' AppRegistry.registerComponent('App', () => App); AppRegistry.runApplication('App', { rootTag: document.getElementById('root') });
アプリケーションのソースコードの変更は以上になります。残りは、webpack などのツールを利用して、トランスパイルを行い、Web アプリ対応をしていきます。
webpack のconfig である、以下のようなwebpack.config.js をweb/ に配置します。
const path = require('path'); const webpack = require('webpack'); const appDirectory = path.resolve(__dirname, '../'); const babelLoaderConfiguration = { test: /\.js$/, include: [ path.resolve(appDirectory, 'index.web.js'), path.resolve(appDirectory, 'src'), path.resolve(appDirectory, 'node_modules/react-native-uncompiled') ], use: { loader: 'babel-loader', options: { cacheDirectory: true, presets: ['module:metro-react-native-babel-preset'], plugins: ['react-native-web'] } } }; const imageLoaderConfiguration = { test: /\.(gif|jpe?g|png|svg)$/, use: { loader: 'url-loader', options: { name: '[name].[ext]' } } }; module.exports = { entry: [ path.resolve(appDirectory, 'index.web.js') ], output: { filename: 'bundle.web.js', path: path.resolve(appDirectory, 'web') }, module: { rules: [ babelLoaderConfiguration, imageLoaderConfiguration ] }, resolve: { alias: { 'react-native$': 'react-native-web' }, extensions: [ '.web.js', '.js' ] } }
babel のreact-native-web のプラグインを呼び出し、react-native のimport 文をreact-native-web に書き換える、ということをしています。
上記設定にしたがって、bundle.web.js を作成します。
./node_modules/.bin/webpack --config web/webpack.config.js
Flutter
Flutter では、標準でandroid / iOS アプリだけではなく、Web アプリの開発をすることができます。Web アプリは安定版ではなかったのですが、先日のFlutter2 のバージョンアップで安定版となりました。
Flutter でのWeb アプリの作成のためには、特別な設定などは不要です。
flutter build web
上記コマンドで、main.dart が作成されるので、web/index.html を呼び出せば、Web アプリが実行されます。
Flutter のWeb アプリでは、html レンダラーとcanvaskit レンダラーがあります。html レンダラーはデータサイズが小さいが、パフォーマンスが低い、という問題があります。反対に、canvaskit レンダラーはパフォーマンスが高いが、データサイズが大きい、という問題があります。デフォルトでは、PC の場合、canvaskit レンダラーを、モバイルの場合、html レンダラーを選択するようになっています。
PC でもhtml レンダラーを指定したい場合は、以下のコマンドでビルドをすることができます。
flutter build web --web-renderer html
また、モバイルでcanvaskit レンダラーを指定したい場合、以下のコマンドでビルドをすることができます。
flutter build web --web-renderer canvaskit
各ビルドでは、以下のような通信が行われます。canvaskit レンダラーの時だけ、2.5MB のcanvaskit.wasm というファイルをダウンロードしていることがわかります。
まとめ
React Native およびFlutter のWeb アプリケーションに関する比較を行いました。Flutter の方が圧倒的に容易にWeb アプリケーションの開発をすることができました。android / iOS だけではなく、Web も一つのコードで開発を行うのならば、Flutter の方が良いと考えます。
React Native はandroid / iOS のためだけのフレームワークであり、Flutter はクロスプラットフォームのアプリ開発のためのフレームワークとして、進んでいることを実感しました。今後の開発にとても期待しています。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD