React NativeをExpo無しで始めて、React Native for Webも動かすまで

Android / iOS共通で、サッとアプリケーションを作りたかったので、React Nativeを始めてみました。
また、PC上でも使いたかったので、Webでも使えるようにReact Native for Webもやってみました。

また、React Native for Webの方は、公式のREADMEやGetting Startedだけを見ても実装できず、困ったのでまとめました。 にあるのが、完成形とだいたい同じものです。


macOS 10.13.2
Node.js 8.9.4

react 16.2.0
react-native 0.52.2
react-native-web 0.3.2

React Nativeをはじめる

"Quick Start"の方ではじめると、Expoが付いてくるようです。
今回は外したかったので、"Building Projects with Native Code"の方からはじめました。


続いて、getting startedに記載の通り、いろいろインストール。

brew install watchman
npm install -g react-native-cli


react-native init ReactNativeSample


cd ReactNativeSample で、 react-native run-ios とすると、シミュレータとターミナルが起動して、サンプルアプリが起動します。

Androidについては、 ANDROID_HOME を環境変数で設定しておき、デバッグ可能な端末を繋いでおけば、iOSと同様にサンプルアプリが起動します。


ディレクトリ直下にある App.js を見ると、表示されているテキストがあります。

React Native for Webをはじめる

その前に、App.js を移動しておく

babelの設定的に、App.jssrc の下に移動しておきます。

mkdir src
mv App.js src

それに伴って、 index.jsimport App from './src/App'; に変えておきます。
react-native run-ios で、以前と同じ表示になることを確認しておきます。

React Native for Webの導入


yarn add react react-dom react-native-web
yarn add --dev babel-plugin-react-native-web

続いて、 Getting startedに従って、いくつかのファイルを作成していきます。

まずは "Client-side rendering" にあるように、 index.web.js を作成します。

import App from './src/App';
import React from 'react';
import { AppRegistry } from 'react-native';

// register the app
AppRegistry.registerComponent('App', () => App);

AppRegistry.runApplication('App', {
  rootTag: document.getElementById('root')

続いて、entry pointが無いので、サンプルを探してきて、 web/public/index.html を下記のようにしました。

<!DOCTYPE html>
    <meta name="viewport" content="width=device-width">
    <div id="root"></div>
    <script src="bundle.web.js"></script>

また、"Getting started"の"Web packaging for existing React Native apps"にあるように、必要なパッケージのインストールを行います。

yarn add --dev babel-loader url-loader webpack webpack-dev-server

そして、 web/webpack.config.js を作成します。

const path = require('path');
const webpack = require('webpack');

const appDirectory = path.resolve(__dirname, '../');

// This is needed for webpack to compile JavaScript.
// Many OSS React Native packages are not compiled to ES5 before being
// published. If you depend on uncompiled packages they may cause webpack build
// errors. To fix this webpack can be configured to compile to the necessary
// `node_module`.
const babelLoaderConfiguration = {
  test: /\.js$/,
  // Add every directory that needs to be compiled by Babel during the build.
  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,
      // Babel configuration (or use .babelrc)
      // This aliases 'react-native' to 'react-native-web' and includes only
      // the modules needed by the app.
      plugins: ['react-native-web'],
      // The 'react-native' preset is recommended to match React Native's packager
      presets: ['react-native']

// This is needed for webpack to import static images in JavaScript files.
const imageLoaderConfiguration = {
  test: /\.(gif|jpe?g|png|svg)$/,
  use: {
    loader: 'url-loader',
    options: {
      name: '[name].[ext]'

module.exports = {
  // your web-specific entry file
  entry: path.resolve(appDirectory, 'index.web.js'),

  // configures where the build ends up
  output: {
    filename: 'bundle.web.js',
    path: path.resolve(appDirectory, 'dist')

  // ...the rest of your config

  module: {
    rules: [babelLoaderConfiguration, imageLoaderConfiguration]

  plugins: [
    // `process.env.NODE_ENV === 'production'` must be `true` for production
    // builds to eliminate development checks and reduce build size. You may
    // wish to include additional optimizations.
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(
        process.env.NODE_ENV || 'development'
      __DEV__: process.env.NODE_ENV === 'production' || true

  resolve: {
    // If you're working on a multi-platform React Native app, web-specific
    // module implementations should be written in files using the extension
    // `.web.js`.
    extensions: ['.web.js', '.js']

その後、 ./node_modules/.bin/webpack-dev-server --content-base web/public/ -d --config ./web/webpack.config.js --inline --hot --colors を実行すると、webpackによるコンパイル、dev serverの起動が完了します。

http://localhost:8080/ にアクセスすることで、アプリと同じような画面の表示ができました。


毎回実行コマンドを打つのがめんどうなので、 package.json にscriptを追加しました。

// ...
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "start:android": "react-native run-android",
    "start:ios": "react-native run-ios",
      "webpack-dev-server --content-base web/public/ -d --config ./web/webpack.config.js --inline --hot --colors",
    "test": "jest"
// ...


yarn start:android
yarn start:ios
yarn start:web
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.