Reorganize documentation

Close #1092
Close #1095
This commit is contained in:
Nicolas Gallagher
2018-06-05 10:36:54 -07:00
parent b56a737d62
commit c7c1f29016
13 changed files with 510 additions and 459 deletions

View File

@@ -33,6 +33,9 @@ Steps to reproduce:
**Expected behavior**
<!--
REQUIRED: A clear and concise description of what you expected to happen.
Please check that the behaviour is not expected React Native behaviour by
running your test case on iOS or Android using https://snack.expo.io.
-->
**Environment (include versions). Did this work in previous versions?**

217
README.md
View File

@@ -25,7 +25,7 @@ using Node.js.
Who is using React Native in production web apps?
[Twitter](https://mobile.twitter.com), [Major League
Soccer](https://matchcenter.mlssoccer.com),
[Flipkart](https://www.flipkart.com/), Playstation, Uber, [The
[Flipkart](https://www.flipkart.com/), Uber, [The
Times](https://github.com/newsuk/times-components).
Browser support: Chrome, Firefox, Edge, Safari 7+, IE 10+.
@@ -38,34 +38,56 @@ The easiest way to get started is to edit this
anything to try it out.
For installation and configuration details please read the [getting
started](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/getting-started.md)
started](https://github.com/necolas/react-native-web/blob/master/docs/guides/getting-started.md)
guide.
## Documentation
You can find the API documentation [on the website][website-url].
Please refer to the [React Native documentation][react-native-url] for more
design details, and for information about the [Gesture Responder
Please refer to the [React Native documentation][react-native-url] for the
overall API, design details, and information about the [Gesture Responder
system](https://facebook.github.io/react-native/docs/gesture-responder-system.html)
and [animations](https://facebook.github.io/react-native/docs/animations.html).
Some components and APIs are extended with additional features for the web. And
in a few cases, features present for Android or iOS are missing on the web.
These differences are documented [on the website][website-url].
### Guides
* [Getting started](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/getting-started.md)
* [Style](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/style.md)
* [Accessibility](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/accessibility.md)
* [Internationalization](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/internationalization.md)
* [Direct manipulation](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/direct-manipulation.md)
* [Experimental / unstable use](https://github.com/necolas/react-native-web/blob/master/packages/website/guides/advanced.md)
These guides provide a detailed look at using React Native to create accessible
web experiences. Certain web-specific patterns are documented in the "web
recipes" guide.
* [Getting started](https://github.com/necolas/react-native-web/blob/master/docs/guides/getting-started.md)
* [Client-side rendering](https://github.com/necolas/react-native-web/blob/master/docs/guides/client-side-rendering.md)
* [Server-side rendering](https://github.com/necolas/react-native-web/blob/master/docs/guides/server-side-rendering.md)
* [Style](https://github.com/necolas/react-native-web/blob/master/docs/guides/style.md)
* [Accessibility](https://github.com/necolas/react-native-web/blob/master/docs/guides/accessibility.md)
* [Internationalization](https://github.com/necolas/react-native-web/blob/master/docs/guides/internationalization.md)
* [Direct manipulation](https://github.com/necolas/react-native-web/blob/master/docs/guides/direct-manipulation.md)
* [Web recipes](https://github.com/necolas/react-native-web/blob/master/docs/guides/web-recipes.md)
* [Multi-platform apps](https://github.com/necolas/react-native-web/blob/master/docs/guides/multi-platform-apps.md)
* [Experimental / unstable use](https://github.com/necolas/react-native-web/blob/master/docs/guides/advanced.md)
## Integrations
Examples of using React Native for Web with other web tools:
* [Docz](https://github.com/pedronauck/docz/tree/master/examples/react-native-flow)
* [Gatsby](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-react-native-web)
* [Next.js](https://github.com/zeit/next.js/tree/master/examples/with-react-native-web)
* [Phenomic](https://github.com/phenomic/phenomic/tree/master/examples/react-native-web-app)
* [Razzle](https://github.com/jaredpalmer/razzle/tree/master/examples/with-react-native-web)
* [Storybook](https://github.com/necolas/react-native-web/tree/master/packages/website/storybook/.storybook)
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/master/examples/react-native)
## Examples
There are examples [on the website][website-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/website).
And all the [React Native examples][examples-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/examples))
are also available. Here is an example to get you started:
Check out all the [React Native examples][examples-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/examples)).
There are more examples [on the website][website-url] ([source
code](https://github.com/necolas/react-native-web/blob/master/packages/website)).
And here is a simple example to get you started:
```js
import React from 'react';
@@ -96,104 +118,87 @@ You'll notice that there is no reference to `react-dom`; the `App` component is
defined using the platform-agnostic APIs and Components introduced by React
Native. This allows the app to be rendered to web and native platforms.
## Integrations
Examples of using React Native for Web with other web tools:
* [Gatsby](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-react-native-web)
* [Next.js](https://github.com/zeit/next.js/tree/master/examples/with-react-native-web)
* [Phenomic](https://github.com/phenomic/phenomic/tree/master/examples/react-native-web-app)
* [Razzle](https://github.com/jaredpalmer/razzle/tree/master/examples/with-react-native-web)
* [Storybook](https://github.com/necolas/react-native-web/tree/master/packages/website/storybook/.storybook)
* [Styleguidist](https://github.com/styleguidist/react-styleguidist/tree/master/examples/react-native)
Example recipes for web-specific UI patterns:
* [Links](https://codesandbox.io/s/53r88k5opx)
* [Hover styles](https://codesandbox.io/s/o9q8vy70l5)
* [Root element styles](https://codesandbox.io/s/52x1871vjl)
## Compatibility with React Native
React Native v0.55
### Components
| Name | Status | Notes |
| :----------------------- | :------------------ | :---- |
| ActivityIndicator | Available | |
| ART | Available | |
| Button | Available | |
| CheckBox | Available | |
| FlatList | Available | |
| Image | Available (partial) | Missing multiple sources and HTTP headers. |
| ImageBackground | Available | |
| KeyboardAvoidingView | Available (mock) | |
| ListView | Available | |
| Modal | Not started | |
| Picker | Available | |
| RefreshControl | Not started | |
| SafeAreaView | Available | |
| ScrollView | Available (partial) | Missing momentum scroll events. |
| SectionList | Available | |
| Slider | Not started | |
| StatusBar | Mock | |
| SwipeableFlatList | Available | |
| SwipeableListView | Available | |
| Switch | Available | |
| Text | Available (partial) | Missing `onLongPress` support. |
| TextInput | Available (partial) | Missing rich text features and auto-expanding behaviour. |
| Touchable | Available | Includes additional support for mouse and keyboard interactions. |
| TouchableHighlight | Available | |
| TouchableNativeFeedback | Not started | |
| TouchableOpacity | Available | |
| TouchableWithoutFeedback | Available | |
| View | Available | |
| VirtualizedList | Available | |
| WebView | Not started | |
| YellowBox | Mock | |
| Name | Status | Notes |
| :----------------------- | :----- | :---- |
| ActivityIndicator | | |
| ART | | |
| Button | | |
| CheckBox | | |
| FlatList | | |
| Image | | Missing multiple sources ([#515](https://github.com/necolas/react-native-web/issues/515)) and HTTP headers ([#1019](https://github.com/necolas/react-native-web/issues/1019)). |
| ImageBackground | | |
| KeyboardAvoidingView | (✓) | Mock. No equivalent web APIs. |
| ListView | | |
| Modal | ✘ | Not started ([#1020](https://github.com/necolas/react-native-web/issues/1020)). |
| Picker | | |
| RefreshControl | ✘ | Not started ([#1027](https://github.com/necolas/react-native-web/issues/1027)). |
| SafeAreaView | | |
| ScrollView | | Missing momentum scroll events ([#1021](https://github.com/necolas/react-native-web/issues/1021)) and `pagingEnabled` ([#1057](https://github.com/necolas/react-native-web/issues/1057)). |
| SectionList | | |
| Slider | ✘ | Not started ([#1022](https://github.com/necolas/react-native-web/issues/1022)). |
| StatusBar | (✓) | Mock. No equivalent web APIs. |
| SwipeableFlatList | | |
| SwipeableListView | | |
| Switch | | |
| Text | | Missing `onLongPress` ([#1011](https://github.com/necolas/react-native-web/issues/1011)) and `numberOfLines` ([#13](https://github.com/necolas/react-native-web/issues/13)) support. |
| TextInput | ✓ | Missing `onContentSizeChange` ([#793](https://github.com/necolas/react-native-web/issues/793)), rich text features ([#1023](https://github.com/necolas/react-native-web/issues/1023)), and auto-expanding behaviour ([#795](https://github.com/necolas/react-native-web/issues/795)). |
| Touchable | | Includes additional support for mouse and keyboard interactions. |
| TouchableHighlight | | |
| TouchableNativeFeedback | ✘ | Not started ([#1024](https://github.com/necolas/react-native-web/issues/1024)). |
| TouchableOpacity | | |
| TouchableWithoutFeedback | | |
| View | | |
| VirtualizedList | | |
| WebView | ✘ | Not started ([1025](https://github.com/necolas/react-native-web/issues/1025)). |
| YellowBox | (✓) | Mock. No YellowBox functionality. |
### Modules
| Name | Status | Notes |
| :----------------------- | :------------------ | :---- |
| AccessibilityInfo | Mock | No equivalent web APIs. |
| Alert | Not started | |
| Animated | Available | Missing `useNativeDriver` support. |
| AppRegistry | Available | Includes additional support for SSR with `getApplication`. |
| AppState | Available | |
| AsyncStorage | Available | |
| BackHandler | Mock | No equivalent web APIs. |
| CameraRoll | Not started | No equivalent web APIs. |
| Clipboard | Available | |
| ColorPropType | Available | |
| DeviceInfo | Available (partial) | |
| Dimensions | Available | |
| Easing | Available | |
| EdgeInsetsPropType | Available | |
| Geolocation | Available | |
| I18nManager | Available | Includes additional support for runtime switch to RTL. |
| ImageEditor | Not started | No equivalent web APIs. |
| ImageStore | Not started | No equivalent web APIs. |
| InteractionManager | Available (partial) | |
| Keyboard | Mock | |
| LayoutAnimation | Available (partial) | Missing transform to web animation. |
| Linking | Available | |
| NativeEventEmitter | Available | |
| NativeMethodsMixin | Available | |
| NativeModules | Available (partial) | Mocked. Missing ability to load native modules. |
| NetInfo | Available (partial) | Missing functionality to detect extensive connections. |
| PanResponder | Available | |
| PixelRatio | Available | |
| Platform | Available | |
| PointPropType | Available | |
| Settings | Not started | |
| Share | Available | Only available over HTTPS. Read about the [Web Share API](https://wicg.github.io/web-share/). |
| StyleSheet | Available | |
| TextPropTypes | Available | |
| UIManager | Available | |
| Vibration | Available | |
| ViewPropTypes | Available | |
| Name | Status | Notes |
| :----------------------- | :----- | :---- |
| AccessibilityInfo | (✓) | Mock. No equivalent web APIs. |
| Alert | ✘ | Not started ([#1026](https://github.com/necolas/react-native-web/issues/1026)). |
| Animated | | Missing `useNativeDriver` support. |
| AppRegistry | | Includes additional support for server rendering with `getApplication`. |
| AppState | | |
| AsyncStorage | | |
| BackHandler | (✓) | Mock. No equivalent web APIs. |
| CameraRoll | | No equivalent web APIs. |
| Clipboard | | |
| ColorPropType | | |
| DeviceInfo | (✓) | Limited information. |
| Dimensions | | |
| Easing | | |
| EdgeInsetsPropType | | |
| Geolocation | | |
| I18nManager | | Includes additional support for runtime switch to RTL. |
| ImageEditor | | No equivalent web APIs. |
| ImageStore | | No equivalent web APIs. |
| InteractionManager | (✓) | |
| Keyboard | (✓) | Mock. |
| LayoutAnimation | (✓) | Missing translation to web animations. |
| Linking | | |
| NativeEventEmitter | | |
| NativeMethodsMixin | | |
| NativeModules | (✓) | Mocked. Missing ability to load native modules. |
| NetInfo | | Missing functionality to detect expensive connections as there are no equivalent web APIs. |
| PanResponder | | |
| PixelRatio | | |
| Platform | | |
| PointPropType | | |
| Settings | ✘ | No equivalent web APIs. |
| Share | | Only available over HTTPS. Read about the [Web Share API](https://wicg.github.io/web-share/). |
| StyleSheet | | |
| TextPropTypes | | |
| UIManager | | |
| Vibration | | |
| ViewPropTypes | | |
## Contributing

View File

@@ -0,0 +1,42 @@
# Client-side rendering
Render apps using `AppRegistry`:
```js
// 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', {
initialProps: {},
rootTag: document.getElementById('react-app')
});
```
Or render individual components:
```js
import AppHeader from './src/AppHeader';
import React from 'react';
import { render } from 'react-native';
render(<AppHeader />, document.getElementById('react-app-header'))
```
(Components will also be rendered within a tree produced by calling
`ReactDOM.render` (i.e., an existing web app), but
otherwise it is not recommended.)
You might need to adjust the styles of the HTML document's root elements for
your app to fill the viewport.
```html
<html style="height:100%">
<body style="height:100%">
<div id="react-root" style="display:flex;height:100%"></div>
```

View File

@@ -0,0 +1,116 @@
# Getting started
This guide will help you render components and applications with React Native
for Web.
Your application may need to polyfill `Promise`, `Object.assign`, `Array.from`,
and [`ResizeObserver`](https://github.com/que-etc/resize-observer-polyfill) as
necessary for your desired browser support.
If you're not familiar with setting up a new React web project, please follow
the recommendations in the [React documentation](https://reactjs.org/).
## Install
```
yarn add react react-dom react-native-web
```
And if you need to use `ART`:
```
yarn add react-art
```
## Starter kits
Web: [create-react-app](https://github.com/facebookincubator/create-react-app)
includes built-in support for aliasing `react-native-web` to `react-native`.
```
create-react-app my-app
```
Multi-platform: [create-react-native-app](https://github.com/react-community/create-react-native-app)
includes experimental support for Web.
```
create-react-native-app my-app --with-web-support
```
## Configuring a module bundler
If you have a custom setup, you may choose to configure your module bundler to
alias the package to `react-native`.
For example, modify your [webpack](https://github.com/webpack/webpack)
configuration as follows:
```js
// webpack.config.js
module.exports = {
// ...the rest of your config
resolve: {
alias: {
'react-native$': 'react-native-web'
}
}
}
```
Now you can create your components and applications with the React Native API.
## Configuring Babel
If you need to do the aliasing with Babel you can use
[babel-plugin-module-resolver](https://www.npmjs.com/package/babel-plugin-module-resolver)
```
{
"plugins": [
["module-resolver", {
"alias": {
"^react-native$": "react-native-web"
}
}]
]
}
```
## Configuring Jest
[Jest](https://facebook.github.io/jest/) can be configured using the provided
preset. This will map `react-native` to `react-native-web` and provide
appropriate mocks:
```
{
"preset": "react-native-web"
}
```
Please refer to the Jest documentation for more information.
## Configuring Flow
[Flow](https://flow.org) can be configured to understand the aliased module:
```
[options]
module.name_mapper='^react-native$' -> 'react-native-web'
```
You may also need to include a custom libdef
([example](https://gist.github.com/paularmstrong/f60b40d16fc83e1e8e532d483336f9bb))
in your config.
## Other notes
### Safari flexbox performance
Safari prior to version 10.1 can suffer from extremely [poor flexbox
performance](https://bugs.webkit.org/show_bug.cgi?id=150445). The recommended
way to work around this issue (as used on mobile.twitter.com) is to set
`display:block` on Views in your element hierarchy that you know don't need
flexbox layout.

View File

@@ -0,0 +1,154 @@
# Multi-platform applications
## Web-specific code
Minor platform differences can use the `Platform` module.
```js
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 below 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:
```js
import MyComponent from './MyComponent';
```
React Native will automatically import the correct variant for each specific
target platform.
## Web packaging for existing React Native apps
What follows is merely an _example_ of one basic way to package a web app using
[Webpack](https://webpack.js.org) and [Babel](https://babeljs.io/). (You can
also the React Native bundler, [Metro](https://github.com/facebook/metro), to
build web apps.)
Packaging web apps is subtly different to packaging React Native apps and is
complicated by the need to tree-shake and code-split non-trivial apps.
Install webpack-related dependencies, for example:
```
yarn add --dev babel-loader url-loader webpack webpack-cli webpack-dev-server
```
React Native's Babel preset rewrites ES modules to CommonJS modules, preventing
bundlers from automatically performing "tree-shaking" to remove unused modules
from your web app build. To help with this, you can install the following Babel
plugin:
```
yarn install --dev babel-plugin-react-native-web
```
Create a `web/webpack.config.js` file:
```js
// 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,
// The 'react-native' preset is recommended to match React Native's packager
presets: ['react-native'],
// Re-write paths to import only the modules needed by the app
plugins: ['react-native-web']
}
}
};
// 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 = {
entry: [
// load any web API polyfills
// path.resolve(appDirectory, 'polyfills-web.js'),
// your web-specific entry file
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
]
},
resolve: {
// This will only alias the exact import "react-native"
alias: {
'react-native$': 'react-native-web'
},
// 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 from the root of your application:
```
./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.

View File

@@ -0,0 +1,33 @@
# Server-side rendering
Server-side rendering to HTML is supported using `AppRegistry`:
```js
import App from './src/App';
import ReactDOMServer from 'react-dom/server';
import { AppRegistry } from 'react-native-web';
// register the app
AppRegistry.registerComponent('App', () => App);
// prerender the app
const { element, getStyleElement } = AppRegistry.getApplication('App', { initialProps });
// first the element
const html = ReactDOMServer.renderToString(element);
// then the styles (optionally include a nonce if your CSP policy requires it)
const css = ReactDOMServer.renderToStaticMarkup(getStyleElement({ nonce }));
// example HTML document string
const document = `
<!DOCTYPE html>
<html style="height:100%">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${css}
<body style="height:100%; overflow-y:hidden">
<div id="root" style="display:flex; height: 100%">
${html}
</div>
<script nonce="${nonce}" src="${bundlePath}"></script>
`
```

View File

@@ -0,0 +1,51 @@
# Web recipes
Examples of how to implement web patterns with React Native.
#### `html` and `body` styles
The `html` and `body` elements require certain styles to support full-screen
React Native apps, and disable "features" like pull-to-refresh in mobile
browsers. Using the `body` as the root scroll view is [not reliably
supported](https://github.com/necolas/react-native-web/issues/829).
[Example code](https://codesandbox.io/s/52x1871vjl).
#### Hover styles
Relying on the web's native hover styles can result in several unwanted UX
consequences. Hover styles might be displayed during touch interactions and can
remain visually "stuck". Furthermore, there's no way to delay or persist hover
for accessibility purposes. This recipe shows how to apply hover styles that
integrate with the Responder event system (e.g., the `Touchable*` press styles)
and display styles *only* when the mouse is active. It can also be used as the
basis for programmatic hover delays and rendering of components (e.g., hover
cards).
[Example code](https://codesandbox.io/s/o9q8vy70l5)
#### Link styles
Cross-platform link components are straight-forward to create and can be
combined with the hover recipe.
[Example code](https://codesandbox.io/s/53r88k5opx)
<!--
#### Typography
Rather than relying on inhereted global typography styles, React Native allows
you to define components that encapsulate a typographic system. This has the
added benefit of enabling content-specific typography adjustments, e.g.,
different font sizes or weights for different languages.
[Example code]()
#### Responsive font size
[Example code]()
#### SVG icons
[Example code]()
-->

View File

@@ -1,353 +0,0 @@
# Getting started
This guide will help you render components and applications with React Native
for Web.
Your application may need to polyfill `Promise`, `Object.assign`, `Array.from`,
and [`ResizeObserver`](https://github.com/que-etc/resize-observer-polyfill) as
necessary for your desired browser support.
If you're not familiar with setting up a new React web project, please follow
the recommendations in the [React documentation](https://reactjs.org/).
## Install
```
yarn add react react-dom react-native-web
```
And if you need to use `ART`:
```
yarn add react-art
```
## Starter kits
Web: [create-react-app](https://github.com/facebookincubator/create-react-app)
includes built-in support for aliasing `react-native-web` to `react-native`.
```
create-react-app my-app
```
Multi-platform: [create-react-native-app](https://github.com/react-community/create-react-native-app)
includes experimental support for Web.
```
create-react-native-app my-app --with-web-support
```
## Configuring a module bundler
If you have a custom setup, you may choose to configure your module bundler to
alias the package to `react-native`.
For example, modify your [webpack](https://github.com/webpack/webpack)
configuration as follows:
```js
// webpack.config.js
module.exports = {
// ...the rest of your config
resolve: {
alias: {
'react-native$': 'react-native-web'
}
}
}
```
Now you can create your components and applications with the React Native API.
## Configuring babel
If you need to do the aliasing with Babel you can use
[babel-plugin-module-resolver](https://www.npmjs.com/package/babel-plugin-module-resolver)
```
{
"plugins": [
["module-resolver", {
"alias": {
"^react-native$": "react-native-web"
}
}]
]
}
```
## Client-side rendering
Render apps using `AppRegistry`:
```js
// 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', {
initialProps: {},
rootTag: document.getElementById('react-app')
});
```
Or render individual components:
```js
import AppHeader from './src/AppHeader';
import React from 'react';
import { render } from 'react-native';
render(<AppHeader />, document.getElementById('react-app-header'))
```
(Components will also be rendered within a tree produced by calling
`ReactDOM.render` (i.e., an existing web app), but
otherwise it is not recommended.)
You might need to adjust the styles of the HTML document's root elements for
your app to fill the viewport.
```html
<html style="height:100%">
<body style="height:100%">
<div id="react-root" style="display:flex;height:100%"></div>
```
## Server-side rendering
Server-side rendering to HTML is supported using `AppRegistry`:
```js
import App from './src/App';
import ReactDOMServer from 'react-dom/server';
import { AppRegistry } from 'react-native-web';
// register the app
AppRegistry.registerComponent('App', () => App);
// prerender the app
const { element, getStyleElement } = AppRegistry.getApplication('App', { initialProps });
// first the element
const html = ReactDOMServer.renderToString(element);
// then the styles (optionally include a nonce if your CSP policy requires it)
const css = ReactDOMServer.renderToStaticMarkup(getStyleElement({ nonce }));
// example HTML document string
const document = `
<!DOCTYPE html>
<html style="height:100%">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${css}
<body style="height:100%; overflow-y:hidden">
<div id="root" style="display:flex; height: 100%">
${html}
</div>
<script nonce="${nonce}" src="${bundlePath}"></script>
`
```
## Testing with Jest
[Jest](https://facebook.github.io/jest/) can be configured using the provided
preset. This will map `react-native` to `react-native-web` and provide
appropriate mocks:
```
{
"preset": "react-native-web"
}
```
Please refer to the Jest documentation for more information.
## Using Flow
[Flow](https://flow.org) can be configured to understand the aliased module:
```
[options]
module.name_mapper='^react-native$' -> 'react-native-web'
```
You may also need to include a custom libdef
([example](https://gist.github.com/paularmstrong/f60b40d16fc83e1e8e532d483336f9bb))
in your config.
## Multi-platform applications
### Web-specific code
Minor platform differences can use the `Platform` module.
```js
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 below 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:
```js
import MyComponent from './MyComponent';
```
React Native will automatically import the correct variant for each specific
target platform.
## Web packaging for existing React Native apps
What follows is merely an _example_ of one basic way to package a web app using
[Webpack](https://webpack.js.org) and [Babel](https://babeljs.io/). (You can
also the React Native bundler, [Metro](https://github.com/facebook/metro), to
build web apps.)
Packaging web apps is subtly different to packaging React Native apps and is
complicated by the need to tree-shake and code-split non-trivial apps.
Install webpack-related dependencies, for example:
```
yarn add --dev babel-loader url-loader webpack webpack-cli webpack-dev-server
```
React Native's Babel preset rewrites ES modules to CommonJS modules, preventing
bundlers from automatically performing "tree-shaking" to remove unused modules
from your web app build. To help with this, you can install the following Babel
plugin:
```
yarn install --dev babel-plugin-react-native-web
```
Create a `web/webpack.config.js` file:
```js
// 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,
// The 'react-native' preset is recommended to match React Native's packager
presets: ['react-native'],
// Re-write paths to import only the modules needed by the app
plugins: ['react-native-web']
}
}
};
// 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 = {
entry: [
// load any web API polyfills
// path.resolve(appDirectory, 'polyfills-web.js'),
// your web-specific entry file
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
]
},
resolve: {
// This will only alias the exact import "react-native"
alias: {
'react-native$': 'react-native-web'
},
// 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 from the root of your application:
```
./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.
## Other notes
### Safari flexbox performance
Safari prior to version 10.1 can suffer from extremely [poor flexbox
performance](https://bugs.webkit.org/show_bug.cgi?id=150445). The recommended
way to work around this issue (as used on mobile.twitter.com) is to set
`display:block` on Views in your element hierarchy that you know don't need
flexbox layout.
### Platform-specific component props
There are properties that do not work across all platforms. All web-specific
props are annotated with `(web)` in the documentation.