nx-react-native
nx-react-native copied to clipboard
React-native aliases with nextjs plugin
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 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.
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)
Hello, this is still an issue @tocalvo. Have you find a way to get this done?
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);"

And try the build again.
Any update on this?
Hi I am able to make Next JS working with React Native Web.
- 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
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!