How to import Electron in angular 2 using angular cli - node.js

I'm trying to prototype an Electron app using Angular 2 (configured with the latest webpack-based angular cli) for the gui, but I'm stuck since I don't get how to import Electron api in my angular2 components. Specifically I want to be able to open a new BrowserWindow at the click on a button in the ui... so:
<button type="button" (click)="openNewWindow()">
open
</button>
and in my component:
openNewWindow() {
let appWindow = new BrowserWindow({width: 800, height: 600});
appWindow.loadUrl('http://www.google.com');
}
but... how can I import BrowserWindow?!
By using:
import { BrowserWindow } from 'electron';
I get a "no module error" and by following the answer to this question: Webpack cannot find module 'electron' I get:
syntax error near unexpected token ( var electron = require('./')
What should I do?
ps. by running "electron ." without the BrowserWindow import the app is working properly

Run the command npm install electron #types/electron
Then import it normally using
import { ipcRenderer } from 'electron'.
If you run into any problems, try to run npm eject, a webpack.config.js will be generated, add "target": "electron-renderer" at the top of module.exports

Set this in index.html
<script>
var electron=require("electron");
</script>
Add this line in typings.d.ts file
declare var electron: any;
Use inside the component like this example:
const {ipcRenderer, clipboard} = electron;
clipboard.writeText('Electron is ready!!');

I tried to work with angular-cli and Electron and was not able to make them to work together. It's the reason why I started the following project: https://github.com/osechet/angular-tour-of-heroes-webpack
It integrates Angular 2 with webpack and Electron. It's based on the Angular 2 tutorial (with unit tests). When running Electron in dev mode (npm run start.desktop), it livereloads the sources.

To complete the answer given by chaouechi souhail.
As I understand his answer aims to solve the situation where the angular app is directly embedded in the electron app.
If for some reason you are using two separate projects whereof one is the electron app which embeds the other as a web app using one of electron's webview components you might find the following approach helpful aswell.
In your electron app you'll have something like
<webview id="webview" src="http://localhost:4200/" nodeintegration></webview>
In your angular project you
install the electron nodejs module, ie npm install electron . The types module mentioned by chaouechi might suffice, I do not know.
you eject the webpack config through ng eject
in webpack's config (webpack.config.js) you define electron as an external module such that webpack does not attempt to build it into the ng app, extend the exports as below
module.exports = {
//...
externals: {
electron: "require('electron')", // tell's webpack how to import the electron module within your angular app after being packed
//...
},
//...
}
Now, in your ng components, it should be possible to include electron classes as follows: import { remote } from "electron";

Update as of 3/20/2021
Angular CLI v11
This information was pretty hard to find so I'm answering in as many places as I can that has outdated info.
There are a few simple steps.
Add #angular-builders/custom-webpack (this saves you from ejecting angular's current webpack file which we don't really want to touch).
npm i -D #angular-builders/custom-webpack
Modify your angular.json to use the package you installed and a custom webpack file that you create (more detailed instructions on the package's readme)
Make your custom webpack file look like this:
module.exports = {
target: "electron-renderer",
};
literally that's it. You don't need anything else in your webpack file and you should be all set to use electron as you expect. No need to create your own typings file or anything.

Related

NPM modules with Sails.js, and more specifically: using Dropzone.js with Sails.js

I've been using Sails.js for a year or so off and on, but when it comes to adding an NPM module I'm a bit confused. Specifically, I'm trying to use Dropzone with Sails for multi-file uploading and am having quite a bit of trouble figuring out how to go about the whole thing. I've installed via npm install --save dropzone and I'm stuck on what do now.
For example, Dropzone's documentation has the following:
// If you are using JavaScript/ECMAScript modules:
import Dropzone from "dropzone";
// If you are using CommonJS modules:
const { Dropzone } = require("dropzone");
let myDropzone = new Dropzone("#my-form");
myDropzone.on("addedfile", file => {
console.log(`File added: ${file.name}`);
});
I'm assuming I'd be using the CommonJS module method, but I cannot figure out where to put it and get the Dropzone constructor to be recognized.
Any ideas?

Dynamic require not supported in React Native

I have just tried to use wasm bindings in a react-native project. But the wasm bindings require access to node modules like fs so I used rn-nodeify as a work-around to get the React Native representation of fs and to be able to use require. That worked fine but I think that the wasm bindings are incompatible with react native, because I get the error Dynamic require defined at line 10; not supported by Metro. The error is talking about the line below:
//line 10
const { TextDecoder, TextEncoder, inspect } = require(String.raw`util`);
The bindings I'm using are from this package #iota/identity-wasm
Steps to reproduce
If you want to reproduce this issue I have created a sample RN Project that throws the error by startup.
git clone https://github.com/JonasHiltl/DigitalIdentityNodeified.git
cd ./DigitalIdentityNodeified
npm install
npx react-native start
npx react-native run-android
I'm interested to know what exactly a dynamic require is and if it's possible to replace the dynamic require with a normal one.
Sadly you cannot use require dynamicly in react-native :/
You will have to make a require for every single thing you will need.
Check out this for example:
Dynamic require not supported in React Native

issues with imports on modularized apollo server

i have a fully working modularized apollo server on nextJS (based on this article https://www.apollographql.com/blog/modularizing-your-graphql-schema-code-d7f71d5ed5f2/ ) basically im doing an Array of my typedefs and merging the resolvers using the merge function from lodash... so far so good... this feed a function makeExecutableSchema and this schema is going to the server... and it works great...
the problem is im trying to move the server outside nextJS... and when i do try to create a new project and yarn init or npm init... install the dependencies, and try to copy paste all my schema files to the new npm init project ALL my imports are messed up, and i start getting all this errors like:
in nextJS i have (this one simply works in nextJS):
import { merge } from "lodash";
in the new node project it says merge couldnt be found in lodash...
or the module is commonJS and it cannot do named imports...
or if i do an import using require it says ReferenceError: require is not defined, i think this one should be due to node expecting to run this on a browser but i have no idea how to specify this wont run on a browser since it's simply a js file which intends to modularized the apollo schema...
i just dont understand why all the import sentences work just fine in Next but when im starting the apollo server in plain node every import is giving so many errors... i have fixed some by adding the extension at the end of the filename im importing (thing that was not necessary in nextJS) or by adding "/index" at the end of the package being imported...
Is there a way to make the imports behave like in Next??? but in a new nodeJS project?
Any help or orientation would be GREATLY appreciated
The answer was:
Use Babel, install with NPM or YARN
"#babel/core"
"#babel/node"
"#babel/preset-env"
add the .babelrc file to the root directory of the project:
{
"presets": ["#babel/preset-env"]
}
to run the main file use a script in package.json like:
"start": "nodemon --exec babel-node index.js"
and this will allow to execute modern JavaScript :D

Loading Nodejs Module at runtime in electron app

Currently I am playing around with electron using vue-cli-plugin-electron-builder along side a simple vue project. This is the project https://github.com/nklayman/vue-cli-plugin-electron-builder .
vue create my-project
cd my-project
vue add electron-builder
npm run electron:serve
My goal is to add a simple plugin-like architecture. The app serves only base functionality but can be extended with "plugins". Those plugins therefore are not included in the built, but will be loaded at runtime by electron. I would prefere when those plugins just behave like node modules ( module.exports = ) with its own dependencies ( probably with a package.json file inside ). I would locate those plugins at app.getPath('userData') + '/Plugins.
I looked at a few approaches on how to tackle this problem :
1. Using Nodejs vm module
First, I tried using Nodejs vm module to read and execute a script from an external file, all at runtime. It works great so far, although I would not be able to use external dependencies inside those loaded scripts. If I want to use external dependencies inside the plugin scripts, those dependencies must have been included in the electron build beforehand. Somehow defeats the whole purpose of having plugins ... only vanilla js + nodejs base modules would be possible .
2. using global.require
I saw this solution in another SO answer.
Using node require with Electron and Webpack
Webpack/electron require dynamic module
They say to use global.require but it throws an error saying global.require is not a function. The solution looked promising first, but somehow I can't get it to work.
3. simply use require
Of course I had to try it. When I try to require an external module from a non-project location it won't find the module, even if the path is correct. Again, the path I am trying to locate the module should be at app.getPath("userData"), not in the projects root directory. When however, I locate the plugins inside the root directory of the project it gets included in the built. This again defeats the purpose of having plugins.
Goal
So far, I haven't found a viable solution to this. I simply want my electron app to be extendible with basic node modules at runtime ( following a pre-defined schema to simplify ) . Of course there is atom, made with electron, using their own apm manager to install and load plugins, but this seems way to overpowered. Its enough for me to only have plugin files located locally, to have a public "marketplace" is no goal. Also, it's ok if the app has to reload / restart to load plugins.
Any ideas ?
After more and more research I stumbled over 2 packages :
https://www.npmjs.com/package/live-plugin-manager
https://github.com/getstation/electron-package-manager
both integrating npm to programmatically handle package installation at runtime. I settled for live-plugin-manager for now since its better documented and even allow package installation from local file system.
Pro
I was able to integrate the system out-of-the-box into a vanilla electron app. Works like a charm.
Cons
.I was not able to use it inside a vue electron boilerplate (like the one I said I was using in OP), since webpack is interferring with the require environment. But there sure is a solution to this.
Update : I was able to get it to work eventually inside a webpack bundled electron vue boilerplate. I accidentally mixed import and require . The following code works for me using live-plugin-manager
// plugin-loader.js
const path = require('path');
const { PluginManager } = require('live-plugin-manager');
const pluginInstallFolder = path.resolve(app.getPath('userData'), '.plugins');
const pluginManager = new PluginManager();
module.exports = async (pkg) => {
// installs pkg from npm
await pluginManager.install(pkg);
const package = pluginManager.require(pkg);
return package
}
// main.js
const pluginLoader = require('./plugin-loader');
pluginLoader("moment").then((moment) => {
console.log(moment().format());
})
This will install "moment" package from npm during runtime into a local directory and load it into the app, without bundling it into the executable files.

How to Import nodes modules in react native

hope you're doing well.
I'm new at react native and i'm stuck with a problem while trying to import a node module.
I need to create an app that will get orders from the API of a Wordpress Website with WooCommerce.
I first created a project with the command create-react-native-app picking then npm install. It's creating a structure like this in the project folder named picking:
node_modules
App.js
app.json
App.test.js
etc....
Then I installed the package woocommerce-api with npm install woocommerce-api --save (https://www.npmjs.com/package/woocommerce-api). This package allow me to do request to the WooCommerce API easier.
I want to not put the config to the WooCommerce API in the App.js, so I created a folder src and a folder woocommerce with a file api.js (should I write it with the first letter in uppercase ?) in it and I added import Api from 'picking/src/woocommerce/api'; in my App.js.
So now the structure is
node_modules
src
-- woocommerce
-- api.js
App.js
app.json
App.test.js
etc....
The problem is that I can't achieve to import the WooCommerceAPI module from woocommerce-api, no matter what I set in path to get the module.
There is the file api.js at the moment :
import WooCommerceAPI from '../../woocommerce-api';
var Api = new WooCommerceAPI({
url: 'http://localhost/mysite',
consumerKey: 'ck_xxxxxxxxxxxxxxxxxxxxxxxxxx',
consumerSecret: 'cs_xxxxxxxxxxxxxxxxxxxxxxxxxxx',
wp_api: true,
version: '/wc/v2',
queryStringAuth: true
});
export default Api;
And I get the error :
Unable to resolve module '../../woocommerce-api' from etc ...
I can't find what is the problem and why this is not working. If you could help me on this, it would be very nice.
Have a nice day everyone :)
EDIT: I changed the line for the import to import WooCommerceAPI from 'woocommerce-api'; and I got a new error : Metro Bundler has encountered an internal error, please check your terminal error output for more details, but there is nothing in the terminal except Failed building JavaScript bundle.
EDIT2: I downgrade node from 9.4 to 8.0.0 and restart the project. I got the same error but in the terminal i now get this in yellow/orange : Problem checking node_modules dependencies: Unexpected end of JSON input
Okay, so I find a workaround. In fact, the import is working. For some reason that i don't know, this is the npm package that is not working and make the app crash.
So I removed the package woocommerce-api and I create a file in src/woocommerce called woocommerce-api.js, then I copied the content of this https://github.com/minhcasi/react-native-woocommerce/blob/master/WooCommerceAPI.js that is the same as the one in the npm package and I pasted it in my woocommerce-api.js. I import it in my api.jsfile and "voilĂ " !
Seems to work fine.
As you install woocommerce-api in your project there is no need to place the location like ../../woocommerce-api.
just change ../../woocommerce-api to woocommerce-api and your project should work.

Resources