Kaffiend / electron-angular-ngrx

An Angular (6x) Electron seed featuring @angular/cli, @ngrx/platform, and Typescript. Complete with HMR workflow
MIT License
39 stars 10 forks source link

Native modules #17

Open greg9504 opened 5 years ago

greg9504 commented 5 years ago

Hello, I found a few problems with native module support. I've managed to get it all working but it's required a bit of work.

For my testing I cloned the repo (I'm on Windows), built and made sure everything ran OK, then attempted to add better-sqlite3 npm install better-sqlite3

First problem is that better-sqlite3 needs to be rebuilt against Electron node headers. So we need electron-builder npm install --save-dev electron-builder

Now we need a way to force our native modules to be rebuilt. Taking what was done in repo: https://github.com/maximegris/angular-electron I added a postinstall to package.json

"scripts": {
    "postinstall": "npm run postinstall:electron && npx electron-builder install-app-deps",
    "postinstall:electron": "node utils/cli-renderer",
    ....

then run npm install to force the rebuilding of the native module. From now on anytime a new package is installed the postinstall is automatically run and any native modules will get built against Electron.

At this point you should be able to use the native module but ONLY in the main process. If you attempt to require it in a renderer process (in an Angular service or Component) the module will not load with error

"MODULE_NOT_FOUND" Error: Cannot find module 'better-sqlite3'

And the directories that are searched are:

"...installdir\electron-angular-ngrx\node_modules\electron\dist\resources\default_app.asar\node_modules"

"...installdir\electron-angular-ngrx\node_modules\electron\dist\resources\node_modules"

This took me the better part of a day to figure why this was happening... it's best summed up here: https://github.com/chentsulin/electron-react-boilerplate/issues/374#issuecomment-247203032

Basically if you start electron with a .js file that is NOT in the same directory as the package.json file things go astray wrt relative paths.

The 'fix' for now was to edit tsconfig.electron.json and change

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "../../dist/electron",
    ...

to

{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "outDir": "../../",
    ...

and then change

"electron:serve": "wait-on http-get://localhost:4200/ & npm run electron:tsc && electron ./dist/electron/main.js",

to

"electron:serve": "wait-on http-get://localhost:4200/ & npm run electron:tsc && electron .",

Now the directories searched are:

"...installdir\electron-angular-ngrx\node_modules" "...installdir\node_modules" "...installdir\node_modules" "...installdir\node_modules" "D:\node_modules"

with the module being found under the first one.

Greg.

greg9504 commented 5 years ago

Forgot to add that I had to remove references to bootstrap for now, as the electron-builder would throw errors (Error: Unresolved node modules: jquery, popper.js), for possible work arounds see https://github.com/electron-userland/electron-builder/issues/2529

ON EDIT - just looking at my other changes:

So using better-sqlite3 as an example, to use the native module would look like:

import * as Database from 'better-sqlite3';
// then instead of doing
// const db = new Database(args...);
// do
const dataBase: typeof Database = window.require('better-sqlite3');
const db = dataBase(args...);

The maximegris repo creates a service to hide the window.require("native-module") part.

To be honest I'm not sue why this works. From a 'coding' point of view I much prefer not having to do the window.require and just import then new the object, which is how it worked with the https://github.com/colinskow/angular-electron-dream-starter repo. It would be nice to figure out how the default paths used for require are produced.

Greg.

Kaffiend commented 5 years ago

@greg9504 Fantastic research and documentation. Ill take a look at this, this weekend. There are some things i want to try with extending the CLI for a more natural integration and should help with this.