6

I have an angular app setup that's using grunt, but I'd like to be able to use grunt as a preprocessor to replace variables and I haven't been able to find anything that matches my needs.

For instance, if I change the name of my main app module to "someAppName" in a config file, I'd like to just use something like "ENV.APP_NAME" in various html and js files and have that replaced by an appropriate value for that environment.

Ideally I'd like to have a config file somewhere along these lines, either as a .json file or using module.exports to expose an object, which specifies values for different environments:

{ APP_NAME:{ dev: "someAppDev", prod: "someApp" }, API_BASE:{ dev: "localhost:8000/", prod: "https://www.some-site.com/api/" } } 

and then I could create a grunt task and pass it either "dev" or "prod" to have it run the preprocessor and replace each instance with the corresponding value. I've found this https://github.com/STAH/grunt-preprocessor but the examples are confusing and I don't think it's quite what I'm looking for.

Is there anything like this that allows you to create preprocessed environment variables and read them from an external config file, or am I forced to build my own grunt plugin? Has anyone achieved something similar with grunt?

EDIT: I've begun building a grunt plugin for this specific task, once it's done and tested I'll post it up on npm

8
  • Maybe this would help: mindthecode.com/… Commented Feb 7, 2015 at 22:25
  • I've seen that, it does add environment variables but not as a preprocessor. so I'd have access to environment variables within a controller but I couldn't, say, have it as part of an html file or json and have it replaced as I'm looking for Commented Feb 7, 2015 at 22:29
  • Maybe independent program that would read all html js files before and replace specified tags? It may be written in java. Something like replace all. Commented Feb 7, 2015 at 22:36
  • yeah I'm sure there are some tools out there to do it but I'd like a grunt task so it can be part of the automated workflow if possible. adding a watch task to the config file to recompile, similar to using a watch task with SASS files, would be nice Commented Feb 7, 2015 at 22:54
  • maybe this: stackoverflow.com/questions/18271744/… Commented Feb 7, 2015 at 22:57

3 Answers 3

6

Use grunt-ng-constant.

Npm install this plugin:

npm install grunt-ng-constant --save-dev 

Then in grunt write to config file:

ngconstant: { // Options for all targets options: { space: ' ', wrap: '"use strict";\n\n {%= __ngModule %}', name: 'config', }, // Environment targets development: { options: { dest: '<%= yeoman.app %>/scripts/config.js' }, constants: { ENV: { myvar1: 'Hello from devel', myname: 'John Doe' } } }, production: { options: { dest: '<%= yeoman.dist %>/scripts/config.js' }, constants: { ENV: { myvar1: 'Hello', myname: 'John Doe' } } } }, 

Then add to grunt task:

 grunt.task.run([ 'clean:server', 'ngconstant:development', 'connect:livereload', 'watch' ]); 

Running task would generate config.js with constants defined in gruntfile. Then add config.js to your index.html:

<script src="/scripts/config.js" /> 

Inject it to your app:

var app = angular.module('myApp', [ 'config' ]); 

And inject into controller:

.controller('MainCtrl', function ($scope, $http, ENV) { console.log(ENV.myvar1); }); 

You can set different variables for production and different for development, by setting it in gruntfile and setting ng:production or ng:development.

Refer this article explaining the procedure for more information.

Sign up to request clarification or add additional context in comments.

1 Comment

This is useful, though I don't think it's exactly what the OP is looking for. I might make use of it, though, so thanks.
2

You could do something making use of grunt-string-replace while loading some config values into Grunt from a JSON file. Suppose you had this in myconfig.json:

{ "appName": "MyGrowth", "version": "1.1.2", } 

Then perhaps load the config into Gruntfile.js from JSON with something like:

grunt.initConfig({ myConfig: grunt.file.readJSON('myconfig.json'), // ... the rest of the stuff in your initConfig goes sure } 

Then you would have some sort of task like this maybe:

'string-replace': { version: { options: { replacements: [ { pattern: /MY_VERSION/ig, replacement: '<%= myConfig.version %>' } ] }, files: [{ expand: true, cwd: 'src/', src: '**/*.js', dest: 'dist/' }] } } 

That would make actual changes to the files if you had 'src' and 'dest' in the same folder, otherwise it would put the processed files in the dest folder.

I've not actually used this recipe for preprocessing, but I use it for other types of things like replacing tags in a framework with the app name as configured in package.json.

Hope it helps.

1 Comment

Very helpful answer! Regarding the final part of the OP's question ("create a grunt task and pass it either dev or prod"), outaTiME/grunt-config can define target-specific configuration values, to be used when doing the string replacement. See the "Environment variable in source" section of the README for a good example.
2

Alright I ended up building a grunt plugin just for this task because it's something that I really needed. It allows you to place environment variable definitions in a .json file like I described in my original question and replaces all instances in a specified file or list of files.

https://github.com/ejfrancis/grunt-envpreprocess

So if you have something like this


HTML

<head> <title>ENV.APP_NAME</title> </head> <script src="ENV.API_BASE/user/create"> 

JS

 var version = "ENV.APP_VERSION"; alert(version); 

The task will replace it with this


HTML

<head> <title>AppDev</title> </head> <script src="http://localhost:8000/user/create"> 

JS

var version = "0.1.0"; alert(version); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.