Search code examples
reactjswebpackelectronreact-hookswebpack-4

Using components from an external directory in a Electron project with Webpack


I am trying to do this as simple as possible, I studied Yarn Workspaces for a while, but that's a solution that's currently doesn't work with Electron, there were simply too many issues.

  • I have am Electron project here: ./electron/
  • I have a directory with components here: ./common/

The components are developed in React/JSX, there is nothing really fancy about them. That said, I am using hooks (useXXX).

I tried many ways to include those components (ideally, I wanted to use Yarn Workspaces, but it only multiplied the number of issues), but they all failed. Which is why I would like to avoid using yarn link or workspaces or making the common a library, etc. I just want my Electron project to behave as if the files were under ./electron. That's it.

The closest I came to a solution is by using electron-webpack, and overriding it with this config:

module.exports = function(config) {
  config = merge.smart(config, {
    module: {
      rules: [
        {
          test: /\.jsx?$/,
          //include: /node_modules/,
          include: Path.resolve(__dirname, '../common'),
          loaders: ['react-hot-loader/webpack', 'babel-loader?presets[]=@babel/preset-react']
        },
      ]
    },
    resolve: {
      alias: {
        '@common': Path.resolve(__dirname, '../common')
      }
    }
  })

  return config
}

I can import modules, and they work... except if I use hooks. And I am getting the "Invalid Hook Call Warning": https://reactjs.org/warnings/invalid-hook-call-warning.html.

I feel like that /common folder is not being compiled properly by babel, but the reality is that I have no idea where to look or what to try. I guess there is a solution for this, through that webpack config.

Thanks in advance for your help :)


Solution

  • I found the solution. That happens because the instance of React is different between /common and /electron.

    The idea is to add an alias, like this:

    'react': Path.resolve('./node_modules/react')
    

    Of course, the same can be done for other modules which need to be exactly on the same instance. Don't hesitate to comment this if this answer it not perfectly right.