Importing external .js file to nuxt.config.js - javascript

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;

Related

Load a CJS module config inside another file

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?

Problem with parsing javascript file marked as Shebang

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;
},
},
};

Importing custom CommonJS module fails

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'),
};

Pass variable from webpack entries

I have multiple entries like in webpack docs
module.exports = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
let's say every of these files (index.js) is the same and only thing that change is other routes import.
I would create one file to keep DRY principle but I would need to pass something to actually know which router I want to import.
For example pageOne/index.js is
import Vue from 'vue'
import axios from 'axios'
import App from '../App'
import { store } from '../store';
import VueProgressBar from 'vue-progressbar'
import Router from '../routers/router';
import interceptor from '../../config/httpInterceptor.js';
console.log('in main', window.location.href)
const routerInstance = new Router('main');
routerInstance.createRouter()
.then(router => {
interceptor();
if (!process.env.IS_WEB) Vue.use(require('vue-electron'));
Vue.http = Vue.prototype.$http = axios;
Vue.config.productionTip = false;
Vue.use(VueProgressBar, {
color: 'rgb(255, 85, 0)', failedColor: 'red', thickness: '5px'
});
new Vue({
components: { App },
router,
store,
template: '<App/>'
}).$mount('#app');
});
and in pageTwo/index.js only line that change is from
const routerInstance = new Router('main');
to
const routerInstance = new Router('second');
so it's bad to have three same js files where only one line is changing but I don't know how to refactor it so it's reusable. I would need to pass to file information about which page is being loaded for example it would be something like this
module.exports = {
entry: {
pageOne: './src/pageOne/index.js?page=main',
but now when in index.js I log
console.log('in main', window.location.href)
it is
http://localhost:9080/#/
So I'm not able to require different router basing on this. I need some other solution.
Edit
#Daniel Lizik in comment section suggested to use environment variable. He also said to use webpack config in order to set it. Considering that I would refactor my entry object to following:
module.exports = {
entry: {
pageOne: './src/index.js',
pageTwo: './src/index.js',
pageThree: './src/index.js'
}
};
I would need to configure webpack somehow to set environment variable right after webpack imported file.
Webpack probably loop over this object and import files. Right after it read this line
pageOne: './src/index.js',
I would need to set some env variable to 'pageOne' so when index.js is executed it can check this variable and import correct router.
However I have no idea how I could achieve that.
You don't need to pass the query param in the entry point configuration. You have to pass it from the browser. Then you can parse the query param and pass it to new Router(). You can use urijs node module for parsing the query param in a clean way.
import URI from "urijs";
...
const uriObj = new URI(url);
const page = uriObj.query(true)[page] || "main";
const routerInstance = new Router(page);
In your browser you enter the url with the page param like http://localhost:9080/page=second

Fetch requirejs.config from Gruntfile

Is there any way to import a requirejs config in to my grunt config file? Right now I have to keep two identical versions, one in app/main.js and one in my Gruntfile.js:
module.exports = function(grunt) {
// can I import app/main.js requireConfig here?
var requireConfig = {
paths: {
jquery: 'lib/jquery'
// etc...
}
};
});
My main.js looks something like this:
requirejs.config({
paths: {
jquery: 'lib/jquery'
// etc...
}
});
define(['app'], function(app){
app.start();
});
You can use standard module pattern which supports different type of module system like following.
Your requirejs config file like this
amd-config.js
(function(factory) {
if (typeof define === 'function' && define.amd) {
// Register as an AMD module if available...
define('amd-config', [], factory());
} else if (typeof exports === 'object') {
// Next for Node.js, CommonJS, browserify...
module.exports = factory();
} else {
// setting browser global when none of the above are available
window.amdConfig = factory();
}
}
(function() {
var amdConfig = {
baseUrl: 'scripts',
paths: {
//Paths here
}
};
return amdConfig;
}));
In gruntfile you can just require like any other module.
var requireConfig = require('amd-config');
Include it normally like you do in index.html with script tag before app.js
and then in app.js use it like following.
requirejs.config(window.amdConfig);
define(['app'], function(app){
app.start();
});
PS: There are cleaner way of including it in app.js.
More cleaner than second, create global variable require and include the script before requirejs script. requirejs checks if there is global variable with name require containing object. If its there, it is used as a config object. So you dont have to call requirejs.config yourself.
You can require the file like you require other files. In that case it will be treated as a require module and you will receive the object in require callback. call your requirejs.config like following.
```
require(['amd-config'], function(amdConfig){
requirejs.config(amdConfig);
require(['app'], function(app){
app.start();
});
});
```
A simpler approach you could use, if you are using grunt to build the project. You can simply use:
options:{
mainConfigFile: "path/to/Config.js"
}
granted you need to use:
https://github.com/gruntjs/grunt-contrib-requirejs
You can try something like this:
function getRequireConfig(requireFilePath) {
var config;
var configFileContent,
_require;
_require = require;
require = {
data: {},
config : function (configParam) {
this.data = configParam;
},
get : function () {
return this.data;
}
};
configFileContent = readFileSync(requireFilePath);
eval(configFileContent);
config = require.get();
require = _require;
return config;
}
What it is doing is:
Override require definition to a custom implementation
Load require config file
Eval it so that the config function of custom implementation will be
called Get the config object from data

Categories