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

