fs module fails when integrating Electron into Ang

2019-04-08 12:59发布

I have some trouble integrating Electron. When I use it as described in this blog post, everything works. Problems start when I want to use import Electron (electron.remote) to use it in Angular2 service to let the app using the desktop features like system dialogs and file system access.

I get the following error when loading the app, in electron/index.js which is included in webpack bundle:

Uncaught TypeError: fs.existsSync is not a function (index.js:6)

The file looks quite simple:

var fs = require('fs')
var path = require('path')

var pathFile = path.join(__dirname, 'path.txt')

if (fs.existsSync(pathFile)) {
module.exports = path.join(__dirname, fs.readFileSync(pathFile, 'utf-8'))
} else {
throw new Error('Electron failed to install correctly, please delete node_modules/' + path.basename(__dirname) + ' and try installing again')
}

//////////////////
// WEBPACK FOOTER
// ./~/electron/index.js
// module id = 609
// module chunks = 2

The funny thing here is that another built-in module path has no problem in the same piece of code. When I look in electron app's dev tools I can see the expected path methods as well as the two static properties (delimiters). But when I look what is the fs object I can see it is just an empty Object with the prototype corresponding with NodeJS 6.

I import the electron API in an Angular service file service.ts which is very trivial:

import * as electron from 'electron' ;
import {Injectable} from '@angular/core' ;

@Injectable()
export class Electron {
getRemote(): any { return electron.remote ; }

It is never called, though, only imported in app.module.ts. I created it just to see possible compilation errors.

As for the environment, I installed typings in devDependencies and then installed dt~node and dt~electron (in typings/global/electron/index.d.ts there is some problem in that tsc it does not recognize Promise<any> which I had to replace manually by any to make compilation of the electron main file possible).

As long as I do not want to use the electron API (electron.remote) everything works fine, with some minor quirks in angular, irrelevant to this topic. But as soon as I try to import electron, I get this strange error.

Any idea how to overcome this or where to look for the cause? Why one built-in nodejs module, path, is imported without problems but, in the same file, require() of another built-in module, fs, returns something that is not fs?

Versions (process.versions in the renderer process):

ares:"1.10.1-DEV"
atom-shell:"1.4.14"
chrome:"53.0.2785.143"
electron:"1.4.14"
http_parser:"2.7.0"
modules:"50"
node:"6.5.0"
openssl:"1.0.2h"
uv:"1.9.1"
v8:"5.3.332.47"
zlib:"1.2.8"

The NodeJS version where I run the compilation is 6.9.3 x64 Windows.

1条回答
爷、活的狠高调
2楼-- · 2019-04-08 13:49

As @ccnokes pointed it out in this answer:

Webpack brings its own require which clobbers node.js' require, so when you require a node.js core module that webpack can't resolve to one of your files or dependencies, it throws. (You can see in your stack trace that it includes webpack_require. That's because webpack rewrites all requires to webpack_require so that it uses it's own internal node.js-esque system). Webpack is built for the web/browsers so it doesn't play well with node out of the box.

I would suggest using ngx-electron that appear to be somewhat not maintained (last commit was a year ago) but still works as a charm and will let you use a lot of Electron abilities in Angular (like in this answer's comment).

You could also try this workaround by Vjekoslav Ratkajec:

In your index.html

<script>  const electron = require('electron');  </script>

Then in any of your Typescript files:

declare const electron: any;

The downside is that you won't enjoy Typescript support.

You also could use webpack-target-electron-renderer to tell wich require to import with electron or webpack but I haven't tried it or this boilerplate if you want to start your project from scratch !

Hope it'll help

查看更多
登录 后发表回答