caoxiemeihao / nuxt-electron

Integrate Nuxt and Electron
MIT License
169 stars 18 forks source link

require is not defined in ES module scope #68

Closed Hsinky closed 2 months ago

Hsinky commented 4 months ago

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 commented 4 months ago

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

angelhdzmultimedia commented 4 months ago

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 commented 4 months ago

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

angelhdzmultimedia commented 4 months ago

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

Hsinky commented 4 months ago

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 commented 4 months ago

image

angelhdzmultimedia commented 4 months ago

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

Hsinky commented 4 months ago

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 commented 4 months ago

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

image nuxt-electron

angelhdzmultimedia commented 4 months ago

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 commented 4 months ago

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)

angelhdzmultimedia commented 4 months ago

Hmmm... 🤔 https://github.com/electron-vite/vite-plugin-electron/issues/186

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

angelhdzmultimedia commented 4 months ago

Update

I'm getting somewhere... 👀

image

angelhdzmultimedia commented 4 months ago

Stay tuned to https://github.com/electron-vite/vite-plugin-electron/issues/186

Hsinky commented 4 months ago

I'm getting somewhere

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

angelhdzmultimedia commented 4 months ago

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 commented 4 months ago

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

Thanks!!

angelhdzmultimedia commented 4 months ago

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

https://github.com/caoxiemeihao/nuxt-electron/issues/68#issuecomment-1959182705

TristanDuck commented 4 months ago

Tried all the suggestions here but still getting this: image

angelhdzmultimedia commented 4 months ago

Tried all the suggestions here but still getting this: image

Show package.json and nuxt.config please.

TristanDuck commented 4 months ago

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"
  }
}
angelhdzmultimedia commented 4 months ago

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: https://github.com/caoxiemeihao/nuxt-electron/issues/68#issuecomment-1935280744

angelhdzmultimedia commented 4 months ago

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 commented 4 months ago

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 commented 4 months ago

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

angelhdzmultimedia commented 4 months ago

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 commented 4 months ago

it does't work image

angelhdzmultimedia commented 4 months ago

it does't work image

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

Hsinky commented 4 months ago

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

angelhdzmultimedia commented 4 months ago

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 commented 4 months ago

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

Hsinky commented 4 months ago

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 commented 3 months ago

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 🙋‍♂️.

angelhdzmultimedia commented 3 months ago

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 commented 2 months ago

package.json


{
- "type": "module",
}