Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

require is not defined in ES module scope #68

Closed
Hsinky opened this issue Feb 5, 2024 · 35 comments
Closed

require is not defined in ES module scope #68

Hsinky opened this issue Feb 5, 2024 · 35 comments

Comments

@Hsinky
Copy link

Hsinky commented Feb 5, 2024

when run nuxt dev && electron .
error
require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '[path]\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

help me,please!

@Hsinky
Copy link
Author

Hsinky commented Feb 5, 2024

It worked ! when i remove "type": "module" in package.json,but,I want to use es6,how to update?

@angelhdzdev
Copy link

It worked ! when i remove "type": "module" in package.json,but,I want to use es6,how to update?

~/tsconfig.json

{
...
"compilerOptions": {
  "module: "es6" 
  // or target: "es6"
}
}

Maybe?

@Hsinky
Copy link
Author

Hsinky commented Feb 7, 2024

It worked ! when i remove "type": "module" in package.json,but,I want to use es6,how to update?

~/tsconfig.json

{
...
"compilerOptions": {
  "module: "es6" 
  // or target: "es6"
}
}

Maybe?

Thanks for your help! but ,Still the same error

@angelhdzdev
Copy link

By the way, I never run nuxt dev && electron .. I only run nuxt dev and I get the electron window.

@Hsinky
Copy link
Author

Hsinky commented Feb 7, 2024

By the way, I never run nuxt dev && electron .. I only run nuxt dev and I get the electron window.

Realy?ummm,I try it again,Yes,I got the electron window when i remove type:module in package.json,Otherwise, it would be the same error

@Hsinky
Copy link
Author

Hsinky commented Feb 7, 2024

image

@angelhdzdev
Copy link

Can you tell more about your environment?
Are you using JavaScript with require?

@Hsinky
Copy link
Author

Hsinky commented Feb 7, 2024

No require is used in the code
node:v20.11.0
"@nuxt/ui": "^2.13.0",
"nuxt": "^3.10.0",
"vue": "^3.4.15",
"vue-router": "^4.2.5"
"electron-builder": "^24.9.1",
"electron": "^28.2.1",
"nuxt-electron": "^0.7.0",
"vite-plugin-electron": "^0.15.6",
"vite-plugin-electron-renderer": "^0.14.5"
PC OS:win 10

@Hsinky
Copy link
Author

Hsinky commented Feb 7, 2024

Can you tell more about your environment? Are you using JavaScript with require?

image
nuxt-electron

@angelhdzdev
Copy link

I'm not from the team by the way 😁

Just wanted to help. I'm starting with Electron and Nuxt, had an issue with the preload, and solved it.

All I've read on the internet mentions removing "type": "module" from package.json to get it working.

Both Nuxt and Electron are ESM ready:
https://www.electronjs.org/docs/latest/tutorial/esm
https://nuxt.com/docs/guide/concepts/esm

So, do you want to get rid of the error, or you want to have your .js files with ESM imports instead of require?

(will be playing with tsconfig.json to see if I find something)

@Hsinky
Copy link
Author

Hsinky commented Feb 7, 2024

I'm not from the team by the way 😁

Just wanted to help. I'm starting with Electron and Nuxt, had an issue with the preload, and solved it.

All I've read on the internet mentions removing "type": "module" from package.json to get it working.

Both Nuxt and Electron are ESM ready: https://www.electronjs.org/docs/latest/tutorial/esm https://nuxt.com/docs/guide/concepts/esm

So, do you want to get rid of the error, or you want to have your .js files with ESM imports instead of require?

(will be playing with tsconfig.json to see if I find something)

Thanks for your help again!I wrote the code in nuxt-electron(https://nuxt.com/modules/electron)

@angelhdzdev
Copy link

angelhdzdev commented Feb 7, 2024

Hmmm... 🤔
electron-vite/vite-plugin-electron#186

Edit: And I think the renderer option in nuxt.config.ts > electron is for that purpose...

@angelhdzdev
Copy link

Update

I'm getting somewhere... 👀

image

@angelhdzdev
Copy link

Stay tuned to electron-vite/vite-plugin-electron#186

@Hsinky
Copy link
Author

Hsinky commented Feb 8, 2024

I'm getting somewhere

My question is same to you,So,Did you solve it?

@angelhdzdev
Copy link

I'm getting somewhere

My question is same to you,So,Did you solve it?

Not yet. Will keep playing with the renderer options until I solve it and will let you know.

@Hsinky
Copy link
Author

Hsinky commented Feb 8, 2024

Not yet. Will keep playing with the renderer options until I solve it and will let you know.

Thanks!!

@angelhdzdev
Copy link

angelhdzdev commented Feb 9, 2024

Solution

Update vite-plugin-electron to 0.28.1, and add "type": "module" in package.json.

Edit: You'll get an error because of __dirname in electron/main when defining process.env.ROOT. Replace with process.cwd():

process.env.ROOT = path.join(process.cwd(), '..')
process.env.DIST = path.join(process.env.ROOT, 'dist-electron')
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? path.join(process.env.ROOT, 'public')
  : path.join(process.env.ROOT, '.output/public')
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
const preload = path.join(process.env.DIST, 'preload.js')

Solution Revisited

#68 (comment)

@TristanDuck
Copy link

Tried all the suggestions here but still getting this:
image

@angelhdzdev
Copy link

Tried all the suggestions here but still getting this: image

Show package.json and nuxt.config please.

@TristanDuck
Copy link

Tried all the suggestions here but still getting this: image

Show package.json and nuxt.config please.

// https://nuxt.com/docs/api/configuration/nuxt-config
import vuetify from 'vite-plugin-vuetify'

export default defineNuxtConfig({
  typescript: {
    shim: false,
  },
  ssr: false,
  electron: {
    build: [
      {
        // Main-Process entry file of the Electron App.
        entry: 'electron/main.ts',
      },
      {
        entry: 'electron/preload.ts',
        onstart(args) {
          // Notify the Renderer-Process to reload the page when the Preload-Scripts build is complete,
          // instead of restarting the entire Electron App.
          args.reload()
        },
      },
    ],
    renderer: {},
  },
  modules: [
    'nuxt-electron',
    (_options, nuxt) => {
      nuxt.hooks.hook('vite:extendConfig', (config) => {
        config.plugins.push(vuetify({ autoImport: true }))
      })
    },
  ],
  build: {
    transpile: ['vuetify'],
  },
  devtools: { enabled: true },
})
{
  "name": "nuxt-app",
  "version": "1.0.0",
  "private": true,
  "main": "dist-electron/main.js",
  "type": "module",
  "scripts": {
    "dev": "nuxi dev",
    "build": "nuxi build --prerender && electron-builder",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  },
  "dependencies": {
    "@mdi/font": "^7.4.47"
  },
  "devDependencies": {
    "@antfu/eslint-config": "^2.6.4",
    "electron": "^28.2.4",
    "electron-builder": "^24.12.0",
    "eslint": "^8.56.0",
    "nuxt": "^3.10.1",
    "nuxt-electron": "^0.7.0",
    "sass": "^1.70.0",
    "vite-plugin-electron": "0.28.1",
    "vite-plugin-electron-renderer": "^0.14.5",
    "vite-plugin-vuetify": "^2.0.1",
    "vuetify": "^3.5.3"
  }
}

@angelhdzdev
Copy link

Tried all the suggestions here but still getting this: image

Show package.json and nuxt.config please.

// https://nuxt.com/docs/api/configuration/nuxt-config
import vuetify from 'vite-plugin-vuetify'

export default defineNuxtConfig({
  typescript: {
    shim: false,
  },
  ssr: false,
  electron: {
    build: [
      {
        // Main-Process entry file of the Electron App.
        entry: 'electron/main.ts',
      },
      {
        entry: 'electron/preload.ts',
        onstart(args) {
          // Notify the Renderer-Process to reload the page when the Preload-Scripts build is complete,
          // instead of restarting the entire Electron App.
          args.reload()
        },
      },
    ],
    renderer: {},
  },
  modules: [
    'nuxt-electron',
    (_options, nuxt) => {
      nuxt.hooks.hook('vite:extendConfig', (config) => {
        config.plugins.push(vuetify({ autoImport: true }))
      })
    },
  ],
  build: {
    transpile: ['vuetify'],
  },
  devtools: { enabled: true },
})
{
  "name": "nuxt-app",
  "version": "1.0.0",
  "private": true,
  "main": "dist-electron/main.js",
  "type": "module",
  "scripts": {
    "dev": "nuxi dev",
    "build": "nuxi build --prerender && electron-builder",
    "lint": "eslint .",
    "lint:fix": "eslint . --fix"
  },
  "dependencies": {
    "@mdi/font": "^7.4.47"
  },
  "devDependencies": {
    "@antfu/eslint-config": "^2.6.4",
    "electron": "^28.2.4",
    "electron-builder": "^24.12.0",
    "eslint": "^8.56.0",
    "nuxt": "^3.10.1",
    "nuxt-electron": "^0.7.0",
    "sass": "^1.70.0",
    "vite-plugin-electron": "0.28.1",
    "vite-plugin-electron-renderer": "^0.14.5",
    "vite-plugin-vuetify": "^2.0.1",
    "vuetify": "^3.5.3"
  }
}

Please, check your electron/main.ts that matches this:
#68 (comment)

@angelhdzdev
Copy link

Tried all the suggestions here but still getting this: image

SOLUTION

In ~/electron/main.ts, replace process.env.ROOT = path.join(process.cwd(), '..') or process.env.ROOT = path.join(__dirname, '..')
with process.env.ROOT = path.join(import.meta.url, '..').

As per the error shown, __dirname doesn't work in ES6 modules.
Replacement for modules is import.meta.url to get the path to the electron/main.ts file (to itself) and from there, 2 levels up to reach the CWD (Current Working Directory, the root of the nuxt project).

@TristanDuck
Copy link

Tried all the suggestions here but still getting this: image

SOLUTION

In ~/electron/main.ts, replace process.env.ROOT = path.join(process.cwd(), '..') or process.env.ROOT = path.join(__dirname, '..') with process.env.ROOT = path.join(import.meta.url, '..').

As per the error shown, __dirname doesn't work in ES6 modules. Replacement for modules is import.meta.url to get the path to the electron/main.ts file (to itself) and from there, 2 levels up to reach the CWD (Current Working Directory, the root of the nuxt project).

This worked! Thanks for the help.

@Hsinky
Copy link
Author

Hsinky commented Feb 26, 2024

Solution

Update vite-plugin-electron to 0.28.1, and add "type": "module" in package.json.

Edit: You'll get an error because of __dirname in electron/main when defining process.env.ROOT. Replace with process.cwd():

process.env.ROOT = path.join(process.cwd(), '..')
process.env.DIST = path.join(process.env.ROOT, 'dist-electron')
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? path.join(process.env.ROOT, 'public')
  : path.join(process.env.ROOT, '.output/public')
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
const preload = path.join(process.env.DIST, 'preload.js')

Thanks!!! There are other mistakes.
image

@angelhdzdev
Copy link

angelhdzdev commented Feb 26, 2024

Solution

Update vite-plugin-electron to 0.28.1, and add "type": "module" in package.json.
Edit: You'll get an error because of __dirname in electron/main when defining process.env.ROOT. Replace with process.cwd():

process.env.ROOT = path.join(process.cwd(), '..')
process.env.DIST = path.join(process.env.ROOT, 'dist-electron')
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? path.join(process.env.ROOT, 'public')
  : path.join(process.env.ROOT, '.output/public')
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
const preload = path.join(process.env.DIST, 'preload.js')

Thanks!!! There are other mistakes. image

Your remove the ../ from ../preload.js

@Hsinky
Copy link
Author

Hsinky commented Feb 26, 2024

it does't work
image

@angelhdzdev
Copy link

it does't work image

const preload = path.join(process.env.DIST, 'preload.js')

@Hsinky
Copy link
Author

Hsinky commented Feb 26, 2024

That's not the problem.The following code runs in the development environment

process.env.ROOT = path.join(process.cwd())//, '..'
process.env.DIST = path.join(process.env.ROOT, 'dist-electron')
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? path.join(process.env.ROOT, 'public')
  : path.join(process.env.ROOT, '.output/public')
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
const preload = path.join(process.env.DIST, 'preload.js')

but,It will not work after installation
image

@angelhdzdev
Copy link

angelhdzdev commented Feb 26, 2024

That's not the problem.The following code runs in the development environment

process.env.ROOT = path.join(process.cwd())//, '..'
process.env.DIST = path.join(process.env.ROOT, 'dist-electron')
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
  ? path.join(process.env.ROOT, 'public')
  : path.join(process.env.ROOT, '.output/public')
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
const preload = path.join(process.env.DIST, 'preload.js')

but,It will not work after installation image

That's a different issue. We are talking about ESM in this thread.

Probably you need to check if your environment is DEV or PROD and use the appropriate path like __dirname instead of import.meta.url.

Edit: I'm checking this issue. __dirname is not going to work in ESM in production and we are compiling to ESM. So we stick to import.meta.url.

Edit: I reached a dead end here. Can't make it work when building the .exe. Getting errors in DEV mode, and in PROD the Electron window is empty.

@Hsinky
Copy link
Author

Hsinky commented Feb 27, 2024

type:module in package.json,error!(I'm not good at English.)
image

@Hsinky
Copy link
Author

Hsinky commented Feb 27, 2024

when process.env.ROOT =path.join(import.meta.url,'../..') ,erro is reload script must have absolute path
when process.env.ROOT =path.join(process.cwd()),error is preload.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.

@salazarr-js
Copy link

If we're trying to use ES Modules (ESM) in Electron we should have "type": "module" in our package.json and the preload scripts must have the .mjs extension

The problem is that the nuxt-electron plugin does't do this automatically despite it using vite-plugin-electron internally and this was discussed/fixed on electron-vite/vite-plugin-electron#186

This is a little workaround that worked for me

nuxt.config.ts

export default defineNuxtConfig({
  ...,
  modules: ['nuxt-electron'],
  electron: {
    renderer: { },
    build: [
      { entry: 'electron/main.ts' },
      {
        entry: 'electron/preload.ts',
        vite: {
          build: {
            rollupOptions: {
              output: {
                entryFileNames: `[name].mjs`,
                chunkFileNames: `[name].mjs`,
              },
            },
          },
        },
        onstart(args) {
          args.reload()
        },
      },
    ],
  },
})

This generates the proper dist-electron/preload.mjs file that the main electron script expects.

electron/main.ts

import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { env } from 'node:process'
//
import { BrowserWindow, app } from 'electron'

/** Env */
const isDev = !!env.VITE_DEV_SERVER_URL
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

env.ROOT = path.join(dirname, '../')
env.DIST = path.join(env.ROOT, 'dist-electron')
env.VITE_PUBLIC = isDev ? path.join(env.ROOT, 'public') : path.join(env.ROOT, '.output/public')
// env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'

/** Create main windows and load app */
function bootstrap() {
  const preload = path.join(env.DIST!, 'preload.mjs')

  const mainWindow = new BrowserWindow({
    width: 1280,
    height: 1024,
    webPreferences: {
      preload,
      nodeIntegrationInWorker: true,
      contextIsolation: false,
      nodeIntegration: true,
      webSecurity: false, // TODO: fix `Insecure Content-Security-Policy`
    },
  })

  if (isDev) {
    mainWindow.loadURL(env.VITE_DEV_SERVER_URL!)
    mainWindow.webContents.openDevTools()
  }
  else {
    mainWindow.loadFile(path.join(env.VITE_PUBLIC!, 'index.html'))
  }
}

/** Main process */
app.whenReady().then(() => {
  bootstrap()
})

I've to mention that I don't know what I'm doing, nor am I a Nuxt or Electron expert, but all the @angelhdzmultimedia messages helped me to find a way, thanks 🙋‍♂️.

@angelhdzdev
Copy link

If we're trying to use ES Modules (ESM) in Electron we should have "type": "module" in our package.json and the preload scripts must have the .mjs extension

The problem is that the nuxt-electron plugin does't do this automatically despite it using vite-plugin-electron internally and this was discussed/fixed on electron-vite/vite-plugin-electron#186

This is a little workaround that worked for me

nuxt.config.ts

export default defineNuxtConfig({
  ...,
  modules: ['nuxt-electron'],
  electron: {
    renderer: { },
    build: [
      { entry: 'electron/main.ts' },
      {
        entry: 'electron/preload.ts',
        vite: {
          build: {
            rollupOptions: {
              output: {
                entryFileNames: `[name].mjs`,
                chunkFileNames: `[name].mjs`,
              },
            },
          },
        },
        onstart(args) {
          args.reload()
        },
      },
    ],
  },
})

This generates the proper dist-electron/preload.mjs file that the main electron script expects.

electron/main.ts

import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { env } from 'node:process'
//
import { BrowserWindow, app } from 'electron'

/** Env */
const isDev = !!env.VITE_DEV_SERVER_URL
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

env.ROOT = path.join(dirname, '../')
env.DIST = path.join(env.ROOT, 'dist-electron')
env.VITE_PUBLIC = isDev ? path.join(env.ROOT, 'public') : path.join(env.ROOT, '.output/public')
// env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'

/** Create main windows and load app */
function bootstrap() {
  const preload = path.join(env.DIST!, 'preload.mjs')

  const mainWindow = new BrowserWindow({
    width: 1280,
    height: 1024,
    webPreferences: {
      preload,
      nodeIntegrationInWorker: true,
      contextIsolation: false,
      nodeIntegration: true,
      webSecurity: false, // TODO: fix `Insecure Content-Security-Policy`
    },
  })

  if (isDev) {
    mainWindow.loadURL(env.VITE_DEV_SERVER_URL!)
    mainWindow.webContents.openDevTools()
  }
  else {
    mainWindow.loadFile(path.join(env.VITE_PUBLIC!, 'index.html'))
  }
}

/** Main process */
app.whenReady().then(() => {
  bootstrap()
})

I've to mention that I don't know what I'm doing, nor am I a Nuxt or Electron expert, but all the @angelhdzmultimedia messages helped me to find a way, thanks 🙋‍♂️.

Hey! Thanks for the feedback. Will try your solution.

@caoxiemeihao
Copy link
Owner

package.json

{
- "type": "module",
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants