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

react-native-web with react-navigation - error "Module parse failed: Unexpected token" #2339

Closed
1 task done
rdewolff opened this issue Jul 11, 2022 · 5 comments
Closed
1 task done
Labels

Comments

@rdewolff
Copy link

rdewolff commented Jul 11, 2022

Is there an existing issue for this?

  • I have searched the existing issues

Describe the issue

Hi all

Am trying to add react-native-web to an existing react-native project based on Ignite Bowser template. I have tried with many variation of versions, config of webpack, etc.. without success.

Main version and library I am using, see below for full config files.

react-native 0.63.2
react-navigation 5.x
react-native-web 0.18.6
typescript 3.9.7
webpack 5.73.0

Here is my main issue: when running my react native web app, I get the following error message:

$ webpack serve --mode=development --config webpack.config.js
<w> [webpack-dev-server] "hot: true" automatically applies HMR plugin, you don't have to add it manually to your webpack configuration.
<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
<i> [webpack-dev-server] On Your Network (IPv4): http://10.0.1.229:8080/
<i> [webpack-dev-server] On Your Network (IPv6): http://[fe80::1]:8080/
<i> [webpack-dev-server] Content not from webpack is served from '/Users/rdewolff/Projects/meetme/dev/meetme-mobile/public' directory
asset meetme.bundle.js 14.8 MiB [emitted] (name: app)
asset index.html 458 bytes [emitted]
runtime modules 28.1 KiB 16 modules
orphan modules 2.45 KiB [orphan] 9 modules
modules by path ./node_modules/ 9.41 MiB
  javascript modules 9.26 MiB 2805 modules
  json modules 147 KiB 5 modules
modules by path ./app/ 2.09 MiB
  javascript modules 2.02 MiB 215 modules
  json modules 72.2 KiB 3 modules
modules by path ./*.json 8.74 KiB
  ./app.json 50 bytes [built] [code generated]
  ./package.json 8.69 KiB [built] [code generated]
./index.web.js 492 bytes [built] [code generated]
external "react-native" 42 bytes [built] [code generated]
./util.inspect (ignored) 15 bytes [built] [code generated]
ws (ignored) 15 bytes [optional] [built] [code generated]

ERROR in ./node_modules/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js 21:5
Module parse failed: Unexpected token (21:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| const sizesDiffer = require('../../Utilities/differ/sizesDiffer');
|
> type ReturnBoolType = <V>(V) => true;
| type BoolifiedDeprecatedViewStylePropTypes = $ObjMap<
|   typeof DeprecatedViewStylePropTypes,
 @ ./node_modules/react-native-screens/lib/module/native-stack/views/FontProcessor.js 1:229-305
 @ ./node_modules/react-native-screens/lib/module/native-stack/views/HeaderConfig.js 1:436-462
 @ ./node_modules/react-native-screens/lib/module/native-stack/views/NativeStackView.js 1:922-947
 @ ./node_modules/react-native-screens/lib/module/native-stack/index.js 1:553-587
 @ ./app/navigation/root-navigator.web.tsx 1:286-330
 @ ./app/navigation/index.ts 1:76-103
 @ ./app/app.web.tsx 1:555-578
 @ ./index.web.js 1:241-261

ERROR in ./node_modules/react-native/Libraries/ReactNative/AppContainer.js 21:5
Module parse failed: Unexpected token (21:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| const View = require('../Components/View/View');
|
> type Context = {rootTag: number, ...};
|
| type Props = $ReadOnly<{|
 @ ./node_modules/react-native-screens/lib/module/native-stack/views/NativeStackView.js 1:765-823
 @ ./node_modules/react-native-screens/lib/module/native-stack/index.js 1:553-587
 @ ./app/navigation/root-navigator.web.tsx 1:286-330
 @ ./app/navigation/index.ts 1:76-103
 @ ./app/app.web.tsx 1:555-578
 @ ./index.web.js 1:241-261

webpack 5.73.0 compiled with 2 errors in 3830 ms

The problem seems to be very similar to the one described and discussed here : #2052

I tried checking source code from other app like https://github.com/criszz77/luna that have it working but could not find the difference and make it work in my project. It seems to me this is a webpack configuration issue to use react-native-web properly.

The error is located specifically here in react-native-screens:

import ReactNativeStyleAttributes from 'react-native/Libraries/Components/View/ReactNativeStyleAttributes';

How can I fix the babel/webpack config to handle properly react-native-screens that is importing the file? Specifically in an external lib?

I have the following ideas in mind:

  1. Fix the webpack of rnw to work with that use case
  2. Use another lib like react-router-dom for the navigation to not use the package causing problem.
  3. Use eslib ? Seems not very common and not sure I want to take this road.

I'd love to get some ideas or feedback on how to proceed with that error.

Config files

package.json
{
 "name": "meetme",
 "version": "0.0.1",
 "private": true,
 "scripts": {
   "clean": "rm -rf node_modules && yarn cache clean && yarn install && yarn start -- --reset-cache",
   "set-env:dev": "cp app/config/env.dev.js app/config/env.js",
   "set-env:beta": "cp app/config/env.beta.js app/config/env.js",
   "set-env:production": "cp app/config/env.production.js app/config/env.js",
   "build": "rm -rf dist/ && webpack --mode=production --config webpack.config.js",
   "web": "webpack serve --mode=development --config webpack.config.js",
   "dev": "osascript launch-iterm.scpt",
   "android": "react-native run-android",
   "ios": "react-native run-ios",
   "start": "react-native start",
   "test": "jest",
   "lint": "eslint index.js app storybook test --fix --ext .js,.ts,.tsx",
   "test:e2e": "detox test -c ios.sim.debug",
   "build:e2e": "detox build -c ios.sim.debug",
   "ci:test:e2e": "detox test -c ios.sim.release -l verbose --cleanup",
   "ci:build:e2e": "detox build -c ios.sim.release",
   "compile": "tsc --noEmit -p . --pretty",
   "format": "npm-run-all format:*",
   "format:js": "prettier --write '**/*.js'",
   "format:json": "prettier --write '**/*.json'",
   "format:md": "prettier --write '**/*.md'",
   "format:ts": "prettier --write '**/*.ts{,x}'",
   "hack:types-react-navigation": "rimraf node_modules/@types/react-navigation/node_modules/@types",
   "hack:types-react-native": "rimraf node_modules/@types/react-native/node_modules/@types",
   "hack:types-react-test-renderer": "rimraf node_modules/@types/react-test-renderer/node_modules/@types",
   "patch": "patch-package",
   "postinstall": "node ./bin/postInstall",
   "prepare": "npm-run-all patch hack:*",
   "storybook": "start-storybook -p 9001 -c ./storybook",
   "adb": "adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001 && adb reverse tcp:8081 tcp:8081 && adb reverse tcp:3030 tcp:3030",
   "fastlane:ios:beta": "fastlane ios beta",
   "fastlane:ios:production": "fastlane ios production",
   "fastlane:android:beta": "fastlane android beta",
   "fastlane:android:production": "fastlane android production",
   "codepush:android:beta": "fastlane codepush platform:android env:beta",
   "codepush:android:production": "fastlane codepush platform:android env:production",
   "codepush:ios:beta": "fastlane codepush platform:ios env:beta",
   "codepush:ios:production": "fastlane codepush platform:ios env:production",
   "xcode:cleanup": "rm -rf \"~/Library/MobileDevice/Provisioning Profiles/*\" && rm -rf ~/Library/Developer/Xcode/DerivedData/*"
 },
 "dependencies": {
   "@babel/preset-react": "^7.18.6",
   "@eva-design/eva": "^1.4.0",
   "@feathersjs/feathers": "^4.5.2",
   "@feathersjs/socketio-client": "^4.5.2",
   "@formatjs/intl": "^1.4.5",
   "@formatjs/intl-relativetimeformat": "^7.3.6",
   "@meetme/shared": "link:./../meetme-shared",
   "@react-native-community/async-storage": "^1.11.0",
   "@react-native-community/masked-view": "0.1.10",
   "@react-native-community/push-notification-ios": "^1.2.0",
   "@react-navigation/bottom-tabs": "5.11.15",
   "@react-navigation/drawer": "5.12.9",
   "@react-navigation/native": "5.9.8",
   "@react-navigation/native-stack": "5.0.4",
   "@sentry/react-native": "^1.6.2",
   "@sentry/wizard": "^1.1.4",
   "@ui-kitten/components": "^4.4.1",
   "@ui-kitten/eva-icons": "^4.4.1",
   "analytics-react-native": "^1.2.0",
   "apisauce": "1.1.2",
   "i18n-js": "^3.0.11",
   "libphonenumber-js": "^1.7.50",
   "lodash.throttle": "4.1.1",
   "luxon": "^1.23.0",
   "mobx": "^4.15.4",
   "mobx-react-lite": "^1.4.1",
   "mobx-state-tree": "^3.14.1",
   "moment": "2.17.1",
   "qs": "^6.9.6",
   "ramda": "0.27.1",
   "react": "16.13.1",
   "react-hook-form": "^6.14.2",
   "react-native": "0.63.2",
   "react-native-appstate-hook": "^1.0.4",
   "react-native-calendar-events": "^2.1.2",
   "react-native-calendar-strip": "^2.2.1",
   "react-native-calendars": "^1.265.0",
   "react-native-chart-kit": "^6.6.0",
   "react-native-code-push": "^6.2.1",
   "react-native-contacts": "morenoh149/react-native-contacts#e9241d7017842af37af67498d561088e6c9b0342",
   "react-native-date-picker": "^3.2.2",
   "react-native-deep-linking": "^2.2.0",
   "react-native-dropdownalert": "^4.2.1",
   "react-native-gesture-handler": "^1.5.0",
   "react-native-iap": "^4.5.2",
   "react-native-image-picker": "3.6.0",
   "react-native-keychain": "6.1.1",
   "react-native-localize": "^1.0.0",
   "react-native-push-notification": "7.3.1",
   "react-native-reanimated": "^2.2.0",
   "react-native-safe-area-context": "3.4.1",
   "react-native-safe-area-view": "1.1.1",
   "react-native-screens": "^2.18.1",
   "react-native-splash-screen": "3.2.0",
   "react-native-svg": "^12.1.0",
   "react-native-uuid": "^1.4.9",
   "react-native-web": "^0.18.6",
   "react-native-week-view": "^0.16.0",
   "react-query": "^3.8.2",
   "reactotron-mst": "^3.1.4",
   "reactotron-react-js": "^3.3.7",
   "reactotron-react-native": "^5.0.2",
   "socket.io-client": "^2.3.0",
   "tiny-emitter": "^2.1.0",
   "tipsi-stripe": "^9.1.4",
   "validate.js": "0.13.1"
 },
 "devDependencies": {
   "@babel/core": "^7.11.6",
   "@babel/plugin-proposal-decorators": "^7.0.0",
   "@babel/plugin-proposal-optional-catch-binding": "^7.0.0",
   "@babel/runtime": "^7.11.2",
   "@storybook/addon-storyshots": "5.3.19",
   "@storybook/react-native": "5.3.19",
   "@storybook/react-native-server": "5.3.19",
   "@svgr/webpack": "^6.2.1",
   "@types/http-errors": "^1.6.3",
   "@types/i18n-js": "^3.0.3",
   "@types/jest": "^25.2.3",
   "@types/luxon": "^1.22.0",
   "@types/ramda": "0.26.44",
   "@types/react": "16.9.23",
   "@types/react-native": "^0.63.2",
   "@types/react-native-calendars": "^1.20.7",
   "@types/react-native-push-notification": "7.2.0",
   "@types/react-test-renderer": "^16.9.2",
   "@typescript-eslint/eslint-plugin": "^2.27.0",
   "@typescript-eslint/parser": "^2.27.0",
   "babel-jest": "^26.3.0",
   "babel-loader": "^8.2.5",
   "babel-plugin-react-native-web": "^0.18.6",
   "babel-plugin-transform-class-properties": "^6.24.1",
   "detox": "^16.0.0",
   "eslint": "^6.8.0",
   "eslint-config-prettier": "^6.0.0",
   "eslint-config-standard": "^14.1.0",
   "eslint-plugin-import": "^2.15.0",
   "eslint-plugin-node": "^11.0.0",
   "eslint-plugin-promise": "^4.0.1",
   "eslint-plugin-react": "^7.12.4",
   "eslint-plugin-react-hooks": "^4.1.0",
   "eslint-plugin-react-native": "^3.6.0",
   "eslint-plugin-standard": "^4.0.0",
   "html-webpack-plugin": "^5.5.0",
   "ignite-bowser": "5.4.1",
   "jest": "25.5.4",
   "jetifier": "^1.6.2",
   "metro-react-native-babel-preset": "^0.63.0",
   "npm-run-all": "4.1.5",
   "patch-package": "6.2.2",
   "postinstall-prepare": "1.0.1",
   "prettier": "^2.0.4",
   "react-devtools-core": "4.8.2",
   "react-dom": "^16.0.0",
   "react-native-clean-project": "^3.6.3",
   "react-powerplug": "1.0.0",
   "react-test-renderer": "16.13.1",
   "rimraf": "3.0.2",
   "solidarity": "3.0.0",
   "typescript": "3.9.7",
   "url-loader": "^4.1.1",
   "webpack": "^5.73.0",
   "webpack-cli": "^4.10.0",
   "webpack-dev-server": "^4.9.3"
 },
 "jest": {
   "preset": "react-native",
   "setupFiles": [
     "<rootDir>/node_modules/react-native/jest/setup.js",
     "<rootDir>/test/setup.ts"
   ],
   "testPathIgnorePatterns": [
     "/node_modules/",
     "/e2e"
   ],
   "transformIgnorePatterns": [
     "node_modules/(?!(jest-)?react-native|react-native|@react-navigation|@storybook|@react-native-community)"
   ]
 },
 "prettier": {
   "printWidth": 100,
   "semi": false,
   "singleQuote": true,
   "trailingComma": "all"
 },
 "detox": {
   "test-runner": "jest",
   "configurations": {
     "ios.sim.debug": {
       "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/meetme.app",
       "build": "xcodebuild -workspace ios/meetme.xcworkspace -scheme meetme -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -UseModernBuildSystem=NO",
       "type": "ios.simulator",
       "name": "iPhone 8"
     },
     "ios.sim.release": {
       "binaryPath": "ios/build/Build/Products/Release-iphonesimulator/meetme.app",
       "build": "xcodebuild -workspace ios/meetme.xcworkspace -scheme meetme -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -UseModernBuildSystem=NO",
       "type": "ios.simulator",
       "name": "iPhone 8"
     }
   }
 },
 "eslintConfig": {
   "parser": "@typescript-eslint/parser",
   "extends": [
     "prettier",
     "plugin:@typescript-eslint/recommended",
     "plugin:react/recommended",
     "plugin:react-native/all",
     "plugin:react-hooks/recommended",
     "standard"
   ],
   "parserOptions": {
     "ecmaFeatures": {
       "jsx": true
     },
     "project": "./tsconfig.json"
   },
   "plugins": [
     "@typescript-eslint",
     "react",
     "react-native"
   ],
   "settings": {
     "react": {
       "pragma": "React",
       "version": "detect"
     }
   },
   "globals": {
     "__DEV__": false,
     "jasmine": false,
     "beforeAll": false,
     "afterAll": false,
     "beforeEach": false,
     "afterEach": false,
     "test": false,
     "expect": false,
     "describe": false,
     "jest": false,
     "it": false
   },
   "rules": {
     "comma-dangle": 0,
     "no-unused-vars": 0,
     "no-undef": 0,
     "quotes": 0,
     "react/no-unescaped-entities": 0,
     "react/prop-types": "off",
     "react-native/no-raw-text": 0,
     "space-before-function-paren": 0,
     "@typescript-eslint/ban-ts-ignore": 0,
     "@typescript-eslint/indent": 0,
     "@typescript-eslint/explicit-member-accessibility": 0,
     "@typescript-eslint/explicit-function-return-type": 0,
     "@typescript-eslint/member-delimiter-style": 0,
     "@typescript-eslint/no-explicit-any": 0,
     "@typescript-eslint/no-object-literal-type-assertion": 0,
     "@typescript-eslint/no-empty-interface": 0,
     "@typescript-eslint/no-var-requires": 0
   }
 },
 "hyperlayout": {
   "default": [
     [
       [
         "cd ~/Projects/meetme/dev/meetme-mobile && yarn start",
         "cd ~/Projects/meetme/dev/meetme-backend && DEBUG=* yarn dev"
       ],
       "cd ~/Projects/meetme/dev/meetme-backup && docker-compose up -d && cd ../meetme-mobile"
     ]
   ]
 }
}

babel.config.js
module.exports = {
presets: [
  // mobile
  'module:metro-react-native-babel-preset',
  // web
  '@babel/preset-react',
],
env: {
  production: {},
},
plugins: [
  [
    '@babel/plugin-proposal-decorators',
    {
      legacy: true,
    },
  ],
  ['@babel/plugin-proposal-optional-catch-binding'],
],
}
webpack.config.js
/**
 * Webpack is used for the web version.
 * It has been configured based on the info shared by Aryan Goharzad
 * in the following paper:
 * https://arry.medium.com/how-to-add-react-native-web-to-an-existing-react-native-project-eb98c952c12f
 */

const path = require('path')

const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const appDirectory = path.resolve(__dirname)
const { presets } = require(`${appDirectory}/babel.config.js`)

const compileNodeModules = [
  // Add every react-native package that needs compiling
  'react-native-safe-area-context',
  'react-native-safe-area-view',
  'react-native-reanimated',
  'react-native-gesture-handler',
  'react-native-screens',
  'react-native-calendars',
  'react-native-swipe-gestures',

  '@eva-design/eva',
  '@ui-kitten/eva-icons',
  '@ui-kitten/components',
  '@ui-kitten/eva-icons',
  'react-native-svg',
  'react-native-eva-icons',
  'react-native-week-view',
  '@react-navigation/bottom-tabs',
  '@react-navigation/drawer',
  '@react-navigation/native',
  '@react-navigation/native-stack',
  'react-native-calendar-strip',
  'react-native-date-picker',
  'react-native-dropdownalert',
  'react-native-image-picker',
  '@react-native-community/push-notification-ios',
  'react-native-calendar-events',
  'tipsi-stripe',
  'react-native-code-push',
  '@react-native-community/masked-view',
  '@react-native-community/async-storage',
].map((moduleName) => path.resolve(appDirectory, `node_modules/${moduleName}`))

const babelLoaderConfiguration = {
  test: /\.js$|tsx?$/,
  // Add every directory that needs to be compiled by Babel during the build.
  include: [
    path.resolve(__dirname, 'index.web.js'),
    path.resolve(__dirname, 'app/app.web.tsx'),
    path.resolve(__dirname, 'app'),
    ...compileNodeModules,
  ],
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      presets,
      plugins: ['react-native-web'],
    },
  },
}

const svgLoaderConfiguration = {
  test: /\.svg$/,
  use: [
    {
      loader: '@svgr/webpack',
    },
  ],
}

const imageLoaderConfiguration = {
  test: /\.(gif|jpe?g|png)$/,
  use: {
    loader: 'url-loader',
    options: {
      name: '[name].[ext]',
    },
  },
}

module.exports = {
  entry: {
    app: path.join(__dirname, 'index.web.js'),
  },
  output: {
    path: path.resolve(appDirectory, 'dist'),
    publicPath: '/',
    filename: 'meetme.bundle.js',
  },
  externals: {
    'react-native': true,
  },
  resolve: {
    extensions: ['.web.tsx', '.web.ts', '.tsx', '.ts', '.web.js', '.js'],
    alias: {
      'react-native$': 'react-native-web',
    },
  },
  module: {
    rules: [babelLoaderConfiguration, imageLoaderConfiguration, svgLoaderConfiguration],
  },
  // this should be only enabled on web version
  // devtool: 'eval-source-map',
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'index.html'),
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.DefinePlugin({
      // See: https://github.com/necolas/react-native-web/issues/349
      __DEV__: JSON.stringify(true),
    }),
  ],
}

Expected behavior

Expecting the project to start and display the web app properly.

Steps to reproduce

n/a

Test case

n/a

Additional comments

No response

@rdewolff rdewolff added the bug label Jul 11, 2022
@necolas
Copy link
Owner

necolas commented Jul 11, 2022

There are dozens of past issues like this that you should have found in a search. You need to configure the bundler to compile RN dependencies with Babel https://necolas.github.io/react-native-web/docs/multi-platform/#compiling-and-bundling

@necolas necolas closed this as completed Jul 11, 2022
@rdewolff
Copy link
Author

Of course I have tried that and done it, check my config files. It's all in there as far as I can see.
But when using react-navigation and react-native-screens it doesn't work anymore. Isn't there a config item I am missing?

@GoDeepBlue
Copy link

I am running in to the same issue and spent a couple days trying to work through. Was there a fix or work around?

@suzy-thetraveler
Copy link

I'm havinga same issue too.

@Talha-raj
Copy link

I'm havinga same issue too.

you found any solution?

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

No branches or pull requests

5 participants