Search code examples
webpackelectronelectron-forgenode-serialport

Webpack not including module with Electron Forge and SerialPort


I'm using the electron-forge webpack template. Had some issues but got serialport working.

But now when I run make to export the app, if I don't copy the node_modules folder to the exported webpack folder, when I run the app it shows serialport not found error.

I know that I must be doing something wrong in the config file, but what? I feel that's something missing.

I'm using const { SerialPort } = eval("require('serialport')");

When using const { SerialPort } = require('serialport'); I get the error 'No native build was found for platform=win32 arch=x64 runtime=electron abi=103 uv=1 libc=glibc node=16.13.2 electron=18.0.4 webpack=true'


Solution

  • If you are using electron-forge there are 2 things you need to understand.

    1. In order to use native modules like serialport, you have to include the modules as an external module in webpack config.

    2. If a module is listed as external, it will be pruned during the packaging process. So in your forge config, you need to include hooks during your building process.

    hooks: {
        readPackageJson: async (forgeConfig, packageJson) => {
          // only copy deps if there isn't any
          if (Object.keys(packageJson.dependencies).length === 0) {
            const originalPackageJson = await fs.readJson(path.resolve(__dirname, 'package.json'));
            const webpackConfigJs = require('./webpack.renderer.config.js');
            Object.keys(webpackConfigJs.externals).forEach(package => {
              packageJson.dependencies[package] = originalPackageJson.dependencies[package];
            });
          }
          return packageJson;
        },
        packageAfterPrune: async (forgeConfig, buildPath) => {
          console.log(buildPath);
          return new Promise((resolve, reject) => {
            const npmInstall = spawn('npm', ['install'], {
              cwd: buildPath,
              stdio: 'inherit',
              shell: true
            });
    
            npmInstall.on('close', (code) => {
              if (code === 0) {
                resolve();
              } else {
                reject(new Error('process finished with error code ' + code));
              }
            });
    
            npmInstall.on('error', (error) => {
              reject(error);
            });
          });
        }
      }