10

I know that Angular 2 is run on a web browser, which does not have access to the file system.

However, I'm using Electron as my front-end, and also running the app via electron:

"build-electron": "ng build --base-href . && cp src/electron/* dist",
"electron": "npm run build-electron && electron dist"

Therefore, I run it with npm run electron which at the very end runs electron dist.

Since I'm running through electron and not ng I would think that I should be able to access the filesystem. However, when I do:

import * as fs from 'fs'

I get an error:

ng:///AppModule/AppComponent_Host.ngfactory.js:5 ERROR TypeError: __WEBPACK_IMPORTED_MODULE_0_fs__.readFileSync is not a function(…)

Similarly, when I try: var fs = require('fs');

I get:

ng:///AppModule/AppComponent_Host.ngfactory.js:5 ERROR TypeError: fs.readFileSync is not a function

This is the call resulting in the error:

this.config = ini.parse(fs.readFileSync('../../CONFIG.ini', 'utf-8'))

Does anyone have any idea what's causing this?

Thanks.

Kevin
  • 979
  • 4
  • 10
  • 22

5 Answers5

8

Solved it by:

1) Eject webpack: ng eject

2) Add target: 'electron-renderer' to the module.exports array inside webpack.config.js

3) Require remote, since we're in the renderer, but fs is only available in the main process (Read more): var remote = require('electron').remote;

4) Require fs (this time using remotes implementation of require): var fs = remote.require('fs');

And now it works!

Kevin
  • 979
  • 4
  • 10
  • 22
  • 5
    If you are using the [ngx-electron package](https://github.com/ThorstenHans/ngx-electron) you can skip steps 1-3 and just require it via the ElectronService.Remote.require() function – D4rth B4n3 Apr 03 '18 at 11:20
  • 1
    `ng eject` Appears to have been removed. – khollenbeck Apr 01 '21 at 15:04
3

I am using

Angular CLI: 7.0.7
Node: 8.12.0
OS: win32 x64
Angular: 7.0.4

I tried the ng eject method it didn't work in my case, it is disabled by default and will be removed completely in Angular 8.0

Error message: The 'eject' command has been disabled and will be removed completely in 8.0.

It worked for me by creating a file called native.js in the src folder and insert the following:

`window.fs = require('fs');

Add this file to the angular-cli.json scripts array:

"scripts": [
    "native.js"
]

Add the following lines to polyfills.ts:

`declare global {
    interface Window {
        fs: any;
    }
}`

After that you can access the filesystem with:

`window.fs.writeFileSync('sample.txt', 'my data');`

credits

2

As I understand it, you build the application with Webpack.

You can expose all Node modules via the externals array in your webpack config.

module.exports = {
   "externals": {
      "electron": "require('electron')",
      "child_process": "require('child_process')",
      "fs": "require('fs')",
      "path": "require('path')",
      ...
   }
}

Since they are provided through the Webpack externals, one does not have to require them but use them with imports.

import * as fs from 'fs'

You can read more about this problem in my article.

Matthias Sommer
  • 1,070
  • 13
  • 28
  • Hi, I had to `ng eject` to get access to `webpack.config.js` - There is no `externals` array in `module.exports`. I have added it, with the 4 externals you have listed above (I removed the `...` of course). However, when I type fs or electron in to the console, I get `fs` | `electron` `is undefined`. Any idea? – Kevin Aug 15 '17 at 11:24
1

I'm late to the party but I also stumbled upon this problem recently. To the late comers, you can use ngx-fs

https://github.com/Inoverse/ngx-fs

Usage:

const fs = this._fsService.fs as any;
fs.readdir("\\", function (err, items) {
   if (err) {
      return;
   }
   for (let i = 0; i < items.length; i++) {
     console.log(items[i]);
   }
});
jokab
  • 671
  • 7
  • 14
0

I had the same problem and could solve it in an easier way:

  1. Just download this project as start, the 'require'-s are already in the webpack.config.js file (along with the integration of angular, electron and so on): https://github.com/maximegris/angular-electron

  2. import 'fs' into home.ts (or into any other component) as mentioned by @Matthias Sommer above:

import * as fs from 'fs'

  1. Use 'fs' :)
slashpm
  • 214
  • 2
  • 9