nx-react-native icon indicating copy to clipboard operation
nx-react-native copied to clipboard

React-native aliases with nextjs plugin

Open tocalvo opened this issue 4 years ago • 7 comments

Hi 👋 ! I try to use react-native components in a nextjs app inside an nx monorepo. But throws an import error.

This a demo repo with the problem (aliases-native branch) -> https://github.com/tocalvo/react-monorepo-cache/tree/aliases-native

If you try to launch the nx serve next-example command, the builds go fine, but on render throw:

event - compiled successfully
/Users/tom/repos/tocalvo/react-monorepo-cache/node_modules/react-native/index.js:13
import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Module._compile (internal/modules/cjs/loader.js:891:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
    at Module.require (/Users/tom/repos/tocalvo/react-monorepo-cache/node_modules/@nrwl/tao/src/compat/compat.js:5:36)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/Users/tom/repos/tocalvo/react-monorepo-cache/node_modules/styled-components/native/dist/styled-components.native.cjs.js:6243:19)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
    at Module.require (/Users/tom/repos/tocalvo/react-monorepo-cache/node_modules/@nrwl/tao/src/compat/compat.js:5:36)
    at require (internal/modules/cjs/helpers.js:74:18)
    at eval (webpack-internal:///styled-components/native:1:18)
/Users/tom/repos/tocalvo/react-monorepo-cache/node_modules/react-native/index.js:13
import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo';
^^^^^^

I try to add the babel plugin (both, "react-native" and the "module-resolver" with an alias) In the nextjs .babelrc file and in the lib .babelrc file

.babelrc
{
  "presets": ["next/babel"],
  "plugins": [
    ["styled-components", { "pure": true, "ssr": true }],
    ["react-native-web", { "commonjs": true }],
    [ "module-resolver",
      {
        "alias": {
          "react-native": "react-native-web"
        }
      }
    ]
  ]
}

The webpack config with aliases on next.config.js

const withNx = require('@nrwl/next/plugins/with-nx');

module.exports = withNx({
  webpack: (config) => {

    config.resolve = {
      ...config.resolve,
      alias: {
        ...config.resolve.alias,
        'react-native$': 'react-native-web'
      },
    }
    return config
  }
});

in the react-native-web guide talks about the module-alias, so i add them to the next.config.js:

const moduleAlias = require("module-alias");
moduleAlias.addAliases({
  "react-native": require.resolve("react-native-web"),
});
moduleAlias();

and works, but just in the nx server command, with nx build next-example fails with the same error. I try to add the module-alias on a custom nextjs server.js file, but the same result, not working on the build command.

Nextjs should take aliases from tsconfig, so, i try to add the aliases on the tsconfig.json (plus the aliases for libs):

{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "jsx": "preserve",
    "allowJs": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "types": ["node", "jest"],
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
     "paths": {
       "react-native": ["react-native-web"],
       "@react-monorepo-cache/theme-lib": ["libs/theme-lib/src/index.ts"],
       "@react-monorepo-cache/ui": ["libs/ui/src/index.ts"],
       "@react-monorepo-cache/ui-styled": ["libs/ui-styled/src/index.ts"],
       "@react-monorepo-cache/native-shared-components": [
         "libs/native-shared-components/src/index.ts"
       ]
     }
  },
  "include": ["**/*.ts", "**/*.tsx", "next-env.d.ts"],
  "exclude": ["node_modules"]
}

But still not working :( Is possible that alises on nextjs are override by the nx nextjs plugin or something similar?

Any help would be greatly appreciated😃

tocalvo avatar Feb 04 '21 13:02 tocalvo

@tocalvo Maybe the extensions need to be added to next.config.js as well?

https://github.com/vercel/next.js/blob/master/examples/with-react-native-web/next.config.js

I'll test it out on my machine as well, AFAIK there shouldn't be anything different in the Nx setup compared to plain Next.js app.

jaysoo avatar Feb 10 '21 16:02 jaysoo

Hi! Thanks for give it a try 😄 i try with the extensions and fails too , the only thing i found to work is adding

const moduleAlias = require("module-alias");
moduleAlias.addAliases({
  "react-native": require.resolve("react-native-web"),
});
moduleAlias();

inside the node_module/next/dist/build/utils.js file, inside "isPageStatic" function. But is really weird, its like nextjs is ignoring aliases from tsconfig on build time. Should take aliases from tsconfig, and i was afraid that maybe some config in Typescript config in nx is overwriting it. (because nx uses alias on packages and libs)

tocalvo avatar Feb 13 '21 14:02 tocalvo

Hello, this is still an issue @tocalvo. Have you find a way to get this done?

teovillanueva avatar Apr 23 '21 17:04 teovillanueva

Hi, i think yes, is still an issue (but im not so sure if is a nx bug, nextjs bug, nx-nextjs plugin, or the react-native nx plugin bug 😅). I just make a little fix adding the aliases on the nextjs build file. But its not really a clean solution 😪 , the good solution will be a clear way to send the aliases to the nextjs build process. I just add the aliases on the "node_module/next/dist/build/utils.js" file to finish the build. You can try it, just add the aliases you need after the "const mod=await require(serverBundle);"

Captura de pantalla 2021-04-23 a las 8 03 30

And try the build again.

tocalvo avatar Apr 23 '21 18:04 tocalvo

Any update on this?

zRelux avatar May 15 '21 21:05 zRelux

Hi I am able to make Next JS working with React Native Web.

  1. you have to change your .babelrc config to this
{
  "presets": ["@nrwl/next/babel"],
  "plugins": [["react-native-web", { "commonjs": true }]]
}

don't forget to install babel-plugin-react-native-web

also, you need to change your next.config.js to match this:

// eslint-disable-next-line @typescript-eslint/no-var-requires
const withNx = require('@nrwl/next/plugins/with-nx');

module.exports = withNx({
  nx: {
    // Set this to false if you do not want to use SVGR
    // See: https://github.com/gregberge/svgr
    svgr: true,
  },
  webpack(config) {
    config.resolve.alias = {
      ...(config.resolve.alias || {}),
      // Transform all direct `react-native` imports to `react-native-web`
      'react-native$': 'react-native-web',
    };
    config.resolve.extensions = [
      '.web.js',
      '.web.ts',
      '.web.tsx',
      ...config.resolve.extensions,
    ]
    return config;
  },
});

Now you can run the project. However, jest is still failed. Still find a way to solve it. Hope it helps

broerjuang avatar Jun 19 '21 19:06 broerjuang

Still new to next js and to nx.. I am trying to implement navigations to react native web project.. I am getting the following error:

`ERROR in /Users/omairsyed/dev/acme/node_modules/react-native/index.js 14:7 Module parse failed: Unexpected token (14:7) 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 | | // Components

import typeof AccessibilityInfo from './Libraries/Components/AccessibilityInfo/AccessibilityInfo'; | import typeof ActivityIndicator from './Libraries/Components/ActivityIndicator/ActivityIndicator'; | import typeof Button from './Libraries/Components/Button';`

Here is my code:

`import * as React from 'react'; import { View, Text } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack';

const linking = { prefixes: ['https://localhost'], config: { screens: { Main: { screens: { Home: '/Main/Home', Details: '/Main/Details' } }, MyModal: '/MyModal' }, } }

function HomeScreen() { const linkTo = useLinkTo();

return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text style={{ fontSize: 30 }}>This is the home screen!</Text> <Button onPress={() => linkTo('/MyModal')} title="Open Modal" /> </View> ); }

function DetailsScreen() { return ( <View> <Text>Details</Text> </View> ); }

function ModalScreen() { const linkTo = useLinkTo();

return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text style={{ fontSize: 30 }}>This is a modal!</Text> <Button onPress={() => linkTo('/Main/Home')} title="Dismiss" /> </View> ); }

const MainStack = createStackNavigator(); const RootStack = createStackNavigator();

function MainStackScreen() { return ( <MainStack.Navigator> <MainStack.Screen name="Home" component={HomeScreen} /> <MainStack.Screen name="Details" component={DetailsScreen} /> </MainStack.Navigator> ); }

function RootStackScreen() { return ( <RootStack.Navigator mode="modal"> <RootStack.Screen name="Main" component={MainStackScreen} options={{ headerShown: false }} /> <RootStack.Screen name="MyModal" component={ModalScreen} /> </RootStack.Navigator> ); }

export function App() { return ( <NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}> <RootStackScreen /> </NavigationContainer> ); }

export default App;`

Please help!

omairahmed63 avatar Oct 05 '21 23:10 omairahmed63