forge icon indicating copy to clipboard operation
forge copied to clipboard

Unable to import local modules into main.js in app built with vite template

Open rhythnic opened this issue 1 year ago • 5 comments

Pre-flight checklist

  • [X] I have read the contribution documentation for this project.
  • [X] I agree to follow the code of conduct that this project uses.
  • [X] I have searched the issue tracker for a bug that matches the one I want to file, without success.

Electron Forge version

6.1.1

Electron version

v24.1.2

Operating system

Ubuntu 20.4.6

Last known working Electron Forge version

No response

Expected behavior

App allows importing/requiring local files into main.js

Actual behavior

App throws an error when started

Uncaught Exception:
Error: Cannot find module './mod'
Require stack:
- /PROJECT_PATH/.vite/build/main.js
- /PROJECT_PATH/node_modules/electron/dist/resources/default_app.asar/main.js

Steps to reproduce

  1. Scaffold a new application with command: yarn create electron-app my-app --template=vite
  2. Create any JS file, e.g. mod.js
  3. Require mod.js in the main.js file.
  4. Run yarn start

Additional information

No response

rhythnic avatar Apr 15 '23 13:04 rhythnic

This is unlikely, or can you provide a minimal reproduction repo?

caoxiemeihao avatar Apr 15 '23 13:04 caoxiemeihao

Hi @caoxiemeihao, it might be worthwhile trying the reproduction steps provided. I encountered a similar issue and found that using import instead of require works. Vite doesn't bundle the file when required. Not much of a hurdle now that I'm aware, but it's confusing since the template comes with requires.

If you are interested, a reproduction repository/run is here https://github.com/miraries/electron-forge-issue-repro/actions/runs/4929837390/jobs/8809987890#step:5:58.

Perhaps we could update the main.js vite template?

miraries avatar May 09 '23 20:05 miraries

@miraries Thanks for your reproduction it. Because @rollup/plugin-commonjs will be ignore parse require() when we use Vite bundle as cjs format. At present, we have two solution for it:

  1. use import instead require (recommend)
  2. add vite-plugin-commonjs

vite.main.config.mjs

  import { defineConfig } from 'vite';
+ import pluginCommonjs from 'vite-plugin-commonjs';

+ const commonjs = pluginCommonjs();
+ commonjs.apply = undefined; // enable for build

  // https://vitejs.dev/config
  export default defineConfig({
+   plugins: [commonjs()],
  });

TODO

  • [ ] better solution for require

caoxiemeihao avatar Jun 02 '23 10:06 caoxiemeihao

@miraries Thanks for your reproduction it. Because @rollup/plugin-commonjs will be ignore parse require() when we use Vite bundle as cjs format. At present, we have two solution for it:

  1. use import instead require (recommend)
  2. add vite-plugin-commonjs

vite.main.config.mjs

  import { defineConfig } from 'vite';
+ import pluginCommonjs from 'vite-plugin-commonjs';

+ const commonjs = pluginCommonjs();
+ commonjs.apply = undefined; // enable for build

  // https://vitejs.dev/config
  export default defineConfig({
+   plugins: [commonjs()],
  });

TODO

  • [ ] better solution for require

Neither of the suggested solutions works for me. Even if main.js is turned into .mjs to support import syntax since the code from the required is not added to the bundle. So it searches in .vite/build/fileName.js and finds nothing.

However, this seems to be a common issue with rollup/vite. I think many of us got a bit too comfortable with the way webpack handles files.

My way to solve this was to add plugin that copy files to the right destination and then set destination target in require.

// vite.main.config.mjs

import {defineConfig} from 'vite';
import copy from 'rollup-plugin-copy'

export default defineConfig({
    plugins: [
        copy({
            targets: [
                {
                    src: 'src/main-process/api/**/*.{js,mjs}',
                    dest: ".vite/build",
                    rename (name, extension, fullPath) {
                        fullPath = fullPath.replace("src/", "");
                        fullPath = fullPath.replace(`/${name}.${extension}`, "")

                        // Rename .mjs to .js in order to follow rules of build system
                        if (extension === "mjs") {
                            return `${fullPath}/${name}.js`
                        }
                        // Preserve the directory structure when copyng the file.
                        return `${fullPath}/${name}.${extension}`
                    }
                },
            ]
        })
    ]
});

// src/main.js
const getThemeConfig = require("./main-process/api/theme/getThemeConfig.js");

Im currently checking if it's possible to get the paths properly by using custom alias and change it depending on what mode you are running.

Ballpin avatar Jun 15 '23 16:06 Ballpin

I am facing the same issue where I am trying to import a function and it shows - "connect" is not exported by "src/main/MongoDB.js", imported by "src/main/index.js". even tho i am exporting it - module.exports = { connect , //other functions};

Silentgamerz avatar Jul 16 '24 17:07 Silentgamerz