3

I need some help with NextJS webpack config?

I have a mono-repo and share code between React-Native and NextJS. To split OS-specific code I separated the native and the web code like that: (Login.web.tsx & Login.native.tsx)

Example: /Login/index.tsx

import React, { lazy, ReactElement, Suspense } from 'react'
import { Platform, View } from 'react-native'

const LoginComponent = lazy(() => (Platform.OS === 'web' ? import('./Login.web') : import('./Login.native')))

const Login = (props: NavigationProp): ReactElement => {
  return (
    <Suspense fallback={<View />}>
      <LoginComponent {...props} />
    </Suspense>
  )
}

export default Login

This example code is located in the ui-screens project and will be imported into the one and only NextJS page like that

import { Login } from '@monorepo/ui-screens'

export default function App() {
  return (
    <Login />
  )
}

React-Native deals perfectly with that and loads the correct Login.native.tsx page. But the NextJS webpack compiler still sees this file Login.native.tsx and tries to compile it, which obviously causes errors.

When I change the code of /Login/index.tsx like that, for test purposes, my web app runs fine

const LoginComponent = lazy(() => (Platform.OS === 'web' ? import('./Login.web') : import('./Login.web')))

How can I make webpack to exclude files that have the *.native.* extensions?

Note: I tried RemovePlugin:

const withPlugins = require('next-compose-plugins')
const withTM = require('next-transpile-modules')([
  'react-native',
  '@types/react-native',
  '@monorepo/ui-screens'
])
const RemovePlugin = require('remove-files-webpack-plugin')

module.exports = withPlugins([withTM()], {
  enableSvg: true,
  esModule: true,
  images: {
    disableStaticImages: true
  },
  plugins: [
    new RemovePlugin({
      before: {
        include: ['Login.native.tsx']
      }
    })
  ],
  webpack: (config) => {
    config.resolve.alias = {
      ...(config.resolve.alias || {}),
     'react-native$': 'react-native-web',
    }
    config.resolve.extensions = ['.web.js', '.web.jsx', '.web.ts', ...config.resolve.extensions]
    return config
  }
}

But it has no effect.

Any help would be much appreciated.

Thomas Dittmar
  • 1,764
  • 1
  • 23
  • 42

2 Answers2

7

After hours of reading the webpack docs, Github issues and comments, I have finally found a super easy solution called webpackIgnore

Just by inserting it into the import command, I can tell webpack to literally ignore the file at compilation time:

const LoginComponent = lazy(
 () => (Platform.OS === 'web' ? 
 import('./Login.web'): 
 import(/* webpackIgnore: true */ './Login.native'))
)

I love this elegant solution.

Now I only have to tell my Typescript compiler to NOT delete this line.

Thomas Dittmar
  • 1,764
  • 1
  • 23
  • 42
  • 1
    Well done. I'm looking for a pure nextjs webpack config to just ignore the native and take only web.js or other js files. Can't seem to find one. – KeitelDOG May 21 '22 at 15:39
  • Does anyone know why `config.resolve.extensions` have no effect in NextJS webpack config?? – conor909 Oct 17 '22 at 11:54
  • I believe packages such as `react-native-svg` relies on file extension splitting – conor909 Oct 17 '22 at 13:03
0

I had a similar problem. I seem to have been able to get around it by moving the affected files into the public folder.

In my case I had two files which contained functions being used by many different components. In the components, the function were called using useEffect, so there was no issue until I tried to build the project. Moving the files into the public folder and changing some references allowed my project to build successfully and keep working.

Next.js only prerenders files in the pages folder.

F-67
  • 3
  • 2