How to use Native Node Modules in angular running in electron - node.js

Problem description:
This is not a duplicate of this Question. I'm not trying to access the electron module (I use a electron wrapper for angular to do this), I'm trying to use a npm native module in angular while running angular inside electron.
Original description:
I have an angular app which I run with electron (A new app, doesn't do anything yet).
To access Bluetooth I use noble and bleno but while they are working from within electron (to test this I added, noble = require('noble') to index.js in the electron folder) they do not work when I add for example noble to the app.compoents.js in angular.
This is my app.component.ts
import { Component } from '#angular/core';
import {ElectronService} from 'ngx-electron';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title: String = 'Colaboration room';
noble = require('noble')
}
I get this error:
WARNING in ./node_modules/bindings/bindings.js 76:43-53 Critical
dependency: the request of a dependency is an expression
While this is only a warning, the angular initial page is no longer displayed ( its empty).
Question:
How can I access node native modules in Angular (when running in electron)?
Additional Information:
Im using angulars default compiler webpack
The native modules are build against the node version from electron
with electron-rebuild.
I use the ngx-electron module to access the electron api from within angular, thus my guessing that I cant just access noble from within angular without some modification.
Folder structure
Solution attempt: (Since I'm new to node and Angular, I'm happy for code improvements !)
Since I use a wrapper to access electrons apis I had no problem with the electron module.
My real problem was that I didn't know how to access native node modules in angular.
One possible solution is to add the native npm module to webpacks script part (I did not test this yet).
The other solution is to use require in electrons main.js and set it as a
global variable.
const noble = require('noble');
global.sharedObj = noble;
You can then access this global variable using electrons api with the angular electron wrapper.
getBluetoothCentralPulgin(){
var es = new ElectronService();
return es.remote.getGlobal('sharedObj');
}

Related

Cannot resolve native module in package when building Angular CLI project

Background
I'm creating an application that allows users to interact with basic web controls which output controller events through emulated virtual controllers (so user slides a slider, and that manifests in the system as an axis being changed on a virtual controller). I'm building this as an Electron app which contains an Angular CLI project.
To get the virtual controller functionality I'm consuming a project which wraps native virtual controller functionality and exposes it for node applications. (node-ViGEmClient)
Issue
I've created the basic project and imported the required package. However, when I build the project with ng-build I get the following errors:
./node_modules/vigemclient/lib/DS4Controller.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\deskpad\node_modules\vigemclient\lib'
Tracking these errors down, they come from files like this:
Looking further into the package's structure, it should be looking for vigemclient.node in build/Release, and that file is indeed present:
I feel like there is some configuration I need to do in Angular (something to do with webpack?) but I don't know what it is. Can anyone point me in the right direction?
In case anyone wants to poke around with my (currently barebones) project, it's located here: DeskPad
Project Details
Node: v16.17.0
Angular CLI: v14.2.3
REPRODUCING
Create a new Angular CLI project:
ng new testProj
Install ViGEmClient package:
npm install vigemclient
Note: This seems to require libraries related to building C++ code which are prompted during the initial install for Node.
Add this line to tsconfig.json to allow synthetic default imports:
"allowSyntheticDefaultImports": true,
Reference the package in the default app component so that it is used:
import { Component } from '#angular/core';
import ViGEmClient from 'vigemclient';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'vigTestAngular';
client = new ViGEmClient();
}
Attempt to build the project with the command "npm run build"
Outcome: These errors should be produced:
./node_modules/vigemclient/lib/DS4Controller.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'
./node_modules/vigemclient/lib/ViGEmClient.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'
./node_modules/vigemclient/lib/ViGEmTarget.js:5:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'
./node_modules/vigemclient/lib/X360Controller.js:1:20-59 - Error: Module not found: Error: Can't resolve '../build/Release/vigemclient' in 'C:\Develop\WebDev\Node\vigTestAngular\node_modules\vigemclient\lib'
I was experiencing the exact same error with a native package. In my case this is also an Electron app with angular ~14.2 on Windows.
A friend pointed me to the problem: I was importing the native package from the angular web app code (renderer), but apparently when using native packages in an Electron application, they can only be imported in the Electron main process (main.ts).
Hope this helps!

Where do I find Angular CLI 7.3.9 default generated webpack settings file so I can build my overrides based on it?

I want to extend webpack building process for a project generated by Angular CLI v7.3.9.
I found out I have to use this tool:
https://github.com/just-jeb/angular-builders/tree/7.x.x/packages/custom-webpack
It seems a good solution, but unfortunately I can't find any example about extending existing Angular CLI config file.
I mean - I want to see what Angular CLI already generates for me, before I can think of correct overrides I should use in my custom builder override config. Being somewhat new to webpack, I need to learn what's already there to be able to figure out what I can adjust to avoid totally breaking the project.
Where do I find Angular CLI default generated webpack settings file so I can build my overrides based on it?
To be more specific, the problem is that building the project for production takes about 25 minutes. It is a large project with a few hundreds of form and grid components, and I see that current build process is spending about 20 minutes in ModuleConcatenationPlugin and 5 minutes in TerserPlugin without any serious load on the computer resources. I've heard ModuleConcatenationPlugin is being deprecated and thought that maybe I could use something better instead (UglifyJS ? optimization.concatenateModules ?), but at first I have to find out how Angular CLI uses it, so I can override it correctly.
technically in angular cli since v5 (as far as I know) you have ng eject which will give you access to webpack config.
You can use ngx-build-plus
Example:
Add ngx-build-plus: ng add ngx-build-plus
Add a file webpack.partial.js to the root of your (sub-)project:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
"VERSION": JSON.stringify("4711")
})
]
}
Use the global variable VERSION in your app.component.ts:
import { Component } from '#angular/core';
declare const VERSION: string;
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Version: ' + VERSION;
}
Start your application with the --extra-webpack-config switch pointing to your partial webpack config:
ng serve --extra-webpack-config webpack.partial.js -o
If your project is a CLI based sub project, use the --project switch too:
ng serve --project getting-started -o --extra-webpack-config webpack.partial.js
Update you can take a look at their doc and here is the full config

import, export and other es6 features not working when I choose express as integrated server-side framework in nuxt?

While installing nuxtjs using the following command as described in the documentation here
$ npx create-nuxt-app <project-name>
It will ask some questions:
Choose between integrated server-side frameworks:
None (Nuxt default server)
Express
Koa
Hapi
Feathers
Micro
Fastify
Adonis (WIP)
I choosed express and completed my installation. But I can't use import export and other es6 features inside nuxt.config.js.
in there documentation here the codes use import and export default
import hooks from './hooks'
export default {
router: {
base: '/portal'
}
hooks: hooks(this)
}
If I choose None (Nuxt default server) these codes works fine.
I am working on a front-end application, Back-end is independent node application. What is the difference between these integrated server-side frameworks ? How enable es6 in nuxt config?

how to use node module with es6 import syntax in typescript

I have a typescript project which has uses one of our node modules which normally runs in our front-end. We are now looking to use this module in node on our server.
The module uses es6 import syntax import { props } from 'module/file'
When I include a ref in typescript using either of the following methods
import { props } from 'module/file';
var props = require('module/file');
I get the following error from typescript
unexpected token 'import'
(function (exports, require, module, __filename, __dirname) { import
It's a big job to re-write the module, and I've tried using babel with babel-plugin-dynamic-import-node, as well as SystemJS.
The problem with these systems is that they are all asynchronous, so I can't import the module in the standard fashion, so I would need to do a whole bunch of re-write when we get to the point that I can use import natively in node.js.
I can't be the first person to have this issue, but I can't seem to find a working solution.
--------------- update with set-up -------------
In response to #DanielKhoroshko's response. The original module I am trying to import is normally packaged by webpack in order to use on the front-end. I am now trying to use this same module both server-side and in the front-end (via webpack on the front-end) without re-writing the imports to use require and without running webpack to bundle the js to use on the server.
To be clear, the original module is written in JS, our service which is trying to use this module is written in typescript and transpiled. When the typescript tries to require the old module which uses import, it is at this point that we are running into the issue.
------------------ some progress ---------------------------
I've made some progress by creating a file in my imported module which uses babel in node.js to transpile the es6 code into commonJS modules.
I've done this via
var babel = require("babel-core")
var store = babel.transformFileSync(__dirname + '/store.js', {
plugins: ["transform-es2015-modules-commonjs"]
});
module.exports = {
store: store.code
}
I can now get the store in my new node.js project. However, the submodules within the store.js file are not included in the export.
So where in my module, it says
import activities from './reducers/activities';
I now get an error
Cannot find module './reducers/activities'
How can I get babel to do a deep traversal to include the sub-directories?
unexpected token 'import' means you are running es-modules code in environment that doesn't support import/export commands. If you are writing you code in TypeScript it's important to transpile it first before building for the browser or use ts-node to run it server-side.
If you are using webpack there are loaders ts-loader and awesome-typescript-loader
What is your setup?
To describe the module you would need to create an activities.d.ts file in the same folder where the js-version (I understood it is called activities.js and containers a reducer) resides with the following (approx.):
import { Reducer } from 'redux';
export const activities: Reducer<any>;
#Daniel Khoroshko was right in many ways, I ended up finding #std/esm which lets you import es6 modules and worked find for fetching the included imports as well.
var babel = require('babel-register')({
presets: ["env"]
});
require = require('#std/esm')(module);
var store = require('ayvri-viewer/src/store');
exports.default = {
store: store
}
I had to run babel to get a consistent build from es6 to node compatible es5

Angular2 integration to core file system and node.js libraries

I am studying Angular2, Typescript and reactive programming.
I wrote a simple Typescript application on NodeJs which monitors a directory for changes (core OS and file system). In a single file.
Here it is https://github.com/maroshi/nodejs-directory-monitor/blob/master/app.ts
Now I want to add an interactive GUI to it using Angular2.
I want to integrate my directory monitor as service to Angular2 application.
The questions.
Is it architecturally safe/correct to allow Angular2 application to access the file system and OS (assuming it is a fancy NodeJs server)?
How to integrate NodeJs fs utility library into an Angular2 application.
I am using the Angular2 quickstart template from https://github.com/angular/quickstart.
I modified the app.component.ts
import * as FileSystem from 'fs';
import { Component, OnInit } from '#angular/core';`
#Component({
selector: 'my-app',
template: `
<h1>My First Angular 2 App</h1>
<p>Some FileSystem info: {{dirInfo}}</p>
`
})
export class AppComponent implements OnInit {
private proccesInfo: string;
ngOnInit(){
let tmpString: string[] = FileSystem.readdirSync('/home');
this.dirInfo = tmpString != null ? tmpString[0] : 'undefined';
}
}
This compiles well but fails to bootstrap with the following errors:
GET XHR http://localhost:3000/fs 404 (Not Found)
Error: patchProperty/desc.set/wrapFn#http://localhost:3000/node_moduleszone.js/dist/zone.js:769:27
Zone</ZoneDelegate</ZoneDelegate.prototype.invokeTask#http://localhost:3000/node_modules/zone.js/dist/zone.js:356:24
Zone</Zone</Zone.prototype.runTask#http://localhost:3000/node_modules/zone.js/dist/zone.js:256:29
ZoneTask/this.invoke#http://localhost:3000/node_modules/zone.js/dist/zone.js:423:29
Error loading http://localhost:3000/fs as "fs" from http://localhost:3000/app/app.component.js
Please advise about this exploration.
Note the tsconfig.json is the default tsconfig.json from the link above. Compiling for NodeJs
"module": "commonjs",
Thanks
Joy and happiness
Dudi

Resources