Nodejs expressjs make npm package available throughout the project - javascript

I've this folder structure.
/app.js
/src
/routes
/controllers
In routes folder, I've bunch of js files. All of these files need to require passport js package like this
const passport = require('passport');
Instead of doing this, can I require the package in one place (Most probably in app.js) and somehow pass that to each and every file in the routes folder instead of requiring it on every file.

There may be a passport/Express-specific solution (e.g., installing passport once as middleware), but answering the question about modules in general:
Requiring a module in a module that uses it is standard practice and clearly expresses the dependencies between modules, so it's not usually something you want to avoid doing.
Instead of doing this, can I require the package in one place (Most probably in app.js) and somehow pass that to each and every file in the routes folder instead of requiring it on every file.
You have a couple of options:
If all of those files have other things they're also all importing, you can create a rollup module that requires all of those things and then makes them available as exports. Then your files would do:
const {passport, anotherThing, yetAnotherThing} = require("./the-rollup-module");
instead of
const passport = require("passport");
const anotherThing = require("another-thing");
const yetAnotherThing = require("yet-another-thing");
The rollup would look like this:
module.exports.passport = require("passport");
module.exports.anotherThing = require("another-thing");
module.exports.yetAnotherThing = require("yet-another-thing");
(I don't recommend this.) You can make it a global by putting this in your entry script:
global.passport = require("passport");
That exposes passport as a global variable, so your modules could just use passport without requireing it. (The default global variable is a reference to the global object, like window on browsers, so any property you create on it becomes a global variable.)
I don't recommend it because then the dependencies between your modules are no longer clearly defined.

No matter how often you require() a module, it will be loaded just once. There is nothing wrong with requiring one module in multiple files, actually this is basically the way the module system is designed to work.

If the files in the routes folder are not using the express router you can rather or else export the function which accepts passport and app objects like
module.exports = function(app, passport) {
app.get('/', (req, res) => {
res.json('some route');
});
}
Then you will be requiring the passport only once in the app.js/server.js and passing the same object to every route

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

How make const variable available to other file

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.

Is it possible to use dotenv in a react project?

I am trying to set some environment variables (for making API calls to dev/prod endpoints, keys depending on dev/prod, etc.) and I'm wondering if using dotenv will work.
I've installed dotenv, and I am using webpack.
My webpack entry is main.js, so in this file I've put require('dotenv').config()
Then, in my webpack config, I've put this:
new webpack.EnvironmentPlugin([
'NODE_ENV',
'__DEV_BASE_URL__' //base url for dev api endpoints
])
However, it is still undefined. How can I do this correctly?
Sorry for picking up old question, but
react-scripts actually uses dotenv library under the hood.
With react-scripts#0.2.3 and higher, you can work with environment variables this way:
create .env file in the root of the project
set environment variables starting with REACT_APP_ there
access it by process.env.REACT_APP_... in components
.env
REACT_APP_BASE_URL=http://localhost:3000
App.js
const BASE_URL = process.env.REACT_APP_BASE_URL;
See docs for more details.
The short answer is no. A browser cannot access local or server environment variables so dotenv has nothing to look for. Instead, you specify ordinary variables in your React application, usually in a settings module.
Webpack can be made to take environment variables from the build machine and bake them into your settings files. However, it works be actually replacing strings at build-time, not run-time. So each build of your application will have the values hard-coded into it. These values would then be accessible through the process.env object.
var nodeEnv = process.env.NODE_ENV;
Additionally, you could use the DefinePlugin for webpack which lets you explicitly specify different values depending on your build target (dev, prod, etc.). Note that you have to JSON.stringify all values passed into it.
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
}),
This is fine for any sort of public details but should never be used for any sort of private keys, passwords or API secrets. This is because any values baked in are publicly accessible and could be used maliciously if they contain sensitive details. For those sorts of things, you need to write some server-side code and build a simple API which can authenticate with the 3rd party API using the secrets, then pass the relevant details along to your client-side application. Your server-side API acts as an intermediary, protecting your secrets while still getting the data you need.
Create .env file
API_URL=http://localhost:8000
Install dotenv npm package
$ npm install --save-dev dotenv
Config webpack to add env variables
const webpack = require('webpack');
const dotenv = require('dotenv');
module.exports = () => {
// call dotenv and it will return an Object with a parsed key
const env = dotenv.config().parsed;
// reduce it to a nice object, the same as before
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
return {
plugins: [
new webpack.DefinePlugin(envKeys)
]
};
Great job! Enjoy React and dotenv.
Actually, you can use dotenv in your React app with webpack. Moreover, there are several ways of doing it. However, keep in mind that it's still a build-time configuration.
A similar way to the answer above. You import dotenv in your webpack config and use DefinePlugin to pass the variables to your React app. More complete guide on how you can inject your .env files depending on current configuration could be found in this blog.
Using a dotenv-webpack plugin. I personally find it really convenient. Let's say you have environments: dev, staging and prod. You create .env file for each environment (.env.dev, .env.staging, etc). In your webpack configuration you need to pick a correct file for the environment:
const Dotenv = require('dotenv-webpack');
module.exports = (env, argv) => {
const envPath = env.ENVIRONMENT ? `.env.${env.ENVIRONMENT}` : '.env';
const config = {
...
plugins: [
new Dotenv({
path: envPath
})
]
};
return config;
};
When you build the app for a particular environment, just pass the environment name to webpack:
webpack --config webpack.config.js --env.ENVIRONMENT=dev
I Just created a config.json in the source folder:
{
"api_url" : "http://localhost:8080/"
}
then required it in the file I needed it
const config = require('./config.json');
and used config.api_url

passing the express app to the routes files

I'm writing an express 4 api server with no front end code. I chose to structure my project so that the folder structure is based on the business logic of the project rather than doing it based on the type of file (routes, models, etc.)
For instance, my User folder has my userRoutes.js, userModel,js, userApi.js, ...
My main question is actually how should I pass the app into my routes files? My favorite approach was doing global.app and making it global, but I hear that is not best practice. If you have any advice on my business logic structure that would be great too.
Firstly, your file structure sounds over-the-top. If you need that much to split things out cleanly, go for it. But, I have a hunch that you're overdoing it.
In any case, what I normally do is return middleware from each module. You can give each middleware its own Express router if you want. In the modules:
const express = require('express');
module.exports = function (config) {
const router = new express.Router();
router.get('/something', (req, res) => {
// Code here
});
return router;
}
Then in your main application:
const somethingHandler = require('somethingHandler.js');
app.use(somethingHandler);
This is in-line with how all other Express middleware modules work. This also allows you to namespace modules by path, with your app.use() call in the main app.
You must require express app or pass to routes file by excute require function like this:
var app = require('express');
var userRoutes= require('your route path')(app);
I think global variable is not good idea.

Express js require() followed by funtion(app)

Im fairly new to Nodejs and express, I was looking through some tutorials and examples and stumbled across
this inside app.js
var router = require('./router')(app);
What is the purpose of doing this?
This is whats inside the router file
module.exports = function (app) {
// The signup route
app.use('/signup', require('./routes/signup'));
}
You import your routers from another file.
This is a technique for scaffolding. Models, views, controllers and routers are kept in different files and then you import them into a main.js with require().
You create your project modular, it's more easy to scale and develop with team.
This is a popular modular pattern in javascript, often seen in node. Here's what you gain:
You can modularize your code into separate files so you don't end up with big monolith chunks of code.
By requiring the module as a function, you can pass some variable constants (such as the application config, or a datatbase entry point).
You can choose what to expose, and what to keep private by using module.exports which cleans up the global object for the application.
In the code snippet you provided, your passing the app config to the routes file, where you are creating a route that is reliant on the variable. If that route relied on interior logic, that logic could be scoped to the routes.js file rather than be exposed to the rest of the application.

Categories