How make const variable available to other file - javascript

I have a JavaScript / Node based project. Within the server.js file (which starts the Node http server), I have a const based variable defined called redisClient. I have another directory called controllers, with about 5 controller files (all *.js files).
How can I gain access to the redisClient const instance from my controller based files?

You could export the redis client that has been created in the server.js (either through module.exports or export const).
You could create another file that creates the redis client and import it into both server.js and the controllers.
You could pass the redis client into the controllers as a parameter.

I don't use node very much... but I believe you can export anything you want from any file - and then require that file in other places and access what you exported on the export object. Depending on what you are doing, - you may want that redisClient to live somewhere else and be used in the server.js... not sure.
Read this: http://openmymind.net/2012/2/3/Node-Require-and-Exports/
I hope that helps. : ) I use es6/es2015 imports and exports in most of my work.

Related

Use configuration file to initialize a node_modules library

I made a react component library that I would like to use in multiple projects.
I need to use different variables depending on the environments, for this reason I was thinking of using an initialization file (eg: my-library.init.js) in the host app that exports a config variable, but I don't know how to make the library read this variable from host app.
the file should look like this:
export const config = {
envs: {
S3_URL: 'https://my.dev.url.org'
ENV: 'dev'
}
}
Any help will be appreciated
Tahnk you

ember js access environment from ember-cli-build in the vendor file

In my ember-cli-build.js file I'm importing a vendor library called new-relic by using app.import('vendor/new-relic.js'), I would like to pass a parameter called env to the new-relic vendor file and use it in the new-relic.js file. I tried doing
app.import('vendor/new-relic.js', { env: 'production' });
When I try to console log env in the vendor file, it says undefined. Is there any way to pass the env to the vendor file?
When you app.import a vendor file, it does not get executed in the same node environment as ember-cli-build.js at build time, but rather on your user's browser at run time, so there is no way to pass the environment as a parameter.
However, Ember automatically makes the environment available in the browser in the following manner. This is how you can set it on the window object in an initializer:
import ENV from 'config/environment';
export function initialize() {
window.env = ENV.environment;
}
export default { initialize };
This will make the environment available on the window object as soon as your ember app boots. If your vendor file accesses it then, this will work.
However, this may not be early enough. You may need the env variable to be available as soon as the the new-relic.js file is read by the browser. In order to handle such a use case, you may need to use the contentFor hook in an addon. There is a nice addon already written for you to do this: ember-cli-content-for-config. With it, you can add this to your index.html:
<script>
window.env = '{{content-for 'config.environment'}}';
</script>
See the README for the addon here: https://github.com/bmac/ember-cli-content-for-config
You will also need to alter new-relic.js to look for the env variable in the global namespace (window object).

Enviroment variables react

I have a react component which in development will redirect to a localhost url but in production to a different url. In my backend I have the same situation and there i solved it with a package called dotenv. I was wondering how someone would do this in a react front-end.
export default withRouter(function Login(props) {
useEffect(() => {
if(localStorage.getItem('jwt')){
props.history.push('/dashboard');
}
})
const handleLogin = () => {
window.location.href = "http://localhost:8000/auth/google";
}
return (
<LoginView handleLogin={handleLogin}/>
)
})
You can use dotenv to add environment variables to react as well. During app deployment(in the build process) the environment variables must be replaced with the corresponding URLs (as this is the most frequently encountered use case in front-end applications). This can be done while configuring the build process.
Here is an example using Webpack https://medium.com/#trekinbami/using-environment-variables-in-react-6b0a99d83cf5
The whole idea here is to create a file (called just .env) filled with
your environment variables. To prevent people from finding out your
local database password is the same one you use for every single one
of your accounts on the internet , I urge you to add the .env file to
your .gitignore. Your front-end code will refer to the same
environment variable (process.env.API_URL) on both environments
(development/production), but because you defined different values in
your .env files, the compiled values will be different.
I would suggest having a separate .env file for the react app as it should not be accidentally served with the website.
Create React App has a module(built around the node dotenv module) you can use for adding custom environment variables
https://create-react-app.dev/docs/adding-custom-environment-variables/
The environment variables are embedded during the build time. Since
Create React App produces a static HTML/CSS/JS bundle, it can’t
possibly read them at runtime. To read them at runtime, you would need
to load HTML into memory on the server and replace placeholders in
runtime, as described here. Alternatively you can rebuild the app on
the server anytime you change them.
Its depend on how you are using react.
If you are using react-script, you can go will above solution(https://create-react-app.dev/docs/adding-custom-environment-variables/).
But if you are using webpack, try to use DotenvPlugin in place of dotenv module (https://webpack.js.org/plugins/environment-plugin/).
In my opinion, pls don't follow method 1 use in medium link, as env should not be push on git but package.json need to be done.

Using imports, how does the server com with the client?

I'm confused by how we import [Publish] functions and [Meteor Methods] that reside under /imports/server to the Blaze client (either in /imports/client/ui or even just under app-name/client).
The classic way, is to just use the publish or meteor method, and everything is consumed by the client without imports. But if everything resides under the /imports directory (including the Blaze templates) how does that work? Are there real examples out there?
Illustration:
// imports/server/publishing/test.js
Meteor.publish('publish.test', function() {
if (this.userId) return TestCollection.find({});
return self.ready();
});
// imports/client/ui/test.js
import { Template } from "meteor/templating";
import { ReactiveDict } from "meteor/reactive-dict";
import { Mongo } from 'meteor/mongo';
import TestCollection from '../../imports/collections/test.js';
import "./test.html";
Template.Test.onCreated(function() {
this.state = new ReactiveDict();
this.autorun(() => {
const subscription = this.subscribe('publish.test');
...
}
});
});
How do server side only stuff make its way to the client in the new imports syle of developing?
UPDATE1:
Reponding to Answer1, would something like this work? Also, does the client look okay?
// app-name/imports/server/trades-pubs.js
// This code only runs on the server
Meteor.publish('trades', function tradesPublication() {
return Trades.find({},{sort: {timestamp: -1}, limit: 1000});
});
// app-name/imports/server/trades-methods.js
Meteor.methods({
// Only on server
'trades.importFromFiles'() {
fs = require('fs');
const path = "/home/daemmon/trades_data/";
var files = fs.readdirSync(path);
...
}
});
// app-name/server/main.js
import '../imports/server/trades-methods.js';
import '../imports/server/trades-pubs.js';
Is this all that's needed to get a publish methods to the client and server side meteor methods avaialbe to the client?
// imports/client/ui/test.js
import { Template } from "meteor/templating";
import { ReactiveDict } from "meteor/reactive-dict";
import { Mongo } from 'meteor/mongo';
import TestCollection from '../../imports/collections/test.js';
import "./test.html";
Template.Test.onCreated(function() {
this.state = new ReactiveDict();
this.autorun(() => {
const subscription = this.subscribe('trades');
...
}
});
});
UPDATE2:
you might want to consider importing app-name/imports/server/trades-methods.js somewhere in your client code as well, i.e. in a file like app-name/client/main.js
I thought we could not import server code on the client? If I wanted to import trades-methods.js for example, I'd have to move it to app-name/imports/api or something outside /imports/server.
UPDATE3:
Reading the Meteor Guide, I'm confused by this paragraph:
.
To fully use the module system and ensure that our code only runs when we ask it to, we recommend that all of your application code should be placed inside the imports/ directory. This means that the Meteor build system will only bundle and include that file if it is referenced from another file using an import (also called “lazy evaluation or loading”).
Meteor will load all files outside of any directory named imports/ in the application using the default file load order rules (also called “eager evaluation or loading”). It is recommended that you create exactly two eagerly loaded files, client/main.js and server/main.js, in order to define explicit entry points for both the client and the server. Meteor ensures that any file in any directory named server/ will only be available on the server, and likewise for files in any directory named client/. This also precludes trying to import a file to be used on the server from any directory named client/ even if it is nested in an imports/ directory and vice versa for importing client files from server/.
These main.js files won’t do anything themselves, but they should import some startup modules which will run immediately, on client and server respectively, when the app loads. These modules should do any configuration necessary for the packages you are using in your app, and import the rest of your app’s code.
.
Doesn't this mean for example that if there is a file inside the [/app-name/imports/server] directory, this file can NOT be imported in the client here [/app-name/client/main.js]?
.
For example I could NOT do the following:
Module inside the imports /server directory:
/app-name/imports/server/server-test.js
Module inside the imports /client directory:
/app-name/imports/client/client-test.js
.
Entry point in Meteor client:
/app-name/client/main.js
// => Would NOT work?
import { ServerTest } from "../../imports/server/server-test.js";
// => Would work?
import { ClientTest } from "../../imports/client/client-test.js";
UPDATE4:
Your wording here on your Update2:
Within the /imports folder, there are no special folder names - so you
can import a file from /imports/server in your client side code.
... is incorrect according to the author of this portion of the Meteor Guide.
First of all, since publications and methods are referenced only by their string name, they don't need to be imported in the code that subscribes to them or calls the functions. When doing Meteor.subscribe('publication') Meteor will try to find a publication named publication in the server, and subscribe to it. Same works with Meteor methods.
However, when using the /imports folder, your publications and methods need to be imported somewhere in server code so that Meteor loads them at all. The best practice to do this is to place a file somewhere in the imports folder, like /imports/startup/server/index.js (as recommended by the Meteor guide), where you simply import all files that declare publications and methods, and then importing this single file in some file outside the imports folder. For more about this, see the Meteor Guide and its example app.
Note also that for Meteor methods, you may want to include them also somewhere in your client code, so that the client can run simulations of them for optimistic UI before the server call returns. To do this, you can do the same as above but with a file like /imports/startup/client/index.js, that you include in the client code. I also recommend checking out the mdg:validated-method package, it makes using methods cleaner.
Update regarding the update in the question:
Yes, that seems like it would work, I think you got the point :)
As a minor detail, as I said, you might want to consider importing app-name/imports/server/trades-methods.js somewhere in your client code as well, i.e. in a file like app-name/client/main.js. This would enable the client to run a simulation of the method and update the UI immediately for better user experience. Don't do this if you don't want to expose some super-secret server code to the client though.
Update 2 in the question
Within the /imports folder, there are no special folder names - so you can import a file from /imports/server in your client side code. However, I do recommend placing code that is only meant for the server, like publications, in a folder named server, and not placing code that is meant to be used from both sides to a folder named server or client. Thus you might want to move your trades-methods.js file outside your /imports/server folder anyway. However this is only for clarity, Meteor does not care about folder names inside /server!
I really, really recommend you to read the Meteor guide, particularly the chapter on application structure and checking out the structure of the related example app. You'll save so much time in the long run!

Complex backbone app with multiple build configurations using Browserify

I'm working on a large Backbone app that is designed to be very configurable due to being multi-tenancy and designed to run on many platforms. Currently the apps are built via Grunt and environment variables are used to determine which Backbone files are included in the finished version of the app.
At present some of the files that get included are extending or overwriting others that are included earlier.
As an example:
BaseHeader.js:
var BaseHeader = Backbone.View.extend({
// code
});
Header.js:
var Header = BaseHeader.extend({
// code
});
At the moment my finished app is built with Grunt which creates an .html file with a bunch of script tags so all the files will be loaded by the browser.
I'd like to use Browserify to bundle my JS into a single file, so now I have:
BaseHeader.js:
var Backbone = require("backbone");
var BaseHeader = Backbone.View.extend({
// code
});
module.exports = BaseHeader;
Header.js:
var Backbone = require("backbone");
var BaseHeader = require("/path/to/BaseHeader.js");
var Header = BaseHeader.extend({
// code
});
module.exports = Header;
But I'm confused as to how to work things.
The entry point for all my apps is the same App.js file which makes a require call to BaseHeader.js, it doesn't however make a require call to Header.js as this file is platform/client specific.
As Browserify simply recurses through the requires in order to find and bundle dependencies it will never pick up Header.js
So, how can I create a build task to optionally require Header.js when needed?
Your looking for the require option to browserify:
This option will include the module or file as part of the bundle even if it isn't referenced in the entry app. It should also expose the said module to your HTML page via a global require() function.
From the docs:
b.require(file, opts)
Make file available from outside the bundle with require(file).
The file param is anything that can be resolved by require.resolve().
file can also be a stream, but you should also use opts.basedir so that relative requires will be resolvable.
If file is an array, each item in file will be required. In file array form, you can use a string or object for each item. Object items should have a file property and the rest of the parameters will be used for the opts.
Use the expose property of opts to specify a custom dependency name. require('./vendor/angular/angular.js', {expose: 'angular'}) enables require('angular')

Categories