SimulatedGREG / electron-vue

An Electron & Vue.js quick start boilerplate with vue-cli scaffolding, common Vue plugins, electron-packager/electron-builder, unit/e2e testing, vue-devtools, and webpack.
https://simulatedgreg.gitbooks.io/electron-vue/content/
MIT License
15.47k stars 1.54k forks source link

How to get a Puppeteer script running inside Electron #1015

Closed mvaneijgen closed 3 years ago

mvaneijgen commented 4 years ago

I know this isn't the place to ask, but I have spend the last week getting my app to work and I'm a bit at a loss, so that is why I post this here.

Screenshot Generator App Preview

My app is done, Screenshot Generator and I'm really happy how it functions, the only slight problem is that it doesn't work... I have a Generate button component from which I try to launch a puppeteer.js script (Node.js), but I just don't know how to invoke it.

Here is what I in theory want to do sketched out. This I made before starting the project and I just started building it knowing that I didn't know how to get this last part working. I now miss 10% off the puzzle which makes my app useless. I'm stuck at and I don't know hot to proceed.

Screenshot Generator Sketch logic

I've looked in to

But all this is just a bit over my head. If any of you have any pointers on how to get it working, please let me know, otherwise just close the issue.

Tell me about your development environment.
Elvincth commented 3 years ago

Try this: https://www.npmjs.com/package/puppeteer-in-electron

JoeyDon commented 3 years ago

Hey mate, did you find a way to make it work?

mvaneijgen commented 3 years ago

@JoeyDon no still looking for a solution. I have the feeling I've tried everything, moved from puppeteer to puppeteer-core, puppeteer-in-electron changed builder from electron-builder to electron-packager, but all giving the same error.

I have the feeling I'm missing a part of the puzzle how to run a Node.js function from a Vue.js method, but I'm not seeing what it is.

Again, my app works great in development, but as soon as I build it anything that has to do with Node.js just doesn't work...

JoeyDon commented 3 years ago

Hey buddy @mvaneijgen , I just figured out something last night.

The below is electron's main.js (In your file might called something else, but this is where you will have createWindow(), app.on("ready", async () => {} etc)

//Catch clicktest
ipcMain.on("clicktest", async event => {
  console.log("clicktest from app.js");

  // .local-chromium needs to be at the same level with the app
  const browser = await puppeteer.launch({
    headless: false
  });
  const page = await browser.newPage();
  await page.goto("https://google.com");
  await page.screenshot({ path: "example.png" });
});

Then in the Vue component, I have

<v-btn @click="test">
          Button
</v-btn>

methods: {
    test() {
      console.log("test from helloworld component");
      ipcRenderer.send("clicktest");
    },
}

This is how I triggered Electron nodejs env's functions from Vue side.

My puppeteer is installed via npm install puppeteer, the binary executable of chromium is in the default location node/modules/puppeteer/.local-chromium

Now I am having issues for the the puppeteer location after the built. Going to work that out tonight.

Hope this still can help you mate.

mvaneijgen commented 3 years ago

Hey @JoeyDon cool! I'll be checking it out.

I thought I had the same issue with the Chrome executable that is why I moved to puppeteer-core this is just the API interface. For my app I can force users to have Chrome already installed on there machine, which most of the time is already the case (this also makes the app package a lot smaller).

You can than use the already installed Chrome by checking the Executable Path of the installed Chrome via chrome://version/ (I need to do some more research, but I think this is the same path for each OS (windows/mac/linux) or other wise have the user set the path by them selfs)

You would than use it like so:

  const browser = await puppeteer.launch({
    headless: false,
      executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
  });
JoeyDon commented 3 years ago

Hey @mvaneijgen, I doubt it would work across all os. I did something in another project month ago - I built windows with exe version binary for windows users, and macos version's chromium binary for mac users. Then putting the executable binary in the same directory with the Electron executable. The executablePath looks like: executablePath: "./chromium" (Not exactly, but in a relative path)

I think what you can do is using nodejs record user's input (where's the chromium), then pass that path/directory to executablePath. So whatever platform they are using, it should find the right Chrom app!

Good luck, this is so interesting workings...

mvaneijgen commented 3 years ago

Hey @JoeyDon I'm refactoring my code to use your solution. I've got your setup to work by adding the following to my .vuef file

import { ipcRenderer } from "electron";

export default {
  methods: {
    test() {
      console.log("test from helloworld component");
      ipcRenderer.send("clicktest");
  }
}

Than it think I've found the file you're talking about, for me it's src/main/index.js. There I've add the following code

import { app, BrowserWindow, Menu, ipcMain } from 'electron' // Add ipcMain
import puppeteer from 'puppeteer-core'; 

...
Rest of the code 
...

ipcMain.on("clicktest", async event => {
  console.log("clicktest from app.js");

  // .local-chromium needs to be at the same level with the app
  const browser = await puppeteer.launch({
    headless: false
  });
  const page = await browser.newPage();
  await page.goto("https://google.com");
  await page.screenshot({ path: "example.png" });
});

And it will log the "clicktest from app.js", but as soon as I load something from Puppeteer I get the following error

../screenshot-app/node_modules/puppeteer/lib/cjs/puppeteer/common/Page.js:707
          catch {
                ^

  SyntaxError: Unexpected token {
      at createScript (vm.js:80:10)
      at Object.runInThisContext (vm.js:139:10)
      at Module._compile (module.js:606:28)
      at Object.Module._extensions..js (module.js:653:10)
      at Module.load (module.js:561:32)
      at tryModuleLoad (module.js:504:12)
      at Function.Module._load (module.js:496:3)
      at Module.require (module.js:586:17)
      at require (internal/module.js:11:18)
      at Object.<anonymous> ../screenshot-app/node_modules/puppeteer/lib/cjs/puppeteer/common/Target.js:19:19)

Can you confirm this would be the correct file (src/main/index.js) and do you have a repo of your implementation I could take a look at?

PS: I ment that the path to Chrome is usually the same based on the OS, so all windows machines have the same path and all macOS machines have the same paths.

JoeyDon commented 3 years ago

https://github.com/JoeyDon/Electron-vue-puppeteer-boilerplate

@mvaneijgen Hey man, for sure. I just clean&extract&created this boilerplate for my future projects. In this repo, you should able to launch the puppeteer via the only button from UI. Also last night I finished how to relatively build it.

mvaneijgen commented 3 years ago

@JoeyDon thanks that really helped! I've finally got it working, in the process i've moved from Electron-vue (this repo) to https://nklayman.github.io/vue-cli-plugin-electron-builder/ and got it working in no time!

Repo can be found here https://github.com/mvaneijgen/screenshot-generator-app/tree/Vue-CLI

JoeyDon commented 3 years ago

Nice! Cheers man @mvaneijgen

kurohoan commented 3 years ago

@JoeyDon I am getting the following error, do you know what it is?

Unrecognized manifest key 'browser_action'.
  Unrecognized manifest key 'update_url'.
  Permission 'contextMenus' is unknown or URL pattern is malformed.
  Cannot load extension with file or directory name _metadata. Filenames starting with "_" are reserved for use by the system.
kurohoan commented 3 years ago

@JoeyDon Does anyone know? mvaneijgen

mvaneijgen commented 3 years ago

@kurohoan I would make a new issue or as me move to https://nklayman.github.io/vue-cli-plugin-electron-builder/ I had way more luck with getting puppeteer to work there.

kurohoan commented 3 years ago

@mvaneijgen Just a few minutes ago, I was able to solve this problem. It seems that the problem was caused by some old code left over from when I tried to use "puppeteer-in-electron". Thanks!

johns10 commented 3 years ago

I solved it like this: executablePath = puppeteer.executablePath().replace("app.asar", "app.asar.unpacked")