I'm developing an Electron application with Angular 2.
I followed this tutorial to initially setup the environment.
My setup is a bit more complicated but in general is very similar.
tsconfig.json
:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude": [
"node_modules",
"app/node_modules",
"dist"
]
}
systemjs.config.js
is just like in the tutorial as well as index.html
One of my modules (which resides somewhere inside the app
folder - app/*/*/*/module
) depends on node-ffi
. So I've added the necessary typings to typings.json
:
{
"globalDependencies": {
"core-js": "registry:dt/core-js",
"jasmine": "registry:dt/jasmine",
"node": "registry:dt/node",
"ref": "registry:dt/ref",
"ref-struct": "registry:dt/ref-struct",
"ffi": "registry:dt/node-ffi"
}
}
Now, the module tries to use ffi
like this:
import { DynamicLibrary, Library, types } from 'ffi';
export class CppProxy {
//Some code
}
Which is eventually transpiled to:
var ffi_1 = require('ffi');
//Utilize ffi_1 exported stuff
According to this article, there is a well-defined way for node.js
module lookup and according to this way it should find the node-ffi
module as node-ffi
resides in app/node_modules
. However, it doesn't. It only looks in app
folder for ffi.js
and obviously fails to find it.
My first attempt to fix it was adding ffi
entry to the map section of systemjs.config.js
, like this:
var map = {
'app': '.', // 'dist',
'@angular': 'node_modules/@angular',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'rxjs': 'node_modules/rxjs',
'node-binary': 'node_modules/systemjs-plugin-node-binary/node-binary.js',
'ffi': 'node_modules/ffi/lib/ffi.js'
};
It helped to load ffi
, but brought up new problems. ffi
itself depends on other modules:
var ref = require('ref')
var assert = require('assert')
var debug = require('debug')('ffi:ffi')
var Struct = require('ref-struct')
var bindings = require('./bindings')
So now the application failed to find these modules. I've tried to add some of them to the map too, but again it just solved one level of dependencies.
It doesn't seem right to me, require
shouldn't be looking only in app
folder and I don't feel like adding all the dependencies recursively to map section of systemjs.config.js
.
What am I doing wrong?
Upd:
There another question dealing with a pretty similar issue, but it is asking specifically about using require('remote')
.
I'm asking how can I use a Node.js
module resolution mechanism while still using System.js
as a module loader.
As Pace mentioned in one of his comments, System.js
overrides Node.js
's require
method and uses it's own resolution mechanism. This is why the require
method won't follow the Node.js
lookup mechanism. However there is a way to use the latter:
System.js
stores the Node.js
's require
in _nodeRequire
variable. So the way to load a module using Node.js
mechanism is to load it by
var module = System._nodeRequire('./path/to/module/')
Here is the discussion that helped me to come up with this solution.