Using on the Web

Pre-requisites

Make sure that you have followed the getting started guide and have react-native-paper installed and configured before following this guide.

We're going to use react-native-web and webpack to use React Native Paper on the web, so let's install them as well.

To install react-native-web, run:

yarn add react-native-web react-dom react-art

Using CRA (Create React App)

Install react-app-rewired to override webpack configuration:

yarn add --dev react-app-rewired

Configure babel-loader using a new file called config-overrides.js:

module.exports = function override(config, env) {
  config.module.rules.push({
    test: /\.js$/,
    exclude: /node_modules[/\\](?!react-native-paper|react-native-vector-icons|react-native-safe-area-view)/,
    use: {
      loader: "babel-loader",
      options: {
        // Disable reading babel configuration
        babelrc: false,
        configFile: false,

        // The configration for compilation
        presets: [
          ["@babel/preset-env", { useBuiltIns: "usage" }],
          "@babel/preset-react",
          "@babel/preset-flow"
        ],
        plugins: [
          "@babel/plugin-proposal-class-properties",
          "@babel/plugin-proposal-object-rest-spread"
        ]
      }
    }
  });

  return config;
};

Change your script in package.json:

/* package.json */

  "scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test --env=jsdom",
+   "test": "react-app-rewired test --env=jsdom"
}

Custom webpack setup

To install webpack, run:

yarn add --dev webpack webpack-cli webpack-dev-server

If you don't have a webpack config in your project, copy the following to webpack.config.js get started:

const path = require('path');

module.exports = {
  mode: 'development',

  // Path to the entry file, change it according to the path you have
  entry: path.join(__dirname, 'App.js'),

  // Path for the output files
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'app.bundle.js',
  },

  // Enable source map support
  devtool: 'source-map',

  // Loaders and resolver config
  module: {
    rules: [

    ],
  },
  resolve: {

  },

  // Development server config
  devServer: {
    contentBase: [path.join(__dirname, 'public')],
    historyApiFallback: true,
  },
};

Also create a folder named public and add the following file named index.html:

<!doctype html>
<head>
  <meta charSet="utf-8" />
  <meta httpEquiv="X-UA-Compatible" content="IE=edge" />

  <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />

  <title>App</title>

  <style>
    html, body, #root {
      height: 100%;
    }

    #root {
      display: flex;
      flex-direction: column;
    }
  </style>
</head>
<body>
  <div id="root"></div>
  <script src="app.bundle.js"></script>
</body>

Now we're ready to start configuring the project.

Configure webpack

1. Alias react-native to react-native-web

First, we have to tell webpack to use react-native-web instead of react-native. Add the following alias in your webpack config under resolve:

alias: {
  'react-native$': require.resolve('react-native-web'),
}

2. Configure babel-loader

Next, we want to tell babel-loader to compile react-native-paper and react-native-vector-icons. We would also want to disable reading the babel configuration files to prevent any conflicts.

First install the required dependencies:

yarn add --dev babel-loader @babel/preset-env @babel/preset-react @babel/preset-flow @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread

Now, add the following in the module.rules array in your webpack config:

{
  test: /\.js$/,
  exclude: /node_modules[/\\](?!react-native-paper|react-native-vector-icons|react-native-safe-area-view)/,
  use: {
    loader: 'babel-loader',
    options: {
      // Disable reading babel configuration
      babelrc: false,
      configFile: false,

      // The configration for compilation
      presets: [
        ['@babel/preset-env', { useBuiltIns: 'usage' }],
        '@babel/preset-react',
        '@babel/preset-flow',
      ],
      plugins: [
        '@babel/plugin-proposal-class-properties',
        '@babel/plugin-proposal-object-rest-spread'
      ],
    },
  },
},

3. Configure file-loader

To be able to import images and other assets using require, we need to configure file-loader. Let's install it:

yarn add --dev file-loader

To configure it, add the following in the module.rules array in your webpack config:

{
  test: /\.(jpg|png|woff|woff2|eot|ttf|svg)$/,
  loader: 'file-loader',
}

Load the Material icons

If you followed the getting started guide, you should have the following code in your root component:

<PaperProvider>
  <App />
</PaperProvider>

Now we need tweak this section to load the Material icons from the react-native-vector-icons library:

<PaperProvider>
  <React.Fragment>
    {Platform.OS === 'web' ? (
      <style type="text/css">{`
        @font-face {
          font-family: 'MaterialIcons';
          src: url(${require('react-native-vector-icons/Fonts/MaterialIcons.ttf')}) format('truetype');
        }
      `}</style>
    ) : null}
    <App />
  </React.Fragment>
</PaperProvider>

Remember to import Platform from react-native at the top:

import { Platform } from 'react-native';

You can also load these fonts using css-loader if you prefer.

Load the Roboto fonts (optional)

The default theme in React Native Paper uses the Roboto font. You can add them to your project following the instructions on its Google Fonts page.

We're done!

You can run webpack-dev-server to run the webpack server and open your project in the browser. You can add the following script in your package.json under the "scripts" section to make it easier:

"web": "webpack-dev-server --open"

Now you can run yarn web to run the project on web.