How to use node_modules within Electron? - node.js

Using electron in combination with Angular2, Typescript and Electron I am try to find out how to use a node module package installed via npm.
The current problem is that I have to specify the location of the module like var module = require('./node_modules/xyz/lib/xyz.js'). But then electron does not find the dependencies of xyz, which are located within ./node_modules/xyz/node_modules/yyy and complains ./yyy.js can not be found.
The electron app structure
dist
├── angular2.dev.js
├── config.js
├── index.html
├── main.js
├── node_modules
├── package.json
└── app.js

UPDATE:
A similar question has been asked and my answer would most probably help you here:
If you don't append the path to your app node_modules directory under your app root to the NODE_PATH variable it is not going to work. So you need to do something like this:
export NODE_PATH=/PATH/TO/APP/node_modules
electron /PATH/TO/APP
When exporting NODE_PATH make sure that you provide an absolute path.
If electron cannot find modules when you require them normally, it's a sign that your package.json doesn't contain the modules as dependency even if the module is already available under your dist directory.
So make sure that you are inside dist directory and use
npm install --save xyz
note the --save flag!

The current problem is that I have to specify the location of the module like var module = require('./node_modules/xyz/lib/xyz.js')
You should be able to do var module = require('xyz'); If you have it locates in the relative path ./node_modules/ .... that you mentioned.

If you didn't include the modules in your package.json I found it easiest to just copy all of them to node_modules in your release. It's something like releases > ARCHITECTURE > resources > node_modules

According to electron's docs, set the nodeIntegration preference to true. Do this by adding
webPreferences: {
nodeIntegration: true
}
to your createWindow() function.

Related

Module not found outside of main directory

I have the following dir structure:
src/
app/
package.json
node_modules/
app.js
tools/
tool_A.js
tool_A.js requires the express package
app.js requires tool_A
I have defined the express package in the requirements for app/package.json and it was correctly installed in the node_modules folder.
The issue is that if I run app/app.js I still get the error:
Error: Cannot find module 'express'
Is there a way to make it search the modules starting from the root app, rather than the outside directory?
You can move the package.json to the root directory and use require("../tools/toolA.js") inside of app.js.
Alternatively you create a new package inside of tools and install express for that package:
.../src/tools> npm init
[...]
.../src/tools> npm i express
Given your description, it seems as though the first solution is more appropriate for your situation, but both theoretically work.
EDIT:
Theoretically, though it's anything but clean, you could also use require("../app/node_modules/express"), but that would break as soon as the path to the express module changes.

Linking npm package with equal devDependencies and peerDependencies breaks application in development using webpack

I have the following situation:
Frontend's package.json
{
"dependencies": {
"lib" : "1.0.0",
"foo" : "1.0.0"
}
}
lib's package.json
{
"devDependencies": {
"foo" : "1.0.0"
},
peerDependencies": {
"foo" : "1.0.0"
}
}
While I am developing with webpack-dev-server some Frontend I am linking the module foo with a npm link leading into this dependency tree of the Frontend:
├── foo#1.0.0
└─┬ lib#1.0.0
└── foo#1.0.0
Rather than having something like this:
├── foo#1.0.0
└── lib#1.0.0
I have already found out that webpack finds the module foo in my lib in its node_modules folder, because I defined this package as devDependencies for my unit tests. Now I have the package twice in my bundled source which leads into some bugs.
Question: How can I force webpack or npm to use the module foo of my parent (the Frontend) in my lib like the peerDependencies suggests?
I assume you have frontend and lib checked out locally in two different folders and linked lib to frontend using something like cd frontend && npm link lib. So you goal is to work (change code in two editors) on both packages at the same time, but also want to be able to run your compiler and unit tests in frontend and lib separately.
The answer is: you can't (that easy). That's because dependencies are resolved always first to the folder of the package first. That means, if you have foo installed in lib, it will always pick lib:foo, not root:foo.
The simplest solution for that is to not install lib:foo at all, or just remove it. It's using then root:foo, as you want. If you use npm link however, it installs first all lib's dependencies.
So for a one time build in frontend, you can simply remove that lib:foo package and then build. However, from the point of view of the lib package nothing will work as its dependencies got screwed.
The more robust solution is to install lib in root in a away that only installs the actual dependencies of foo that are not in peer/devDependencies
To do so, you can use npm-local-development at https://github.com/marcj/npm-local-development
It basically does the same thing as npm link, but works around the devDependency limitation by setting up a file watcher and syncs file changes automatically in the background, excluding all devDependencies/peerDependencies.
You install npm-local-development: npm i -g npm-local-development
You create file called .links.json in your root package.
You write every package name with its local relative folder path into it like so
{
"#shared/core": "../../my-library-repo/packages/core"
}
Open a console and run npm-local-development in that root package. Let it run in the background.
Disclaimer: I'm the author of this free open-source project.

How to refer to local installed Angular2 bundle rather than "npm install" every time?

While trying different tutorials of Angular2 I realised everytime I have do "npm install" for all packages (#angular, rxjs, core-js, systemjsm zone.js, lite-serever and list goes on).
So I am wondering rather then duplicating it each time If I could have them at one local and just refer from there, like node_module folder of project A could be referenced from all the packages mentioned in package.json of project B ?
Referring is not possible.
However there is a workaround to this, You can have your folder structure like this
Projects
├── node_modules
├── Project A
├── Project B
├── ├── project files
node when searching for local modules goes back a directory if it doesn't find the needed modules in the directory itself. So in this case a common node_modules will be accessible by all your projects
Warning : while using this, you have to be very cautious, because if you upgrade packages or something then it may be possible that one of your project which was compatible with package version 3.2.1 may not be compatible with 4.1.1. In above case your that project will go down and you'll go mad finding out the reason why this is happening.

When using a private git url for an npm module, how can I configure the consuming application to only use files from the module's dist folder?

I am using angular-cli for my angular application, but because angular-cli currently does not support use for creating a library, I used the seemingly most widely used git project to create my library: https://github.com/jvandemo/generator-angular2-library
My issue is that I don't want to publish my npm module library to the public directory. Instead I want to use the git url directly in my dependencies. During development, this works fine. I can run the build locally and run an npm link inside the "dist" folder and everything is dandy. However when I push my npm module code to git, and then run an npm install in the consuming project, I'm not sure how to set it so that my consuming project just looks inside the dist folder of the module and treats it as if it was the root of the module.
For example, in node_modules/my_private_module, my file structure looks like:
dist/
-- component1
-- compoennt2
-- my_module.metadata.json
-- my_module.d.ts
-- my_module.umd.js
-- index.d.ts
-- index.js
-- package.json
-- README.MD
package.json
README.md
All the files that my application is using are in the /dist folder, but I DO NOT want to specify "dist" in all my imports like
import { myComponent1 } from 'my_private_module/dist';
I want to be able to just specify
import { myComponent } from 'my_private_module";
As I do in development when I run an npm link in the dist folder.
Is there a way I can achieve this?
Thanks
In package.json for your module, in the root folder:
typings: 'dist/index.d.ts',
main: 'dist/index.js'
Remove the package.json in your dist folder.
When the package is resolved from import {...} from 'my_private_module', the module loader will look for a folder called my_private_module under node_modules, and look either for index.js which defines the exports, or within package.json for the main property - which in your case also points to index.js from the dist folder.
It is good practice to put package.json where you want your module to be found, and have main and typings point to index.js and index.d.ts.
I answered a similar question here and it seems relevant.
Basically, treat the generated library in the dist folder as it's own repo. In order to keep the git init files and folders, you tell ng-packagr to not destroy the destination when building. Then you push the changes to the library specific repo and use that as your package url in other projects.

Aurelia multi project build with Webpack

I'm using Aurelia and the new aurelia-webpack-plugin (2.0.0-rc.2). I want to use this as a "multiproject build":
.
├── project1
├── project2
├── project3
├── build
The three projects are all using Aurelia (same versions), but are independent. To avoid build script duplicates I extracted the webpack.config.js and several other scripts to the build folder. The projects are calling them via npm scripts from the package.json of the project. The working directory of this node-process is changed to the build folder before webpack is called.
Some relevant configs in my webpack config:
...
new AureliaPlugin({
includeAll: path.resolve(`${projectDir}/app/`),
viewsFor: `${path.resolve(projectDir)}/app/**/*.{ts,js}`
})
...
entry: {
main: "aurelia-bootstrapper"
},
resolve: {
modules: [`${projectDir}/app`, `${projectDir}/node_modules`, "node_modules"]
}
...
projectDir points to the specific root directory of the project.
The problem is now, that the GlobDependenciesPlugin inside the aurelia-webpack-plugin does not find the entrypoints (Main.ts) of the projects.
After debugging I found at least two reasons for this:
this.root in GlobDependenciesPlugin points to the current cwd of the node process, which is the build folder (there is no way to configure the value)
only the last "node_modules" folder in the modules array from the config is used for searching. The others are filtered out, cause of relative paths.
Is there a way to get this working with this shared build script structure?

Resources