gruntjs / angularjs - optional development config? - angularjs

Like most js web apps we have a config.js file that contains global config information about the app, base api urls and such. These values are often different in local development than in production.
I've looked at answers like: Development mode for AngularJS using GruntJS, and also things like grunt-replace for creating an on-the-fly config file.
My issue is that the "development" part varies from developer to developer, we all need a version of the API setup so the base api urls will be different. I'd like to allow each developer to override specific variables in the config in a way that doesn't require them to commit that info to the git repo (I agree that this isn't best practice, everything should be in the repo, but as this is only 1/2 variables for this project I can overlook it)
Any ideas on how to achieve this setup?

You can use grunt-preprocess. I would have production (and dev-server, etc) values in a file, say env.json. You could use grunt to look for an optional file, say overrides.json or developer.json, which would extend/overwrite the values from env.json.
var envFile = require('./env.json');
You can create command line options to grunt with grunt.option, e.g. var env = grunt.option('env') || undefined;, which could be used to turn off overriding.
You can get data from the optional file using fs.existsSync:
var fs = require('fs');
var developerFile;
if (fs.existsSync('./developer.json')) {
developerFile = require('./developer.json');
}
The simplest way to define the grunt-preprocess context would be to use the developer.json file if present, or the env.json file if not:
context: developerFile ? developerFile : envFile;
This requires the developer file to be complete. An alternative is to extend the envFile with options from developerFile if it's present.

In my project, we use different config files (which are basically files with JS object). So every developer has his app/configs/developer/config.js file, which is not comited in the source control, so every developer has his own setup. Project uses link to app/scripts/config.js by default and this file is just a soft link to developers config file. However, there are also app/configs/staging/config.js and app/configs/production/config.js files, which are replaced when using gruntjj to build project. Those configs are just copied to build solution instead of soft linked file.
I hope that makes sense..

Related

React-i18next and cached translation files

I'm using "react-i18next" to translate my Website and the translation files are in "/public/locales/{en|fr}/translation.json".
Problem: the files are cached and therefore when I update the translation values, the changes are not applied except if I clean my browser caches.
I guess, the solution is to add a hash in the name of these translation files during the start/build. This is what React already does for files in '/src' folder. How can I achieve that ? It seems that 'react-scripts start/build' abstract all the Webpack configuration.
You can host your translations on a dedicated path with the help of i18next-http-backend, like described here.
Alternatively, you could also make use of a professional CDN service like locize and fetch the translations via i18next-locize-backend, like described here.

Gatsby, Environment variables not accessible in browser

I want to use environment variables. I created .env.development file and I put some variables. Then I include the dotenv plugin to read the variables in gatsby-config.js:
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`
});
The content of my .env.development:
GATSBY_APP=MYAPP
It's working in gatbsy-node.js but in browser (REACT) it's empty. I display console.log(process.env) and it return empty object.
Even if I install and configure gatsby-plugin-env-variables.
It looks like you're combining two approaches, and that might be where you're running into trouble.
Gatsby comes out-of-the-box with support for defining environment variables in environment-specific .env.[environment] files (e.g. .env.development), provided these files are in the root of your project (i.e. your-project/.env.development). Documentation for this feature. You do not need to install or configure dotenv for this to work.
Another approach is to use dotenv, which will allows you to use a general .env file. You need to then import and configure the tool, which is generally done at the very top line of gatsby-config.js and looks like this:
require("dotenv").config()
Note that you do not specify the environment name (e.g. development) in this scenario, and you would not commit the .env file to your repository.
The other issue you might run into is that part of your code runs server-side, using Node, and part runs client-side (in the browser). Since process.env is only available in Node, Gatsby does some additional work to make it available in the browser. We don't want all of these variables, which frequently hold secrets, to be provided to the browser, though, so Gatsby only copies over those that whose names begin with GATSBY_. Finally, as a side effect of the way that these variables get copied over, you must explicitly reference them for your build to work:
// this is okay everywhere
const GATSBY_APP = process.env.GATSBY_APP
// this won't work in code that runs client-side, but will work
// in `gatsby-node.js` and other files that only run in Node
const { GATSBY_APP } = process.env
If you wanted to whitelist your own environment variables, either as a prefix (shown here) or have a list of them, you can add something like this in the gatsby-node.js file:
exports.onCreateWebpackConfig = ({ actions, getConfig }) => {
const config = getConfig();
// Allow process.env.MY_WHITELIST_PREFIX_* environment variables
const definePlugin = config.plugins.find(p => p.definitions);
for (const [k, v] of Object.entries(process.env)) {
if (k.startsWith("MY_WHITELIST_PREFIX_")) {
definePlugin.definitions[`process.env.${k}`] = JSON.stringify(v);
}
}
actions.replaceWebpackConfig(config);
};
I was running into the same issue and just found out what I was doing wrong. It looks like you're doing the same thing.
The explanation both the documentation and #coreyward give are correct, however, note that while corey implies they're two different approaches and the issue might be that they're conflicting, they're not, they do different things - so that code of yours is fine.
What's wrong, though, is that you're console logging process.env. And as it turns out, this will always output an empty object even though the variables might be there.
You have to console.log(process.env.GATSBY_APP) directly to see any value.
(Reference)
This is essentially an extension of what Corey pointed out in his "finally as a side-effect" section, however, the way he's written it implies it's an issue with destructuring - but it's not limited to that.
In my case, I was doing the above error AND not exposing the variables with GATSBY_ properly, then while testing I started logging the whole env object like you while I searched for the cause. This meant that even after I added the correct GATSBY_ prefix I still couldn't see anything.
So in short, it's probably only your console.log line that's an issue - access the variable directly, not the env object as a whole.
The Gatsby site as a well documented section on working with environment variables. The gist is that the environment variables are only available during build time when the internal nodejs server is server rendering your site. In order, get those environment variables in the browser you need to programmatically embed them using the special gatsby-*.js files. The example they provide seems to be close to what you want to achieve.

Build files name change - files that are generated from create react app

The build files generated through create react app have different names(hash code) every time.
I would like to give a custom names for the generated files.
Is there any possibility to do the same?
You can change the output filename by customizing the filename property in webpack config -- refer to https://webpack.js.org/guides/caching/
The default implementation is kept like this because, because every time you build an asset, it generates a new name and browsers won't be able to serve a cached response.
If you change the name to a constant you might need to clear the browser cache manually/ disable cache to see your changes immediately. (I think...Applicable only in prod mode as dev mode makes use of Hot module replacement)
Steps to change file name in CRA.
npm run eject This will unwind the hidden configs from CRA and show some additional config folders
Move to the config folder.
Edit file webpack.config.js (Somewhere around line 172 - 180 you can see filename: section where this is defined)
Following up to my comment, if you absolutely must change Webpack configuration you can also consider libraries such as:
Craco
Rescripts

Webpack/React json file not loading externally on build

Im trying to use the azure environment variables with my react build. So far I have an appsettings.json file that I load into react with:
import settings from './appsettings.json';
I then have webpack copy the json into build folder which goes to azure. However I think after build the app isnt actually loading the file as I can see some of my variables embedded in the "chunk.js" so its not actually reaching out the the json file in root anymore? Am I importing the file in the wrong way?
C
Two possible solutions:
var json = require('./data.json'); //with path
change your settings.json to settings.js and use module.exports = {} in it.
I believe azure would accept different forms of setting files, not limited to json.

Environment configuration at build time with npm

There are several blog posts that explain why switching from grunt or gulp to building with just plain npm is a good idea for example this one by Cory Hourse or this one by Keith Cirkle. One thing these blog posts do not explain is how I can easily do environment configuration. For example a common requirement is to have different REST API locations. During development the server might be running on localhost:8080, but on production it should be accessed through a relative URL such as /api or /rest/api and the port or protocol are different for development and production.
There are several solutions for this. For example grunt supports template strings like <% %> and <%= %> and there are grunt or gulp plugins like in this question about grunt-ng-config. These solutions are specific to Angular (which I am using), but I am not necessary looking for an AngularJS specific solution.
I also know of the angular-environment plugin, but as far as I can see this does configuration at run time and I am looking for something that can do this at build time.
So what I am looking for is something that allows me to configure my application at build time either by replacing some template strings or by generating a Javascript file with some variables that I can read at run time.
One requirement is that it should be OS independent. So I do not want to use UNIX specific tools such as sed to rewrite a file. And due to different variable expansion (e.g. % vs. $) a solution should not rely on environment variables.
Is there an existing solution or a best-practice for this?
due to different variable expansion (e.g. % vs. $) a solution should
not rely on environment variables
this cuts off your best solution. Why not rely on env vars? node provides
process.env
to access env vars. You could create custom gulp / grunt tasks that use process.env instead of the "different variable expansions" you refer to.
You can use, for example, Jade templating to pass env var values to your HTML at build time. This would generate your index.html on the fly as part of the build process and add relevant classes based on env vars.
For example, according to the value of an env var you might set a class on the HTML tag.
This might reflect the customer.
Then you could have some CSS
.customer1 .myimage {
background-image: url("customer1.png");
}
.customer2 .myimage {
background-image: url("customer2.png");
}
or you could use JavaScript to detect which class was added to head during the build.

Resources