I created a CommonJS module in project A in the following way:
const { WebElement } = require('selenium-webdriver');
const { By } = require('selenium-webdriver');
class VlElement extends WebElement {
constructor(driver, selector) {
...
}
async getClassList() {
...
}
}
module.exports = VlElement;
In project B I use the following code:
const VlElement = require('projectA');
class VlButton extends VlElement {
constructor(driver, selector) {
super(driver, selector);
}
...
}
module.exports = VlButton;
When running the code, VLElemlent cannot be found.
It is in my package.json and I can see VLElement under projectB > node_modules > projectA.
What am I doing wrong with my exports?
Thanks in advance.
Regards
Make sure you have a projectB/mode_modules/package.json with a main which points to the file that defines/exports VlElement, like this:
"main": "path/to/file/with/VlElement.js",
When you call require('projectA'); this has to be resolved to a file inside projectA so that it can be evaluated to (and return) the exports from that file. The main entry in the package.json allows this (but defaults to index.js, so if you are using that you don't need package.json, probably, but you should have it anyway).
You can have multiple files with various exports, but remember require('projectA'); can still only return one thing, so the way to do that is usually to have an index.js which looks something like:
module.exports = {
'something': require('./something.js'),
'otherthing': require('./otherthing.js'),
'etc': require('./etc.js'),
};
Related
I'm trying to load a config inside a node module but I'm not sure which is a good practice to do it, I have this scenario:
A config my.config.js:
module.exports = {
content: [
'./src/**/*.{tsx,ts}',
],
}
Then I have a module cli.mjs is supposed to load it:
import arg from 'arg'
import { readFile } from 'fs/promises'
import path from 'path'
let configPath = './my.config.js'
const args = arg({
'--config': String,
'-c': '--config',
})
if (args['--config']) {
configPath = args['--config']
}
console.log(readFile(path.resolve(configPath), { encoding: 'utf8' }))
This will just return a simple string with my config inside, not a javascript object:
`
module.exports = {
content: [
'./src/**/*.{tsx,ts}',
],
}
`
How should I load my config in the right way?
I've saw basically everyone use configs like that in TypeScript or CJS projects, but it's hard to me see how and where they parse these configs, probably I'm missing some basic information about this?
I have a react app where I wanted to import a javascript file from a third-party library but file is mark with shebang #!/usr/bin/env node.
I found (e.g. here How to Configure Webpack with Shebang Loader to Ignore Hashbang Importing Cesium React Component into Typescript React Component) I can load file by overriding webpack configuration and adding a new loader shebang-loader (I also have tried shebang-loader2) but overriding webpack in react app is recommended only with #craco/craco so I added it to package.json and tried add loader to existing webpack-config.js.
I produced this lines of code. File craco.config.js:
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const shebangLoader = { test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/, loader: "shebang-loader" }
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};
It resolves problem with shebang and it ignores #!/usr/bin/env node but now I still get error
Module parse failed: Unexpected token (14:16)
File was processed with these loaders:
* ./node_modules/shebang2-loader/index.js
You may need an additional loader to handle the result of these loaders.
| const { getSourceLines, isErrorInLogLevelScope } = require("./utils");
| class NpmGroovyLint {
> "use strict";
| options = {}; // NpmGroovyLint options
| args = []; // Command line arguments
It looks like it does not recognise "use strict" line.
Can anyone put some suggestions what should be a problem ?
After few hours of investigation, I have finally come to a resolution. Firstly I have to say that there is no option to use NpmGroovyLint in react-like applications that run in browsers because after I resolved mentioned problem up here I figured that NpmGroovyLint uses node libraries as perf_hooks which are not available in a browser enviroment.
But I can post code that resolves the problem described in my question. It was needed to add a plugin to babel-loader named 'plugin-proposal-class-properties'. Here is my snipped of craco config. You can use it as a recipe occasionally.
const {addAfterLoader, getLoaders, loaderByName, removeLoaders, throwUnexpectedConfigError} = require('#craco/craco');
const throwError = (message) =>
throwUnexpectedConfigError({
packageName: 'craco',
githubRepo: 'gsoft-inc/craco',
message,
githubIssueQuery: 'webpack',
});
module.exports = {
webpack: {
configure: (webpackConfig, {paths}) => {
const {hasFoundAny, matches} = getLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasFoundAny) throwError('failed to find babel-loader');
const {hasRemovedAny, removedCount} = removeLoaders(webpackConfig, loaderByName('babel-loader'));
if (!hasRemovedAny) throwError('no babel-loader to remove');
if (removedCount !== 2) throwError('had expected to remove 2 babel loader instances');
//add plugin proposal class properties to existing babel loader
const propClassOptions = {...matches[1].loader.options, ...{plugins: ["#babel/plugin-proposal-class-properties"]}};
const propClassLoader = {...matches[1].loader, ...{options: propClassOptions}};
const babelLoaderWithPropClassPlugin = {...matches[1], ...{loader: propClassLoader}};
const shebangLoader = {
test: /node_modules\/npm-groovy-lint\/lib\/groovy-lint.js$/,
use: [{loader: 'shebang2-loader'}, {...{loader: require.resolve('babel-loader')}, ...{options: propClassOptions}}]
}
const {isAdded: babelLoaderWithPropClassIsAdded} = addAfterLoader(webpackConfig, loaderByName('url-loader'), matches[0].loader);
if (!babelLoaderWithPropClassIsAdded) throwError('failed to add ts-loader');
const {isAdded: babelLoaderIsAdded} = addAfterLoader(webpackConfig, loaderByName('babel-loader'), babelLoaderWithPropClassPlugin.loader);
if (!babelLoaderIsAdded) throwError('failed to add back babel-loader for non-application JS');
const {isAdded: shebangLoaderIsAdded1} = addAfterLoader(webpackConfig, loaderByName('url-loader'), shebangLoader);
if (!shebangLoaderIsAdded1) throwError('failed to add shebang-loader');
return webpackConfig;
},
},
};
I want to gather a lot of dependencies in one repository called, lets say module, so I only need to have one dependency for other repositories. Is that possible:
index.js in module repository to gather submodules
const submoduleA = require('submoduleA')
const submoduleB = require('submoduleB')
exports.submoduleA = submoduleA
exports.submoduleB = submoduleB
index.js in another module/library where I need all submodules, so I require module
const { submoduleA, submoduleB } = require('module')
Is that possible in any way? I know it's not a huge benefit, but would be nice to explain how all the submodules came about to be available.
What I want to be as transparent as possible is the module repository. Only requiring it to get all the other dependencies, but not getting in the way of normal syntax for those dependencies.
This example creates a fruit module that exports both the apple module and the banana module.
apple.js
function eatApple() {
return 'Yummy apple!';
}
module.exports = { eatApple };
banana.js
function eatBanana() {
return 'Yummy banana!';
}
module.exports = { eatBanana };
fruit.js
module.exports = {
apple: require('./apple'),
banana: require('./banana')
};
app.js
const fruit = require('./fruit');
console.log(fruit.apple.eatApple(), fruit.banana.eatBanana());
app.js (alternate)
const { apple, banana } = require('./fruit');
console.log(apple.eatApple(), banana.eatBanana());
I am running into a strange issue.
xxx.testFunction(); statement when executed errors out: TypeError: Cannot read property 'testFunction' of undefined, but works when executed with pre-condition if(xxx)..
Issue can be recreated in the following setup
index.js
const { Module1 } = require("./Module1"); //Commenting out this line fixes the issue
const { Module3 } = require("./Module3");
Module3.testFunction();
Module1.js
const { Module2 } = require("./Module2");
class Module1 {
static testFunction() {
console.log("testFunction")
}
}
module.exports = { Module1 };
Module2.js
const { Module3 } = require("./Module3"); //Commenting out this line also fixes the issue
class Module2 {
}
module.exports = { Module2 };
Module3.js
const { Module1 } = require("./Module1");
class Module3 {
static testFunction() {
//if(Module1) //If we merely check this first it works, but directly it doesn't
Module1.testFunction();
}
}
module.exports = { Module3 };
Moreover, if some of the require statements are removed, the function gets executed..
It also gets fixed when order of requires in index.js is changed.
If you're wondering why the extra requires, the reason is that they were needed for other code in the modules.. The above code is a stripped down version of the production code we found the issue in.
As per my understanding variables in nodejs modules are scoped to the module, and should not have any effect on other modules..
Can someone explain this behavior..
It seems that you have a circular dependency. to solve it you can require in the function itself as if you make Module3.js looks like:
class Module3 {
static testFunction() {
const { Module1 } = require("./Module1");
Module1.testFunction();
}
}
module.exports = { Module3 };
I want to import config.js which includes project's API keys. But It returns undefined.
//config.js
var config = {
fbAPI: "key"
}
-
//nuxt.config.js
const cfg = require('./config')
env: {
fbAPI: cfg.apiKey
}
Is this problem about run-time or am I missing something?
You missed modules.export at the end of config.js. The file should look following:
var config = {
fbAPI: "key"
}
module.exports = config;