How to set flags in ember-cli, other than environment? - javascript

This is currently possible:
ember build --environment=production
... and I would like to do something like this instead:
ember build --environment=production --baseurl=foo
but config/environment.js only gets passed in the value of environment.
Is it possible to get the value of the other options passed in at the command line too?

You could set environment variables the old fashioned way (export WHATEVER=wee) from terminal or as part of a build script, then reference them in your Brocfile.js via node with process.env.WHATEVER. After that, it would be a matter of having broccoli do whatever it is you needed to do with them. You could pre-process files and replace strings, for example.
... just a suggestion. Not sure if that's what you're looking for or not.

It appears that this is not allowed:
Looking in node_modules/ember-cli/lib/commands/build.js, we see:
availableOptions: [
{ name: 'environment', type: String, default: 'development' },
{ name: 'output-path', type: path, default: 'dist/' }
],
... and in node_modules/ember-cli/lib/models/command.js
this.availableOptions.forEach(function(option) {
knownOpts[option.name] = option.type;
});
... which together mean that any options that are not defined, for each subcommand of ember, get discarded.

You can do foo=bar ember build (however doing ember build foo=bar doesn't work)
And the argument is available via process.env.foo.

To extend upon #ben's answer.
The raw command line arguments are available inside ember-cli-build.js and other files from the
process.argv.[]
So a command like this
ember build staging
you can access via:
process.argv.includes('staging')
see node's documentation for whats available.
https://nodejs.org/docs/latest/api/process.html

Related

How to use google-closure-compiler-js for a node.js app without gulp/grunt/webpack?

The docs don't have any examples of using this on its own but they do say this:
Unless you're using the Gulp or Webpack plugins, you'll need to specify code via flags. Both jsCode and externs accept an array containing objects in the form {src, path, sourceMap}. Using path, you can construct a virtual filesystem for use with ES6 or CommonJS imports—although for CommonJS, be sure to set processCommonJsModules: true.
I've created a "compile.js" file based on the docs:
const compile = require('google-closure-compiler-js').compile;
const flags = {
jsCode: [{path: './server/server.js'}],
processCommonJsModules: true
};
const out = compile(flags);
console.info(out.compiledCode);
In my "./server/server.js" file, I put a console.log but it doesn't output. Not sure where to go from here...
Borrowing from icidasset/quotes.
It appears, to me, that path is not intended to be used as you are using it.
Quote:
Using path, you can construct a virtual filesystem for use with ES6 or CommonJS imports—although for CommonJS, be sure to set processCommonJsModules: true.
So instead you must expand your own sources, something webpack and gulp must be doing for you when you go that route.
files=['./server/server.js']
files.map(f => {
const out = compile({
jsCode: [{ src: f.content }],
assumeFunctionWrapper: true,
languageIn: 'ECMASCRIPT5'
});
return out;
}

Basic templating with nunjucks

I'm writing a shell script, and would like to use template it, by keeping my variables in a json file.
I'm a beginner to javascript, and so can't seem to get the hang of how to use nunjucks to render my templates. Can you please help me get this simple example to work?
Here's my current attempt. (I have npm installed)
In my project directory :
$ npm install nunjucks
I create sample.njk with the following contents :
{{ data }}
And index.js with the following content :
var nunjucks = require('nunjucks')
nunjucks.configure({ autoescape: true });
nunjucks.render('sample.njk', { data: 'James' });
My project directory then, looks like :
index.js node_modules/ sample.njk
I run index.js with node as
$ node index.js
How do I get it to output (to the command line, or to a new file):
James
after processing the template?
I've tried looking at gulp-nunjucks and gulp-nujucks-render, but there's too much going on there, and I can't even get a simple task accomplished here.
When I define my data in a json file, I only need pass it as a context in the nunjucks.render() function, right?
Thanks for your help.
Depends on what you're trying to accomplish with the data outputted by the Nunj render. If you simply want to print it to the terminal, a simple console.log(); will work.
In Express, res.render takes an optional third param which is a fn. You would do it as such:
var nunjucks = require('nunjucks');
nunjucks.configure({ autoescape: true });
nunjucks.render('sample.njk', { data: 'James' }, function (err, output) {
// If there's an error during rendering, early return w/o further processing
if (err) {
return;
}
// The render fn calls the passed-in fn with output as a string
// You can do whatever you'd like with that string here
console.log(output);
});

Different settings for debug/local ("grunt serve") vs. dist/build ("grunt")?

I want to define some application settings, but I want to provide different values depending on whether I'm running in 'debug' mode (e.g. grunt serve), or whether the final compiled app is running (e.g. the output of grunt). That is, something like:
angular.module('myApp').factory('AppSettings', function() {
if (DebugMode()) { // ??
return { apiPort: 12345 };
} else {
return { apiPort: 8008 };
}
});
How can I accomplish this?
The way I handle it in my apps:
move all your config data for one environment to a file: config.js, config.json,... whatever your app finds easy to read.
now modify your config file to turn it into a template using grunt config values, and generate the file with grunt-template as part of your build - for example: app.constant('myAppConfig', {bananaHammocks: <%= banana.hammocks %>});
finally, add grunt-stage to switch grunt config values depending on environment: create your different config/secret/(env).json files, update your template (app.constant('myAppConfig', {bananaHammocks: <%= stg.banana.hammocks %>});), and then grunt stage:local:build or grunt stage:prod:build
I find this the good balance between complexity and features (separation between environments, runtime code not concerned with building options,...)

Exclude folders from builds in Brocfile

Is there a way to exclude a folder from a build in a Brocfile (or any other place).
The use case is packaging, where I have an app made of sub-apps within pods. eg.
/app/modules/components
/app/modules/app1
/app/modules/app2
/app/modules/app3
I'd like to build them all when environment is set to 'development' or only eg. 'app1' when environment is 'app1'. Any suggestions?
I have tried different combinations of broccoli-file-remover, broccoli-funnel and broccoli-merge-trees to no avail.
var removeFile = require('broccoli-file-remover');
module.exports = removeFile(app.toTree(), {
paths: ['app/modules/pod1/', 'app/modules/pod2/']
});
Ah, so after actually thinking about this clearly, everything is actually working exactly as expected in my previous example.
I clearly wasn't paying enough attention. app.toTree() is far too late to perform this operation, as everything has already been built and concated.
Luckily, ember-cli does enable addons to modify the appropriate trees at various life cycle milestones.
See: https://github.com/ember-cli/ember-cli/blob/master/ADDON_HOOKS.md for more details on which hooks are currently available.
The hook that should do the trick is Addon.prototype.postprocessTree. Now we have two choices, we can build a standalone addon, via ember addon or we can create a light-weight in-repo addon via ember g in-repo-addon. Typically for these types of situations, I prefer in-repo-addons as they don't require a second project, but otherwise they are the same.
ember g in-repo-addon remove
we need to install broccoli-stew via npm install --save broccoli-stew
include it var stew = require('broccoli-stew');
add hook postprocessTree to the add-on
when the postprocessTree is for the type we care about, use broccoli-stew to remove the directories we no longer care care.
The resulting pull request: https://github.com/WooDzu/ember-exclude-pod/pull/1
Note: I noticed template wasn't one of the types available in postprocess, so I added it: https://github.com/ember-cli/ember-cli/pull/4263 (should be part of the next ember-cli release)
Note: we really do want an additional hook
Addon.prototype.preprocessTree, as to ignore the files before we
even build them. I have opened a related issue:
https://github.com/ember-cli/ember-cli/issues/4262
output of the above steps
var stew = require('broccoli-stew');
module.exports = {
name: 'remove',
isDevelopingAddon: function() {
return true;
},
postprocessTree: function(type, tree){
if (type === 'js' || type === 'template') {
return stew.rm(tree, '*/modules/pod{1,2}/**/*');
} else {
return tree;
}
}
};
I am pretty confident broccoli-stew's rm will handle this correctly.
https://github.com/stefanpenner/broccoli-stew/blob/master/lib/rm.js#L4-L40 there are even tests that test a very similar scenario: https://github.com/stefanpenner/broccoli-stew/blob/master/tests/rm-test.js#L48-L57
var stew = require('broccoli-stew');
module.exports = stew.rm(app.tree(), 'app/modules/{pod1,pod2}');
If this doesn't work, feel free to open an issue on broccoli-stew. Be sure to provide a running example though
This is really late, but I created a Broccoli plugin to do just this. It's available at https://www.npmjs.com/package/broccoli-rm.
(The trick is to detect whether an excluded path is a folder, and then use a glob match to make sure that none of the children of the folder get symlinked during copying.)
var rm = require('broccoli-rm');
var input = app.toTree();
module.exports = output = rm([input], {
paths: ['app/modules/pod1', 'app/modules/pod2']
});

Sencha Touch - Cannot find global variable in testing and production builds

I cannot seem to access a global variable in Ext.application after I do a production or test build with Cmd 4. This happens during the first application launch. I have read other similar threads but there is nothing new in there that can solve my problem for whatever reason.
Before I started using Cmd, I would run my application from a server against the application directory, and things ran just fine. I had no problems with my other files picking up the global variables.
Now that I have moved to Cmd 4 / ST2.3.1, the test and production builds get built into one big app.js file. So it seems that when code that is earlier in the js file calls a global variable, it cannot find it, with the console exception:
Uncaught TypeError: Cannot read property 'targetServer' of undefined
This happens during the first application launch, and the app just hangs. The loading indicators are not even removed. I noticed that the Ext.application code is at the end of the app.js. Could it be some code is launching before the application is fully loaded?
In my app.js, I have the following. This is last in my app.js at line 76623. The global variable not being read is "targetServer":
Ext.application({
name: 'qxtapp',
targetServer: 'http://192.168.1.70:8080'
...
});
One of my stores looks like this. This is where I get the exception. The below code is earlier in my app.js, at line 70742:
Ext.define('qxtapp.store.AccountsListStore', {
extend : Ext.data.Store ,
xtype : 'accountsListStore',
config: {
model: 'qxtapp.model.AccountsList',
data: [
{ accountName: qxtapp.app.targetServer+'/account_one' },
// ^ Causes exception- cannot read property "targetServer"
// of undefined
{ accountName: qxtapp.app.targetServer+'/account_two' },
...
]
}
})
Any idea what I'm missing here? Any help is greatly appreciated.
Thanks!
This is an order-of-operations error.
In development, your Ext.application() code (in app.js) is run first because any other classes (e.g. qxtapp.store.AccountsListStore) are loaded dynamically after the browser physically reads app.js.
But when you use Cmd to bundle your classes together, the resulting single JS file is read entirely at once by the browser. What happens is that the Ext.define() methods all run BEFORE Ext.application()... so qxtapp.app isn't yet assigned.
The easiest way to circumvent this problem is to use a true global variable, not just a property assigned to the global "app" object (in app.js):
var TARGET_SERVER = 'http://192.168.1.70:8080';
Ext.application({
//...
})
And in your other classes...
Ext.define('qxtapp.store.AccountsListStore', {
extend : Ext.data.Store ,
xtype : 'accountsListStore',
config: {
model: 'qxtapp.model.AccountsList',
data: [
{ accountName: TARGET_SERVER + '/account_one' }
//...
]
}
});

Categories

Resources