electron / forge

:electron: A complete tool for building and publishing Electron applications
https://electronforge.io
MIT License
6.46k stars 514 forks source link

webview’s preload script cannot be found in production #1590

Open deadcoder0904 opened 4 years ago

deadcoder0904 commented 4 years ago

My preload.js file is in src/components/MyComponent folder. And my other file containing webview is like following:

 const getSourceDirectory = () =>
 process.env.NODE_ENV === "development"
 ? path.join(process.cwd(), "src/components/MyComponent") // or wherever your local build is compiled
 : path.join(process.resourcesPath) // asar location
 const preload = `file://${path.resolve(getSourceDirectory(), 'preload.js')}`

And I include it like:

<webview
    preload={preload}
    src="https://google.com"
/>

This works in development because I know the path. I can’t seem to find the path in production though.

And if I put the same path as development, i.e, "src/components/MyComponent" then it says Can’t find preload.js which is obvious.

How do I make this thing work in production with electron-forge?

I know the error is in the else condition of the ternary operator, i.e, path.join(process.resourcesPath) should be changed to something else but what should it be changed to?

deadcoder0904 commented 4 years ago

I forgot to mention I also added Global Variables in Project Setup as stated like:

const mainWindow = new BrowserWindow({
  webPreferences: {
    preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
  }
});

But I don’t know how to make sure it uses that as my path.

deadcoder0904 commented 4 years ago

I tried doing it like https://github.com/electron-userland/electron-forge/issues/1606 by mentioning it in forge.config.js in package.json:

{
    "mainConfig": "./webpack.main.config.js",
    "renderer": {
        "config": "./webpack.renderer.config.js",
        "entryPoints": [
            {
                "html": "./src/index.html",
                "js": "./src/renderer.tsx",
                "name": "main_window",
                "preload": {
                    "js": "./src/components/MyComponent/preload.ts"
                }
            }
        ]
    }
}

It works well in development. So I tried making it work in production.

In prod, it gives the path to be C:\MyApp\out\myapp-win32-x64\resources\app\.webpack\renderer\renderer\main_window\preload.js

Notice the renderer comes twice. This is the error.

My preload.js exists in C:\MyApp\out\myapp-win32-x64\resources\app\.webpack\renderer\main_window\preload.js

The issue might be somewhere in https://github.com/electron-userland/electron-forge/blob/a7d93bb3e4ed256e86e013920c71887aad28a4d2/packages/plugin/webpack/src/WebpackConfig.ts

deadcoder0904 commented 4 years ago

I made a minimal repro for it https://github.com/deadcoder0904/webview-forge-production-error

I am pretty sure the error is somewhere in this file maybe at https://github.com/electron-userland/electron-forge/blob/master/packages/plugin/webpack/src/WebpackConfig.ts#L58

If anyone can point me in the right-direction I'd try tackling it.

@MarshallOfSound @malept would love any pointers?

aabuelenin commented 4 years ago

I've the same problem, @deadcoder0904 did you manage to find a workaround?

deadcoder0904 commented 4 years ago

@aabuelenin I don't think so otherwise I would've posted an answer :)

patrikniebur commented 4 years ago

I've posted my solution to Stack Overflow. Let me know if it helps!

aabuelenin commented 4 years ago

I ended up doing a string replacement, it's not a good solution, but it works

I'm using capture groups to make it work on different platforms

preload={`file://${BROWSER_PRELOAD_WEBPACK_ENTRY.replace(
                        /(\/|\\)renderer(?:\/|\\)renderer(?:\/|\\)/,
                        '$1renderer$1',
                    )}`}
Eraylee commented 3 years ago

I have the same problem.

deadcoder0904 commented 3 years ago

@Eraylee try the above-posted solutions if they work. I haven't had the chance to try it yet. Although would love to find a permanent solution for this 👍

Kikketer commented 3 years ago

Using the "magic" variables worked for me as long as I used what @deadcoder0904 mentioned:

              "entryPoints": [
                {
                  "html": "./src/index.html",
                  "js": "./src/renderer.js",
                  "name": "main_window",
                  "preload": {
                    "js": "./src/preload.js"
                  }
                }
              ]

With the magic global variable:

    webPreferences: {
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
    },
  })

This isn't documented as far as I can tell: https://www.electronforge.io/config/plugins/webpack#project-setup Hope this helps someone, this worked for me from the fresh "Webpack" variety starting point.

terasum commented 3 years ago

Same problem, any solution?

yourfavorite commented 3 years ago

@terasum have you tried this solution? It worked for me.

https://github.com/electron-userland/electron-forge/issues/1590#issuecomment-691302647

terasum commented 3 years ago

@yourfavorite hi, I've tried that solution, and it doesn't work for me. Because during debug environment, the BROWSER_PRELOAD_WEBPACK_ENTRY will return http://localhost:3000/preload.js, I made a trick to fix this, here is my code:

https://github.com/terasum/medict/blob/152826f8a9145b4670d6b3d8cb91fb6bf5142c37/src/renderer/view/MainWindow.vue#L53

For your reference

george-thomas-hill commented 2 years ago

I have the same problem.

giovanni-bertoncelli commented 1 month ago

For those using Vite: https://electron-vite.org/guide/dev#webview