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

Support for Electron and Externals #4227

Closed
gregvis opened this issue Jan 25, 2017 · 22 comments
Closed

Support for Electron and Externals #4227

gregvis opened this issue Jan 25, 2017 · 22 comments

Comments

@gregvis
Copy link

gregvis commented Jan 25, 2017

Please provide us with the following information:

OS?

All OSes

Versions.

1.0.0-beta.26

Repro steps.

clone my electron starter project
git clone https://github.com/gregvis/angularcli-electron.git
cd into it
npm i
npm start
error in console "Uncaught TypeError: fs.existsSync is not a function"

The log given by the failure.

"Uncaught TypeError: fs.existsSync is not a function"

Mention any other details that might be useful.

In app.component.ts, i have this code:
import { Component } from '@angular/core'; const remote = require('electron').remote; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app works!'; constructor() { remote.dialog.showOpenDialog({ title: 'Electron Works!' }); } }

The remote.dialog.showOpenDialog does a call to a nodejs fs function. In order to fix this, I need the require('electron') to be ignored by webpack.

There are 2 ways to do this. In "webpack-build-common",
1.
target: 'electron-renderer'
This basically adds a bunch of 'externals' that webpack ignores for packing. You can see the code here:
https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js#L70-L185

This does fix the issue, however, there are cases where I would like to be able to add other externals, such as the npm package "drivelist" which uses a "child_process" to get a list of drives connected to the system. It doesn't work properly if it is bundled by webpack.

So in order for me to use both electron AND drivelist, i added the following to "webpack-build-common"

externals: { 'electron' : 'commonjs electron', 'drivelist' : 'commonjs ' + nodeModules + '/drivelist' }

So ideally, I need a way to add target and/or externals to the webpack build.

@filipesilva
Copy link
Contributor

I know this isn't the answer you want to hear, but this isn't a usecase we want to support right now.

I know webpack itself supports many targets but on the CLI, at the moment, we don't. For your usecase I would say using a custom webpack config would be better.

You can still use the CLI as a generator, and use https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack to get AoT builds.

@vilarone
Copy link

vilarone commented Jan 27, 2017

I maked a repository with a temporaly solucion and example in https://github.com/vilarone/ng2-electron-builder 2 month ago. Its use a folked angular-cli with target parameter in angular-cli.json

@albkn
Copy link

albkn commented Mar 18, 2017

I recently stumbled upon this problem myself, electron renderers written using angular-cli does not work with native Node.js modules such as fs.

A temporary hack that works for me is to have another JS file responsible to attaching your external modules to the renderer's global window object:

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

Once you have included that JS file in the app[0].scripts list in .angular-cli.json, window.fs and window.electron will be available throughout your renderer processes without getting destroyed by the CLI.

@Litarvan
Copy link

Litarvan commented Jun 4, 2017

After using the @morcerf solution, i also needed, to pass compilation, to put in my typings.d.ts :

/// <reference path="../node_modules/electron/electron.d.ts"/>
declare var electron: Electron.AllElectron;

@chriseugenerodriguez
Copy link

@morcerf can you be more clear with your solution? Like where to add it with syntax to angular-cli.json?

@Litarvan
Copy link

@premiumwd For me, creating a modules.js file with morcerf's code, and adding it at the top of my scripts of my index.html, worked.

@albkn
Copy link

albkn commented Jun 24, 2017

@premiumwd yep of course, hope this can be more helpful.

For example, your project needs the fs and os node packages which has some native code.

You will need to create a file (for example it is named native.js, but name can be anything):

// Content of native.js
window.fs = require('fs');
window.os = require('os');

Once you that file, you can add this part into your .angular-cli.json:

{
    "$schema": ...,

    "project": ...,

    "apps": [
        "root": ...,

        "scripts": [ "./native.js" ],   // <- The important part, include your file as a global dependency

        ....
    ],

    ...
}

alternatively you can also do a <script>require('./native.js')</script> in your HTML file as @Litarvan has suggested, that should work too.

Once you have done 1 of these approaches, window['fs'] and window['os'] will be available as a global object throughout your renderer's JS.

Note that I haven't migrated my electron code to Typescript. So if you use Typescript, you might have to do some type declaration to make it happy as @Litarvan also suggested above.

@dolanmiu
Copy link

dolanmiu commented Aug 9, 2017

I have created a plugin/extention for @angular/cli, which enables building electron apps on an angular cli project with a simple nge build command!

https://github.com/dolanmiu/ng-cli-electron

@giiyms
Copy link

giiyms commented Aug 26, 2017

Adding these to your polyfills.ts will stop the typescript compiler from complaining

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

@dolanmiu
Copy link

@guyms https://media.giphy.com/media/26uf2JHNV0Tq3ugkE/giphy-facebook_s.jpg

😂

@Eshva
Copy link

Eshva commented Nov 30, 2017

I've found some ugly but workable solution here
I managed to access electron API by adding following to index.html:

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

Then in TS you can declare electron and access any method/property:

declare var electron: any;

After that you can do such things:

electron.shell.openExternal(authenticationUri);

@Eshva
Copy link

Eshva commented Dec 3, 2017

The only workable solution I've found here: Angular 2 + Electron + Angular-CLI

I managed to access electron API by adding following to index.html:

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

Then in TS you can declare electron and access any method/property:

declare var electron: any;

This is very hackish solution and doesn't solve problem of os.platform() being browser.

@rahulsharma841990
Copy link

@Eshva it works. But still some electron features are not working like dialog etc.

@fontenele
Copy link

@Eshva it works!!!! Now i cant use plugin sql.js, its writes the same sqlite file after modify local db to sync (export) with sqlite file, that prevents the app to refresh infinitily.

@mu88
Copy link

mu88 commented Mar 27, 2018

@Eshva you saved my day!!!

@ghuser
Copy link

ghuser commented May 31, 2018

I added this inside app.component.ts and I can now access fs and electron.

const fs = (<any>window).require("fs");
const electron = (<any>window).require("electron");

@lehtiniemi
Copy link

lehtiniemi commented Jun 15, 2018

I'm also getting this with mammoth .docx HTML converter (https://github.com/mwilliamson/python-mammoth):

WARNING in ./node_modules/mammoth/node_modules/sax/lib/sax.js
Module not found: Error: Can't resolve 'stream' in 'C:\Users\My Name\Koodaus\project-name\node_modules\mammoth\node_modules\sax\lib'

ERROR in ./node_modules/mammoth/lib/docx/docx-reader.js
Module not found: Error: Can't resolve 'path' in 'C:\Users\My Name\Koodaus\project-name\node_modules\mammoth\lib\docx'

@ompurwar
Copy link

@ghuser it worked! thanks!

@dashkan
Copy link

dashkan commented Jun 29, 2018

All,

I spent a couple of days reviewing the cli codebase. The build system is very extensible. I ended up creating a new npm package named ng-electron-devkit that extends angular 6 build system to support electron-renderer. My goal is to add support for electron main process and packaging electron assets in the build pipeline in future updates.

This is not a hack to the CLI. You can target both electron-renderer and the browser and have completely different build settings!

Check it out

@marco6
Copy link

marco6 commented Jul 10, 2018

I am currently using a slightly different approach and it worked for me.

In your typings.d.ts :

interface RequireFunction {
	(id: string): any;
	(id: 'fs'): typeof import('fs'); 
	(id: 'electron'): typeof import('electron'); 
	// Add here whatever you need
}

declare var window: Window;

interface Window {
	require: RequireFunction;
}

To me this is clean enough: no stange scripts in your html, no imported JavaScript, no third-party libraries. And the modules listed in your typings.d.ts get typed, too.

I'm attaching a screenshot of the result/usage.

https://ibb.co/mDNmNT

PS: I tested it with typescript 2.9 and angular 6+ only.

@saurabBajgain
Copy link

I added this inside app.component.ts and I can now access fs and electron.

const fs = (<any>window).require("fs");
const electron = (<any>window).require("electron");

Uncaught TypeError: window.require is not a function
at Module../src/app/app.component.ts (app.component.ts:9)
at webpack_require (bootstrap:78)
at Module../src/app/app.module.ts (app.component.ts:21)
at webpack_require (bootstrap:78)
at Module../src/main.ts (main.ts:1)
at webpack_require (bootstrap:78)
at Object.0 (main.ts:12)
at webpack_require (bootstrap:78)
at checkDeferredModules (bootstrap:45)
at Array.webpackJsonpCallback [as push] (bootstrap:32)

Angular CLI: 6.0.8
Node: 10.15.0
OS: win32 x64
Angular: 5.0.3
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package Version

@angular-devkit/architect 0.6.8
@angular-devkit/build-angular 0.12.2
@angular-devkit/build-optimizer 0.12.2
@angular-devkit/build-webpack 0.12.2
@angular-devkit/core 0.6.8
@angular-devkit/schematics 0.6.8
@angular/cdk 5.0.0-rc.1
@angular/cli 6.0.8
@angular/material 5.0.0-rc.1
@ngtools/webpack 7.2.2
@schematics/angular 0.6.8
@schematics/update 0.6.8
rxjs 5.5.2
typescript 2.4.2
webpack 4.28.4

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests