Skip to content
This repository has been archived by the owner on Jun 21, 2018. It is now read-only.

Latest commit

 

History

History
210 lines (161 loc) · 5.21 KB

getting-started.md

File metadata and controls

210 lines (161 loc) · 5.21 KB

Getting started

This guide will help you to correctly configure build and test tools to work with React Native for Web. (Alternatively, you can quickly setup a local project using the starter kits listed in the README.)

It is recommended that your application provide a Promise and Array.from polyfill.

Web packager

Webpack is a popular build tool for web apps. Below is an example of how to configure a build that uses Babel to compile your JavaScript for the web.

Create a web/webpack.config.js file:

// web/webpack.config.js

// 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(__dirname, 'src'),
    path.resolve(__dirname, 'node_modules/react-native-uncompiled')
  ],
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      // This aliases 'react-native' to 'react-native-web' and includes only
      // the modules needed by the app
      plugins: ['react-native-web/babel']
      // The 'react-native' preset is recommended (or use your own .babelrc)
      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 = {
  // ...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('production')
    })
  ],

  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' ]
  }
}

To run in development:

./node_modules/.bin/webpack-dev-server -d --config web/webpack.config.js --inline --hot --colors

To build for production:

./node_modules/.bin/webpack -p --config web/webpack.config.js

Please refer to the Webpack documentation for more information on configuration.

Web entry

Create a index.web.js file (or simply index.js for web-only apps).

Client-side rendering

Rendering using AppRegistry:

// index.web.js

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

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

AppRegistry.runApplication('App', {
  initialProps: {},
  rootTag: document.getElementById('react-app')
});

Rendering within existing web apps is also possible using ReactNative:

import AppHeader from './src/AppHeader';
import React from 'react';
import ReactNative from 'react-native';

ReactNative.render(<AppHeader />, document.getElementById('react-app-header'))

And finally, react-native-web components will also be rendering within a tree produced by calling ReactDOM.render (i.e., an existing web app), but otherwise it is not recommended.

Server-side rendering

Server-side rendering is supported using the AppRegistry:

import App from './src/App';
import ReactDOMServer from 'react-dom/server'
import ReactNative, { AppRegistry } from 'react-native'

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

// prerender the app
const { element, stylesheets } = AppRegistry.getApplication('App', { initialProps });
const initialHTML = ReactDOMServer.renderToString(element);
const initialStyles = stylesheets.map((sheet) => ReactDOMServer.renderToStaticMarkup(sheet)).join('\n');

// construct HTML document
const document = `
<!DOCTYPE html>
<html>
<head>
${initialStyles}
</head>
<body>
${initialHTML}
`

Web-specific code

Minor platform differences can use the Platform module.

import { Platform } from 'react-native';

const styles = StyleSheet.create({
  height: (Platform.OS === 'web') ? 200 : 100,
});

More significant platform differences should use platform-specific files (see the webpack configuration above for resolving *.web.js files):

For example, with the following files in your project:

MyComponent.android.js
MyComponent.ios.js
MyComponent.web.js

And the following import:

import MyComponent from './MyComponent';

React Native will automatically import the correct variant for each specific target platform.

Testing with Jest

Jest also needs to map react-native to react-native-web.

"jest": {
  "moduleNameMapper": {
    "react-native": "<rootDir>/node_modules/react-native-web"
  }
}

Please refer to the Jest documentation for more information.