Require() a module from a variable value - node.js

This works:
require('../../path/to/module')
This doesn't work
const cfg = '../../path/to/module'
require(cfg)
Prints an error in Chrome Dev Tools Console (the app is packed with browserify):
Uncaught Error: Cannot find module '../../path/to/module'
Why does this happen and is there any way I can load a local module using a variable?

Related

#loadable/server pass the whole stats JSON to eval('require')(modulePath)

I'm trying to setup SSR for react app with #loadable/components. I setup all based on docs with babel and webpack plugins. When I try to run node server.js it runs ok but when I open a browser and throws the following error (into node console):
TypeError [ERR_INVALID_ARG_TYPE]: The "id" argument must be of type string. Received an instance of Object
at validateString (internal/validators.js:118:11)
at Module.require (internal/modules/cjs/loader.js:1033:3)
at require (internal/modules/cjs/helpers.js:72:18)
at smartRequire (/Users/max/Documents/repos/app/node_modules/#loadable/server/lib/util.js:44:25)
at new ChunkExtractor (/Users/max/Documents/repos/app/node_modules/#loadable/server/lib/ChunkExtractor.js:181:50)
at renderer (webpack://app/./node_modules/#MYSCOPE/elm/dist/elm.esm.js?:3619:19)
at eval (webpack://app/./src/server.tsx?:64:90)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
code: 'ERR_INVALID_ARG_TYPE'
}
As you can see there is #MYSCOPE in the traceback which holds some of my internal packages (if it matters).
#loadable/server/lib/util.js is the following function:
And when I try to console.log(modulePath) on line 42 I see a whole stats JSON output which seems wrong and I should get a single module path (as I understand).
Any help?
I can share some specific parts of my configuration files if needed. Because I see my own package in console output seems like something is wrong with it's build (it works perfectly on the client-side with cjs build), but having full stats object as module path is very confusing.
UPD: Demo https://www.dropbox.com/s/9r947cgg4qvqbu4/loadable-test.zip?dl=0
Run
yarn
yarn dev:server
# go to localhost:3000 and see the error in console
to rebuild:
yarn
yarn dev:build-client
yarn dev:build-server
yarn dev:server # go to localhost:3000
The statsFile option passed to ChunkExtractor expects a path to the loadable-stats.json file, not the actual JSON content of it. By doing require('../loadable-stats.json'), webpack actually resolve the JSON during build time and assign it to the loadableJson variable.
You can change your loadableJson as follow:
import path from 'path';
const loadableJson = path.resolve(__dirname, '../bundle_client/loadable-stats.json');
This will solve the problem you had on your question. But, if you only do this, you will notice that you have another problem. Loadable by default assumes that your entry chunk name is main. This is not the case in your demo, as you have set the entry chunk name to be app instead.
entry: {
app: ['#babel/polyfill', './src/index.tsx']
},
To solve this, simply tell loadable about your entrypoints names by passing an array to the ChunkExtractor contructor as such:
const extractor = new ChunkExtractor({
statsFile: loadableJson,
entrypoints: ["app"], // name of your entry chunk
});
That's it, everything should now be working properly!
If it helps, I set up the demo on GitHub so you can easily see the changes I made here.

jest test with xmljs GLOBAL not defined

currently I am writing an App using
NodeJS v13.12.0
Jest 25.4.0
xmljs 0.3.2
typescript 3.8.3
ts-jest 25.4.0
This App should mimic a CalDAV Server. For this reason, I rely on the module xmljs, which is (after my research) the only module giving me a direct path method for finding properties in the XML.
In the node Container, the App runs fine without any errors. But When I start a test with Jest, the test fails with the error
ReferenceError: GLOBAL is not defined
at node_modules/xmljs/core.js:46:2
at Object.<anonymous> (node_modules/xmljs/core.js:176:3)
at node_modules/xmljs/XmlParser.js:3:11
at Object.<anonymous> (node_modules/xmljs/XmlParser.js:204:3)
I now know, that this error originates from the xmljs module trying to set the GLOBAL variable, which in NodeJS resolved to global. But this does not happen in jest.
My code works like following:
import XmlParser = require("xmljs");
/*
* data is the body of a PROPFIND request
*/
new XmlParser({ strict: true }).parseString(data, (err, xmlNode) => {
// omit err
xmlNode.path(["propfind", "prop"], true);
const propertiesObj: XmlNode[] = childs[0].children;
const properties: string[] = [];
Object.keys(propertiesObj).forEach(n => {
properties.push(n);
});
logger.silly("Returning properties: %O", properties);
});
Can anyone
Show me a module to use instead without requiring huge modifications of my code
Which supports a pure js implementation without using node-gyp (since it may be used on windows server)
Show me how to make a workaround in jest to spoof this GLOBAL variable being set in xmljs
I appreciate your help
You can set the value of GLOBAL in the setup of your tests. It seems that the GLOBAL variable is the deprecated form of the global in node.
In your jest.config.js file you can add a setup file through the setupFiles option:
module.exports = {
[...] // Other configurations
setupFiles: ['<rootDir>/define-deprecated-global.js']
};
And in the file define-deprecated-global you can define the GLOBAL variable as:
global.GLOBAL = global;

Error: Identifier 'Reader' has already been declared while bundling fstream with rollup.js

I'm new with configuring stuff with Rollup, I'm trying to configure a node CLI app to be bundled in a single cli.bundle.js file that would be executable with a simple node cli.bundle.js without needing to npm install anything before.
On a side note, we already have succeed in doing so with zeit/pkg, but we would rather note have all the nodejs executable bundled inside, so we are trying work with rollup instead of pkg.
The problem we encounter is that when going through the different node_modules of the application, rollup.js crash with error:
[!] Error: Identifier 'Reader' has already been declared
../../common/js-common/node_modules/fstream/lib/file-reader.js (7:4)
5: var fs = require("graceful-fs")
6: , fstream = require("../fstream.js")
7: , Reader = fstream.Reader
^
8: , inherits = require("inherits")
9: , mkdir = require("mkdirp")
Error: Identifier 'Reader' has already been declared
at error (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:5400:30)
at Module.error (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:9820:16)
at tryParse (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:9713:23)
at Module.setSource (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:10076:33)
at Promise.resolve.catch.then.then.then (/home/.../src/external-data/external-data-etl/node_modules/rollup/dist/shared/node-entry.js:12362:20)
While looking for this error with rollup, it seems people were having it more at execution time than at bundle time, so I have no clue of what I can do. This duplicated identifier is in a 3rd party code I don't control :(
Here is my rollup.config.js
Edit: I tried with the new #rollup/plugins to see if there were a fix in them, but I have still the same issue.
import commonjs from '#rollup/plugin-commonjs';
import resolve from '#rollup/plugin-node-resolve';
import json from '#rollup/plugin-json';
export default {
input: 'dist/index.js',
output: {
format: 'cjs',
file: './cli.bundle.js'
},
plugins: [
commonjs(),
resolve(),
json() // asked and added when parsing 'got' package imported by 'download' package
]
};
And our building process is :
transpile from typescript (src) to js (dist) with tsc
bundle (dist) app into single runnable file
We would rather not include babel or typescript plugin to transpile, to stay independant, and certainly the (dist) app is enough (as it was enough for zeit/pkg).
Is there something we are doing wrong ?
The Problem is your dependency it is not coded in the right way you will need to correct the code error they did.

TypeError: Cannot read property 'getAppPath' of undefined

We're using Electron "electron": "^5.0.2"
The code that is having the error is in the main process. It calls our backend services. I was trying to add a constant for the API path the same way we were including constants elsewhere (note: the solution here might be to use an environment variable). The issue is that electron is giving a error when it is trying to access the appPath() method. This same code works elsewhere in the app.
TypeError: Cannot read property 'getAppPath' of undefined
const {app} = require('electron');
const path = require('path');
const constants = require(path.join(app.getAppPath(), 'src/constants'));
When the browser window is created we're setting nodeIntegration to true
window = new BrowserWindow({
webPreferences: {nodeIntegration: true}
});
Try:
const app = require('electron')
app.remote.app.getPath()
If that doesn't work you should try checking if main.js is:
included in package.json
NOT being required by your frontend JS or index.html
of course, make sure electron is installed as a dev dependency
if you are running into while trying to packaging the app you should run the code that uses app in a conditional, app isn't available while packaging but will be available in the prod

Undefined method of global variable with Node.js in WebStorm

For complicated reasons, I have some Node.js code like this:
(util.js)
global.redis= require('redis').createClient(...);
(some other file.js)
const Util= require('./util.js');
global.redis.rpush(...);
In WebStorm 8, when I inspect the code it will recognize global.redis but will error saying unresolved function or method rpush.
redis is listed in the Node.js and NPM settings in WebStorm and I have Node.js globals enabled.
The code runs as expected though.
Has anyone run into this?

Resources