electron-userland / electron-webpack

Scripts and configurations to compile Electron applications using webpack
https://webpack.electron.build/
905 stars 171 forks source link

"Uncaught Error: module not found" inside preload script #276

Open amaury1093 opened 5 years ago

amaury1093 commented 5 years ago

Here's my preload.js:

const { ipcRenderer, remote } = require('electron');

window.electron = {
  ipcRenderer,
  remote
};

And I load it like this:

const window = new BrowserWindow({
    webPreferences: {
      nodeIntegration: false,
      preload: path.resolve(__dirname, 'preload.js')
    }
  });

with the following electron-webpack config:

{
  "main": {
    "extraEntries": ["@/preload.js"]
  }
}

With electron-webpack dev

Everything works.

With electron-webpack build && electron dist/main.js

The error I get in the BrowserWindow console is:

Uncaught Error: module not found
    at preloadRequire (<anonymous>:3059:9)
    at <anonymous>:2:3
    at Object.<anonymous> (<anonymous>:3112:3)
    at Object.require.32../../common/atom-binding-setup (<anonymous>:3120:4)
    at o (<anonymous>:2:273)
    at r (<anonymous>:2:439)
    at <anonymous>:2:468

If interested, here's the compiled dist/preload.js:

require("source-map-support/source-map-support.js").install(),module.exports=function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:n})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(t.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)t.d(n,o,function(r){return e[r]}.bind(null,o));return n},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=28)}({0:function(e,r){e.exports=require("electron")},28:function(e,r,t){const{ipcRenderer:n,remote:o}=t(0);window.electron={ipcRenderer:n,remote:o}}});
//# sourceMappingURL=preload.js.map

Also, if I copy my original preload.js, and paste it into dist/preload.js, and just run electron dist/main, everything works again.

My guess (not 100% sure): the webpack target for everything inside extraEntries is electron, so preload.js is bundled with that target (hence the module.exports stuff), but it should be bundled with target web or electron-renderer.

yanlee26 commented 4 years ago

ERROR in Entry module not found: Error: Can't resolve '@/preload.ts'

loopmode commented 4 years ago

When I needed a preload script, I also ran into various issues. In the end I was happy with the workaround of treating the preload script as a static asset instead of as source code. I used the static folder and a .js file and that worked. Once I even had a tsc watching and generating the js.

xland commented 4 years ago

How about this issue's progress

raviSussol commented 3 years ago

I'm having the same issue that preload.js file is not included in the distribution built app while in develop it runs ok. How can we bundle and include in build version of the application?

shahkeyur commented 3 years ago

@raviSussol Have you added preload.js in extraEntries ?

raviSussol commented 3 years ago

@shahkeyur Yes I have: electron-webpack.json

{
  "title": true,
  "commonSourceDirectory": "src/common",
  "staticSourceDirectory": "src/static",
  "main": {
    "extraEntries": ["@/preload.js"],
    "sourceDirectory": "src/main"
  },
  "renderer": {
    "sourceDirectory": "src/renderer",
    "template": "src/index.html"
  }
}

src/main/index.js

  // Create the browser window.
  const window = new BrowserWindow({
    width: 800,
    height: 600,
    show: false,
    webPreferences: {
      nodeIntegration: true,
      preload: resolve(__dirname, 'preload.js')
    }
  });

src/main/preload.js

// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector);
    if (element) element.innerText = text;
  };

  for (const type of ['chrome', 'node', 'electron']) {;
    replaceText(`${type}-version`, process.versions[type]);
  }
})

Output In develop Screen Shot 2021-03-06 at 7 31 40 AM

In prod Screen Shot 2021-03-06 at 7 36 17 AM

Even my index.html is not included in the built version of the app. I tried with placing it inside/outside of the renderer folder with the mentioned path settings in the electron-webpack.json but no luck. 😞 I'm not sure what I'm missing...

loopmode commented 3 years ago

Hmm have you tried without the magic @ in the path?

shahkeyur commented 3 years ago

@raviSussol Probably to debug you should try opening the devtools in prod mode, and see if you're getting any error. I have been using the preload for a while and I haven't had any issues. I suspect it is some misconfiguration.

raviSussol commented 3 years ago

@loopmode,

Hmm have you tried without the magic @ in the path?

Tried with removing @ and with full path src/main/preload.js - didn't work

@shahkeyur,

@raviSussol Probably to debug you should try opening the devtools in prod mode, and see if you're getting any error. I have been using the preload for a while and I haven't had any issues. I suspect it is some misconfiguration.

OK I tried to look at all relative/absolute paths configuration in the app and I found a mistake in the index.html path given to the window.loadURL. Could be to do with that wrong config that my index.html wasn't loading in the prod app at first. Fixed it with path.resolve(__dirname, 'index.html') and now its working in the built version as well. However, when I replaced window.loadURL with window.loadFile it again fails to load the html file in the production. Not allowed to load local resource error I'm getting when I see in the dev tool in the prod app. Tried to give absolute path as well but couldn't success.

Screen Shot 2021-03-06 at 3 33 03 PM

I want to use window.loadFile as this is a recommended way to load resource in the latest electron app. window.loadURL has now become older and not preferred to be use (or a bit slower than window.loadFile) in terms of performance.

raviSussol commented 3 years ago

Ignore my above comments. Got fixed by removing file:// from the window.loadFile path. I realized that load file api just uses file path directly rather converting it to a url (with file://). Now its working but Im getting another issue that if I add npm module in the preload.js file then get unable to load preload script: Screen Shot 2021-03-06 at 4 07 29 PM

I was using custom title bar electron: src/main/preload.js:

const customTitlebar = require('custom-electron-titlebar');
window.addEventListener('DOMContentLoaded', () => {
  new customTitlebar.Titlebar({
    backgroundColor: customTitlebar.Color.fromHex('#2f3241')
  })
})