Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Other packages can't resolve DeviceInfo and ViewPagerAndroid any more #801

Closed
raarts opened this issue Feb 7, 2018 · 9 comments
Closed

Comments

@raarts
Copy link

raarts commented Feb 7, 2018

I guess this is a bug. (but what do I know)

What is the current behavior?

ERROR in ./node_modules/react-navigation/lib-rn/views/SafeAreaView.js
Module not found: Error: Can't resolve 'react-native-web/dist/exports/DeviceInfo' in '/Users/raarts/work/app/node_modules/react-navigation/lib-rn/views'
 @ ./node_modules/react-navigation/lib-rn/views/SafeAreaView.js 1:1307-1358
 @ ./node_modules/react-navigation/lib-rn/react-navigation.js
 @ ./src/App.js
 @ ./src/index.js
 @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/index.js

ERROR in ./node_modules/react-native-tab-view/src/TabViewPagerAndroid.js
Module not found: Error: Can't resolve 'react-native-web/dist/exports/ViewPagerAndroid' in '/Users/raarts/work/app/node_modules/react-native-tab-view/src'
 @ ./node_modules/react-native-tab-view/src/TabViewPagerAndroid.js 1:1046-1103
 @ ./node_modules/react-native-tab-view/src/index.js
 @ ./node_modules/react-navigation/lib-rn/views/TabView/TabView.js
 @ ./node_modules/react-navigation/lib-rn/react-navigation.js
 @ ./src/App.js
 @ ./src/index.js
 @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/index.js

If the current behavior is a bug, please provide the steps to reproduce and
if a minimal demo of the problem via Glitch or similar (template:
https://glitch.com/edit/#!/react-native-web-playground).

If this is really neceswsary I can provide it, but me-thinks the maintainers will immediately know what's happening here.

What is the expected behavior?

No errors.

Environment (include versions). Did this work in previous versions?

It worked in 0.3.0-rc.4

  • OS: OSX
  • Device: n/a
  • Browser: n/a
  • React Native for Web (version): 0.4.0
  • React (version): 16.2.0

Here's my package.json:

{
  "name": "app",
  "version": "0.1.0",
  "main": "node_modules/expo/AppEntry.js",
  "private": true,
  "dependencies": {
    "css-loader": "^0.28.9",
    "expo": "^25.0.0",
    "hoist-non-react-statics": "^2.3.1",
    "i18next": "^10.2.2",
    "jest-expo": "^25.0.0",
    "jwt-decode": "^2.2.0",
    "prop-types": "^15.6.0",
    "qs": "^6.5.1",
    "query-string": "^5.0.1",
    "react": "16.2.0",
    "react-dom": "16.0.0",
    "react-i18next": "^7.3.0",
    "react-native": "https://github.com/expo/react-native/archive/sdk-25.0.0.tar.gz",
    "react-native-dotenv": "^0.1.1",
    "react-native-dropdownalert": "^3.2.0",
    "react-native-extended-stylesheet": "^0.8.0",
    "react-native-login-keycloak": "^1.0.2",
    "react-native-web": "^0.4.0",
    "react-navigation": "^1.0.0-beta.27",
    "react-redux": "^5.0.6",
    "react-scripts": "1.0.17",
    "reactotron-react-js": "^1.13.0",
    "reactotron-react-native": "^1.14.0",
    "redux": "^3.7.2",
    "redux-persist": "^5.5.0",
    "url-parse": "^1.2.0",
    "uuid": "^3.2.1"
  },
  "scripts": {
    "start": "sed -i -e 's:lib/react-navigation.web.js:lib-rn/react-navigation.js:g' ./node_modules/react-navigation/package.json; ./node_modules/.bin/webpack-dev-server -d --config ./webpack.config.js  --inline --hot --colors --content-base public/",
    "build": "sed -i -e 's:lib/react-navigation.web.js:lib-rn/react-navigation.js:g' ./node_modules/react-navigation/package.json; NODE_ENV=production ./node_modules/.bin/webpack -p --config ./webpack.config.js",
    "test": "node node_modules/jest/bin/jest.js --watch",
    "eject": "react-scripts eject",
    "lint": "eslint --ignore-path .gitignore .",
    "lint:fix": "eslint . --ignore-path .gitignore --fix",
    "prettier": "prettier --write '*.js'",
    "format-code": "yarn run prettier && yarn run lint:fix",
    "precommit": "lint-staged"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "lint-staged": {
    "*.js": [
      "yarn run format-code",
      "git add"
    ]
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-react-native-web": "^0.4.0",
    "eslint": "^4.15.0",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-plugin-import": "^2.8.0",
    "eslint-plugin-jsx-a11y": "^6.0.3",
    "eslint-plugin-react": "^7.5.1",
    "husky": "^0.14.3",
    "lint-staged": "^6.0.0",
    "prettier": "1.9.2",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.11.1"
  }
}

and my webpack config:

// 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, 'src'),
    path.resolve(appDirectory, 'node_modules/react-native-vector-icons'),
    path.resolve(appDirectory, 'node_modules/react-navigation'),
    path.resolve(appDirectory, 'node_modules/react-native-tab-view'),
    path.resolve(appDirectory, 'node_modules/react-clone-referenced-element'),
    path.resolve(appDirectory, 'node_modules/react-native-extended-stylesheet'),
    path.resolve(appDirectory, 'node_modules/react-native-dropdownalert'),
    path.resolve(appDirectory, 'node_modules/reactotron-react-native'),
  ],
  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', 'transform-runtime'],
      // 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]',
    },
  },
};

// This is needed for loading css
const cssLoaderConfiguration = {
  test: /\.css$/,
  use: ['style-loader', 'css-loader'],
};

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

  // configures where the build ends up
  output: {
    filename: 'bundle.js',
    publicPath: '/assets/',
    path: path.resolve(appDirectory, './public/assets'),
  },

  module: {
    rules: [
      babelLoaderConfiguration,
      cssLoaderConfiguration,
      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'],
    alias: {
      'react-native': 'react-native-web',
    },
  },
};

.babelrc

{
  "presets": ["babel-preset-expo", "react-native-dotenv"],
  "env": {
    "development": {
      "plugins": ["transform-react-jsx-source"]
    }
  }
}
@jainpiyush19
Copy link

+1

@necolas
Copy link
Owner

necolas commented Feb 7, 2018

Those modules are not supported on web. You shouldn't expect platform specific code or every RN package to run on web

@necolas necolas closed this as completed Feb 7, 2018
@jainpiyush19
Copy link

Got that. But how to avoid these errors ?

@raarts
Copy link
Author

raarts commented Feb 7, 2018

@necolas For StatusBar a stub is provided, will you accept a PR to do the same for DeviceInfo and ViewPagerAndroid?

@necolas
Copy link
Owner

necolas commented Feb 7, 2018

You can avoid these errors by not bundling those packages in your web app. React Navigation has no web support.

@necolas
Copy link
Owner

necolas commented Feb 7, 2018

RNW doesn't stub any iOS/Android-only components. DeviceInfo is an undocumented native module, so no plans to stub that either right now

@raarts
Copy link
Author

raarts commented Feb 7, 2018

React Navigation was in a sorry state (even though it was the recommended router for RN), and I complained about it there. Many people did. Thankfully some people took that to heart, and the situation has improved tremendously. Because of that they did not make react-native-web support a priority for 1.0. But they stated that they do intend to add it later. And it works reasonably well for now.

I can follow you on using private props, and I will create a PR for react-native-dropdownalert, but this is making it really hard for people like me, who want to share codebases between app and web.

@necolas
Copy link
Owner

necolas commented Feb 7, 2018

The problem lies in packages that assume only iOS/Android exists. You should avoid them or only import them in *.native.js files

@raarts
Copy link
Author

raarts commented Feb 9, 2018

I'd like your advice on something. react-native-dropdownalert accepted my PR to fallback to sane defaults if the _defaultProps isn't found on StatusBar. So that's ok.

But now I want to use React Navigation 1.0.0. They use react-native-tab-view, which is: "A cross-platform Tab View component for React Native.". Now, that package provides a TabViewPagerAndroid component, which is obviously Android only, and they use the React Native ViewPagerAndroid to implement that, by importing it as follows:

(/react-native-tab-view/src/TabViewPagerAndroid.js)

import { View, ViewPagerAndroid, StyleSheet, I18nManager } from 'react-native';

Which throws the error: Can't resolve 'react-native-web/dist/exports/ViewPagerAndroid'.

Now what would be the best way to fix this? react-native is aliased to react-native-web, import statements cannot be wrapped in a condition. Do I create a PR for react-native-tab-view, which creates a directory - say - compat which contains two files (ViewPagerAndroid.js and ViewPagerAndroid.web.js) where the second file returns a null object?

This ties into your remark that "The problem lies in packages that assume only iOS/Android exists". The thing is, this package imports from react-native which contains a stub for ViewPagerAndroid when run on ios. So the ios and android parts do contain stubs for each other.

Now I don't think they will continue providing platform specific components, wouldn't it just be simpler to have react-native-web also provide stubs for those platform-specific components and be done with it?

If not, can you help me in learning wat is the best way of moving forward with this? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants