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

cannot use native modules? #38

Closed
boneskull opened this issue Jun 27, 2019 · 25 comments
Closed

cannot use native modules? #38

boneskull opened this issue Jun 27, 2019 · 25 comments

Comments

@boneskull
Copy link

When running npm run dev, I'm getting this from node-serialport:

The module <path/to/bindings> was compiled with NODE_MODULE_VERSION 70. This version of Node.js requires NODE_MODULE_VERSION 72

I've tried installing electron and using electron-rebuild, upgrading all my dependencies, and trying everything I could from the official tutorial but still get this message. Honestly, I have no idea how Electron is getting launched using npm run dev...

@saltyshiomix
Copy link
Owner

saltyshiomix commented Jul 4, 2019

@boneskull

Thank you for your issues!

If you can, please let me know more details?

Your error message is apparently the difference between NODE_MODULE_VERSION 70 and 72.

@saltyshiomix
Copy link
Owner

@boneskull

I have never been to create electron apps with custom native node binary, but I believe it is possible to do that.

@boneskull
Copy link
Author

will get back with steps to reproduce—maybe it’s something obvious, since i’m not too familiar with electron.

@hadeeb
Copy link
Contributor

hadeeb commented Jul 6, 2019

I have never used electron-rebuild, but electron-builder always worked for me.

try electron-builder install-app-deps, if you haven't already.
Or
add it as a postinstall script

@saltyshiomix
Copy link
Owner

From console, the command below is checking your native dependencies are always matched electron version:
(as @hadeeb said)

$ npx electron-builder install-app-deps

@saltyshiomix
Copy link
Owner

@boneskull

Nextron v5 is out!
Still same error?

$ npm install --global nextron@latest

@boneskull
Copy link
Author

> electron-builder install-app-deps

  • electron-builder  version=21.0.15
  • loaded configuration  file=/Users/boneskull/projects/nextron-test/electron-builder.yml
  • rebuilding native dependencies  dependencies=@serialport/bindings@2.0.8 platform=darwin arch=x64
  • install prebuilt binary  name=@serialport/bindings version=2.0.8 platform=darwin arch=x64
  • build native dependency from sources  name=@serialport/bindings
                                          version=2.0.8
                                          platform=darwin
                                          arch=x64
                                          reason=prebuild-install failed with error (run with env DEBUG=electron-builder to get more information)
                                          error=prebuild-install info begin Prebuild-install version 5.3.0
    prebuild-install WARN install prebuilt binaries enforced with --force!
    prebuild-install WARN install prebuilt binaries may be out of date!
    prebuild-install info looking for cached prebuild @ /Users/boneskull/.npm/_prebuilds/73d12e-bindings-v2.0.8-electron-v70-darwin-x64.tar.gz
    prebuild-install http request GET https://github.com/node-serialport/node-serialport/releases/download/v2.0.8/bindings-v2.0.8-electron-v70-darwin-x64.tar.gz
    prebuild-install http 404 https://github.com/node-serialport/node-serialport/releases/download/v2.0.8/bindings-v2.0.8-electron-v70-darwin-x64.tar.gz
    prebuild-install WARN install No prebuilt binaries found (target=5.0.6 runtime=electron arch=x64 libc= platform=darwin)

added 1221 packages from 632 contributors and audited 24062 packages in 27.001s
found 0 vulnerabilities

It's obviously trying to use some prebuilt binary, which won't work. I get something like this:

The module '/Users/boneskull/projects/nextron-test/node_modules/@serialport/bindings/build/Release/bindings.node' was compiled against a different Node.js version using NODE_MODULE_VERSION 43. This version of Node.js requires NODE_MODULE_VERSION 72. Please try re-compiling or re-installing the module (for instance, using `npm rebuild` or `npm install`).

I'm not sure how to make electron-builder do what I want here... it's not very helpful.

Trying the recommended electron-rebuild--which builds from source--results in the app displaying the original error:

The module '/Users/boneskull/projects/nextron-test/node_modules/@serialport/bindings/build/Release/bindings.node' was compiled against a different Node.js version using NODE_MODULE_VERSION 70. This version of Node.js requires NODE_MODULE_VERSION 72. Please try re-compiling or re-installing the module (for instance, using `npm rebuild` or `npm install`).

What version of Node.js should I be running these commands with? Should it matter?

@boneskull
Copy link
Author

boneskull commented Jul 14, 2019

The steps I took here:

  1. Use npx nextron init to create a new thing
  2. Run npm install in resulting dir
  3. Install my dependency (which uses serialport as a dependency, containing the native module)
  4. Add import statement to source code
  5. Run npm run dev which shows the first error
  6. I had to add electronVersion: 5.0.6 to electron-builder.yml
  7. npx electron-builder install-app-deps results in the first paste above
  8. First error shown above (again) in app (no change)
  9. Run npx electron-rebuild; completes successfully, but results in the second error shown above

@boneskull
Copy link
Author

OK, I think I have an idea of what the problem is. The problem is that (correct me if I'm wrong) next is running its dev server using node. The native module is built using electron-rebuild or electron-builder or any other various commands; it only works in electron, which has NODE_MODULE_VERSION=70.

Node.js, OTOH, has NODE_MODULE_VERSION=72 since 11.x. It has no version 70. Electron has its own NODE_MODULE_VERSION numbers, as does Node.js, and they not the same (reference).

However, you can use ELECTRON_RUN_AS_NODE=1 nextron dev to run next as electron (somehow) and get a different runtime problem:

[ wait ]  starting the development server ...
[ info ]  waiting on http://localhost:8888 ...
Defining routes from exportPathMap
[ ready ] compiled successfully - ready on http://localhost:8888
[ wait ]  compiling ...
[ ready ] compiled successfully - ready on http://localhost:8888


 DONE  Compiled successfully in 167ms                                                                                                                                                                    10:03:06 PM

/Users/boneskull/projects/nextron-test-js/app/background.js:115
  const userDataPath = electron__WEBPACK_IMPORTED_MODULE_0__["app"].getPath('userData');
                                                                    ^

TypeError: Cannot read property 'getPath' of undefined
    at Module../main/background.js (/Users/boneskull/projects/nextron-test-js/app/background.js:115:69)
    at __webpack_require__ (/Users/boneskull/projects/nextron-test-js/app/background.js:21:30)
    at /Users/boneskull/projects/nextron-test-js/app/background.js:85:18
    at Object.<anonymous> (/Users/boneskull/projects/nextron-test-js/app/background.js:88:10)
    at Module._compile (internal/modules/cjs/loader.js:815:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:677:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:609:12)
    at Function.Module._load (internal/modules/cjs/loader.js:601:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:880:10)

Evidently, this confuses webpack too much about where the packages live...

As much as I'd like to get this working, I'm gonna have to throw in the towel.

@saltyshiomix
Copy link
Owner

saltyshiomix commented Jul 17, 2019

@boneskull

Mmm..., this is a complex problem.
If you are ok, could you tell me example repository which has this error?

@saltyshiomix
Copy link
Owner

@boneskull

I found the solution:

$ npx electron-rebuild -f -v <electron-version> -w serialport

@saltyshiomix
Copy link
Owner

The steps I took here:

  1. Use npx nextron init to create a new thing
  2. Run npm install in resulting dir
  3. Install my dependency (which uses serialport as a dependency, containing the native module)
  4. Add import statement to source code
  5. Run npm run dev which shows the first error
  6. I had to add electronVersion: 5.0.6 to electron-builder.yml
  7. npx electron-builder install-app-deps results in the first paste above
  8. First error shown above (again) in app (no change)
  9. Run npx electron-rebuild; completes successfully, but results in the second error shown above

These steps were so helpful :)
Thanks,

@boneskull
Copy link
Author

@saltyshiomix Your solution isn't working for me, so let me try again from the start. Thanks for following up... I had given up on it

@boneskull
Copy link
Author

@saltyshiomix see https://github.com/boneskull/nextron-serialport for example

@boneskull
Copy link
Author

boneskull commented Jul 24, 2019

(import 'serialport' was added to home.jsx in that project)

In a dev environment, Next.js runs a server in a node process, right? It's not working because the node process can't run the native module which was compiled for Electron via electron-rebuild. I can think of two possible strategies to address (there may be more!):

  1. use ELECTRON_RUN_AS_NODE=1 npm run dev, which results in a webpack error:

     /Users/boneskull/projects/boneskull/nextron-serialport/app/background.js:115
       const userDataPath = electron__WEBPACK_IMPORTED_MODULE_0__["app"].getPath('userData');
                                                                         ^
    
     TypeError: Cannot read property 'getPath' of undefined
         at Module../main/background.js (/Users/boneskull/projects/boneskull/nextron-serialport/app/background.js:115:69)
         at __webpack_require__ (/Users/boneskull/projects/boneskull/nextron-serialport/app/background.js:21:30)
         at /Users/boneskull/projects/boneskull/nextron-serialport/app/background.js:85:18
         at Object.<anonymous> (/Users/boneskull/projects/boneskull/nextron-serialport/app/background.js:88:10)
         at Module._compile (internal/modules/cjs/loader.js:839:30)
         at Object.Module._extensions..js (internal/modules/cjs/loader.js:851:10)
         at Module.load (internal/modules/cjs/loader.js:701:32)
         at tryModuleLoad (internal/modules/cjs/loader.js:633:12)
         at Function.Module._load (internal/modules/cjs/loader.js:625:3)
         at Function.Module.runMain (internal/modules/cjs/loader.js:904:10)
    

    We might be able to figure out what's going on here and fix it.

  2. Use npm's almost-entirely-undocumented "package aliases" functionality, which would allow two versions of serialport to be installed. Compile one for node, and the other for electron, and somehow tell the dev server to use the node one

@boneskull
Copy link
Author

Given the difficulties here, I'm thinking that Next (or Nuxt) isn't a great choice for what I'm doing, given its architecture.

@saltyshiomix
Copy link
Owner

@boneskull

I sent a PR which shows how to use SerialPort :)

boneskull/nextron-serialport#1

@boneskull
Copy link
Author

@saltyshiomix's PR fixes the issue!

I found that electron-rebuild isn't necessary, though. See boneskull/nextron-serialport@c16805e

TL;DR: configure electron-builder to have option buildDependenciesFromSource = true

@boneskull
Copy link
Author

I guess I can put that config in electron-builder.yml instead, but same idea.

@boneskull
Copy link
Author

@saltyshiomix Can you think of any way to make serialport run in the renderer process? I imagine this would work fine in a production build, but maybe not w/ Next.js' development server...

@saltyshiomix
Copy link
Owner

saltyshiomix commented Jul 26, 2019

@boneskull

Sorry I'm not familiar to serialport, does it support browser?
If so, you can use serialport in the renderer process(it is just a web client process).

If we want to use server side scripts in the electron architecture, we must use the server scripts in the main process, not the renderer process.

@boneskull
Copy link
Author

boneskull commented Jul 27, 2019

serialport is a Node.js module. It can't be used in the browser.

There's nothing special about serialport other than it contains a native module (specifically, @serialport/bindings).

If we want to use server side scripts in the electron architecture, we must use the server scripts in the main process, not the renderer process.

I don't think that's right. As of Electron v5, using new BrowserWindow({webPreferences: {nodeIntegration: true}}) enables use of Node.js modules. IIRC prior to this version, it was enabled by default.

For example, I can do this in an index.html loaded by BrowserWindow#load:

<!DOCTYPE html>
<html>
	<body>
		<div class="container">
			<ul id="ports"></ul>
		</div>
	</body>
	<script>
		(async () => {
			const ports = await require('serialport').list();
			ports.forEach(({comName}) => {
				const li = document
					.getElementById('ports')
					.appendChild(document.createElement('li'));
				li.textContent = comName;
			});
		})();
	</script>
</html>

Result:

image

I think because in nextron, the Next.js development server is actually serving the pages used by the renderer process, this is not possible to do. Does this sound right?

@saltyshiomix
Copy link
Owner

@boneskull

I think you are right.
But I could not find another way for searching 3 hours, sorry.

@saltyshiomix
Copy link
Owner

I think it's the best way to use server scripts whithin the main process if we want to use Next.js as the renderer process.

@boneskull
Copy link
Author

That's also the conclusion I've come to. thanks for helping!

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

3 participants