Environment specific variables with requirejs - requirejs

I would like to set a requirejs configuration variable which would be available via module.config.
The optimizer does not seem to pass this through.
Is this possible, or should I handle this step via my build process.

You have to set it in your config file for a specific module like this and as long as your told r.js to use this config file it should work:
requirejs.config({
config: {
'path/to/myModule': {
someSetting: 'someSetting'
}
}
});

A simple solution seems to be to be:
Create a config file for each environment (eg., config, config-production)
When you want your config, require('/path/to/config')
When you call r.js, just put in a paths argument (eg., r.js -o build.js paths.config=config-production)
You now have your production configuration settings

Related

Using environment variables in Node

I have been trying to get a streamline way of having different environment variables for local and production web apps, but I haven't come across the "ideal" solution yet.
There's the option of having a config.js file like so:
//config.js
{
"secretKey": "SDFDASFFSFD",
"facebook": {
"clientID": "EFGFDGBGDGFS",
"clientSecret": "EGDFNHFG"
}
}
And accessing via ES6 imports
Or using .env files like so:
SOME_KEY=someValue
HELLO=world
FACEBOOK_SECRET=435SDFSF5DZVD7S
And accessing the variables via process.env in the code using dotenv.
Obviously no matter what route you go down, the file will need to be omitted from version control which is fine. Each of these ways are great, but they only seem to work well for local development.
So how do you then have a separate file for a production environment? The dotenv docs say they strongly recommend against a .local.env and .prod.env situation.
Also, how is best to push to a remote server? I have my own server with Gulp tasks which run on a Git post-receive hook. How is best to pass up the production environment variables to here?
Thanks
You could have own config file for each environment:
- environments
- index.js
- deveplopment.json
- staging.json
- production.json
To use appropriate config file, run the app with required NODE_ENV:
NODE_ENV=production node index
In environments/index.js determinate the current NODE_ENV and use config:
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
module.exports = require('./' + process.env.NODE_ENV);
If config file doesn't include secret info (apiKeys, etc), it can be pushed to repo. Otherwise add it to .gitignore and use environment variables on the server.
Note:
For advanced configuration use such packages as nconf.
It allows to create hierarchical node.js configuration with files, environment variables, command-line arguments, and atomic object merging.
Have you thought about having a keys.js file with a .gitignore on it?
I've used this in the past to use module.exports{} to get my variables usable but not going to version control for the security side of things!

How to read a jasmine spec file config variable from the jasmine.json file

I am learning the node.js jasmine code testing framework and would like to set a variable that will be reused in several test spec files. Is there a way to read a config variable from the jasmine.json file?
I have used the 'process.env.npm_variablename' for normal package.json node.js config variables, but that file is not loaded by the jasmine test runner.
Part way through typing the question, I thought of a solution that seems to be working: load the file with the 'require' function. It looks like this in the initialized current 2.6 jasmine structure:
var jas_config = require('./support/jasmine.json');
if (jas_config.verbose_output) {
console.log("loading test-spec.js");
}

jest global variable example

Can someone give an example on how to use jest globals?
{
...
"jest": {
"globals": {
"__DEV__": true,
}
}
...
}
Do I specify the globals in the package.json file or do I create a folder with a js file where the globals should be defined?
Thanks
Yep. You put the globals in the package.json. For example, here's an excerpt from the default react-native jest configuration:
"jest": {
"globals": {
"__DEV__": true,
"__RCTProfileIsProfiling": false
},
...
},
This will make the variables available globally when the tests are run.
A cleaner way to add globals would be to set "setupFiles": "<rootDir>/private/jest/setup.js" in package.json, and then create a setup.js file that sets global.__DEV__ = true.
This pattern is helpful for making 3rd party libraries available as globals to Jest tests as well (like Backbone, jQuery, lodash, etc.) - eg. global.Backbone = require('backbone'); and so on.
(Re-submitting this as an answer as it was previously just a comment under Michael Helvey's answer.)
For me using the Jest config file worked much better because it is a Javascript file itself so it gives full freedom:
After running jest --init in your folder, in the jest.config.js file Jest makes, scroll down to find:
// A set of global variables that need to be available in all test environments
// globals: {},
Uncomment the second line and put all your globals in there.
If you are using create-react-app, you must use the src/setupTests.js file instead of pointing to a file via setupFiles in the package.json file.
https://create-react-app.dev/docs/running-tests/#srcsetuptestsjs
In the src/setupTests.js file, you can define globals like so:
global.TIMEOUT = 3000;
To share object variables (not only primitives as with configuration's globals property), you can use the testEnvironment property.
More explanations here in Jest's Git

How to not bundle node_modules, but use them normally in node.js?

Architecture
I would like to share code between client and server side. I have defined aliases in the webpack config:
resolve: {
// Absolute paths: https://github.com/webpack/webpack/issues/109
alias: {
server : absPath('/src/server/'),
app : absPath('/src/app/'),
client : absPath('/src/client/'),
}
},
Problem
Now on the server side I need to include webpack in order to recognize the correct paths when I require a file. For example
require('app/somefile.js')
will fail in pure node.js because can't find the app folder.
What I need (read the What I need updated section)
I need to be able to use the webpack aliases. I was thinking about making a bundle of all the server part without any file from node_modules. In this way when the server starts it will use node_modules from the node_modules folder instead of a minified js file (Why? 1st: it doesn't work. 2nd: is bad, because node_modules are compiled based on platform. So I don't want my win files to go on a unix server).
Output:
Compiled server.js file without any node_modules included.
Let the server.js to use node_modules;
What I need updated
As I've noticed in https://github.com/webpack/webpack/issues/135 making a bundled server.js will mess up with all the io operation file paths.
A better idea would be to leave node.js server files as they are, but replace the require method provided with a custom webpack require which takes in account configurations such as aliases (others?)... Can be done how require.js has done to run on node.js server.
What I've tried
By adding this plugin in webpack
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"ignore", /* filename= */"server.bundle.js")
Entries:
entry: {
client: "./src/client/index.js",
server: "./src/server/index.js",
ignore: ['the_only_node_module'] // But I need to do that for every node_module
},
It will create a file server.js which only contains my server code. Then creates a server.bundle.js which is not used. But the problem is that webpack includes the webpackJsonp function in the server.bundle.js file. Therefore both the client and server will not work.
It should be a way to just disable node_modules on one entry.
What I've tried # 2
I've managed to exclude the path, but requires doesn't work because are already minified. So the source looks like require(3) instead of require('my-module'). Each require string has been converted to an integer so it doesn't work.
In order to work I also need to patch the require function that webpack exports to add the node.js native require function (this is easy manually, but should be done automatically).
What I've tried # 3
In the webpack configuration:
{target: "node"}
This only adds an exports variable (not sure about what else it does because I've diffed the output).
What I've tried # 4 (almost there)
Using
require.ensure('my_module')
and then replacing all occurrences of r(2).ensure with require. I don't know if the r(2) part is always the same and because of this might not be automated.
Solved
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
Related
https://www.bountysource.com/issues/1660629-what-s-the-right-way-to-use-webpack-specific-functionality-in-node-js
https://github.com/webpack/webpack/issues/135
http://webpack.github.io/docs/configuration.html#target
https://github.com/webpack/webpack/issues/458
How to simultaneously create both 'web' and 'node' versions of a bundle with Webpack?
http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/
Thanks
Thanks to ColCh for enlighten me on how to do here.
require = require('enhanced-require')(module, require('../../webpack.config'));
By changing the require method in node.js it will make node.js to pass all requires trough the webpack require function which allow us to use aliases and other gifts! Thanks ColCh!
My solution was:
{
// make sure that webpack will externalize
// modules using Node's module API (CommonJS 2)
output: { ...output, libraryTarget: 'commonjs2' },
// externalize all require() calls to non-relative modules.
// Unless you do something funky, every time you import a module
// from node_modules, it should match the regex below
externals: /^[a-z0-9-]/,
// Optional: use this if you want to be able to require() the
// server bundles from Node.js later
target: 'node'
}

Use RequireJS config file as the build file?

I've got some paths configured in require-config.js as follows:
var require = {
baseUrl: '/javascript',
paths: {
'jquery': 'jquery/jquery-1.8.1.min'
// etc. -- several paths to vendor files here
},
}
I am trying to get the optimization working for deployment. The docs say I should have a build.js that looks something like this:
({
baseUrl: 'javascript',
paths: {
'jquery': 'jquery/jquery-1.8.1.min'
},
name: 'main',
out: 'main-build.js'
})
Is there a way to have the optimizer read my config file instead of (or in addition to) build.js? I don't want to have to manually keep the paths configured the same in both files if they change.
I tried to just run node r.js -o path/to/require-config.js, but it threw an error, "malformed: SyntaxError: Unexpected token var"
Edit: for clarification, my require-config.js file is the config only, not my main module. I did this so I could use the same configuration but load a different main module when unit testing.
You'll need to adjust the way your config options are defined. Taken from the RequireJS documentation:
In version 1.0.5+ of the optimizer, the mainConfigFile option can be used to specify the location of the runtime config. If specified with the path to your main JS file, the first requirejs({}), requirejs.config({}), require({}), or require.config({}) found in that file will be parsed out and used as part of the configuration options passed to the optimizer:
So basically you can point your r.js build file to your config options that will also be shared with the browser.
You will need to make use of the mainConfigFile option
For other's reference:
https://github.com/jrburke/r.js/blob/master/build/example.build.js
The build settings (no need to repeat your config.js lib inclusions here):
baseUrl: 'app',
name: 'assets/js/lib/almond', // or require
// Read config and then also build it into the app
mainConfigFile: 'app/config.js',
include: ['config'],
// Needed for almond (and does no harm for require)
wrap: true,

Resources