Accessing command line arguments in runtime - javascript

I'm using the following Vue SPA boilerplate, which is based on webpack.
When the app is running in the dev server or as a deployed version, I'm able to make use of process.env.NODE_ENV to determine whether if it's a development or production build. So far so good.
What I'm after is a way to pass command line arguments that can be parsed in the same fashion, i.e. npm run dev --foo=1 and fetch it using something like process.argv.slice(2).foo.
I've tried accessing things like accessing the command line arguments using process.argv inside the config files and decorating the config files.
I have also tried passing arguments through "env" --env.foo and changing the node modules export to something like
module.exports = env => {
// make use of env
}
without success.
Am I missing something obvious?

The usual pattern for this type of thing is to maintain multiple complete configuration files and choose between them when they are loaded, even though it is arguably more concise not to.
I'll also add that while you may want a command-line flags for ergonomic reasons,
env="foo" npm run dev
and
npm run dev --env=foo
are both equally workable in most situations.

Related

Install different version of npm packages in package.json conditionally

I'm developing a web app which uses a private package.
In some circumstances, I rather to use the local version of the package or different version of that package.
Is there any solution to indicate to use different version of package in package.json?
i.e:
npm install --local
while my package.json looks like:
...
"dependencies": {
...
"my_package": if(local) "address_to_local_package/" else "5.6.1"
...
}
npm does not accommodate this (and honestly, probably should not). This seems like the type of thing that is usually handled at runtime via the NODE_ENV environment variable or similar mechanism. The module changes behavior depending on whether NODE_ENV is set to "production" or "development". (But that's just convention. You can use values like "local" if you want.) So rather than installing different versions of the module, there's a single version that behaves differently based on the value of that environment variable.
If you really want different code bases installed entirely, it will take some effort but you can write a postinstall script for npm to run. Your module then becomes nothing more than a script and then the postinstall figures out what to actually install based on environment variables or maybe a command line flag. This seems brittle to me, though. I'd think hard about if you're solving the right problem here if you go this route. NODE_ENV seems more elegant and conventional.

IBM Informix driver for NodeJS - Setting environment variables on MacOS

This is a follow on to my original question
I am trying to set up IBM's Informix driver for use with NodeJS on MacOS.
After viewing the Readme file for the Informix NPM library, I am a little confused as to what the environment variables are and whether I need to apply them all?
I managed to track down the install location for the SDK files: Applications/IBM/informix and then added this to the ~/.bash_profile file as so:
export INFORMIXDIR=/Applications/IBM/informix
export PATH=$PATH:$INFORMIDIR
Should I change my PATH to include /bin at the end?
I am also confused by the remainder of the statements in the Readme.
I was expecting to set the server name and host dynamically rather than hard-coding them?
Some guidance would be appreciated.
The PATH env variable needs $INFORMIXDIR/bin. (There is nothing in plain $INFORMIXDIR worth running other than the install script).
INFORMIXSERVER and INFORMIXSQLHOSTS may be needed for testing the module, but they are not hardcoded (the module will not store that anywhere)
You will always be able to specify a different INFORMIXSERVER/INFORMIXSQLHOSTS at runtime.
I never tried it on a MacOS, but you may also need to add DYLD_LIBRARY_PATH, something like "export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH" to your script.
Some MacOS binaries will use DYLD_LIBRARY_PATH instead of LD_LIBRARY_PATH.

Can't profile Babel-transpiled Node.js app with Spy-js in WebStorm

So me and my team are currently in the process of profiling our Node.js app to try and improve performance on it as much as we can. After doing it with Chrome's DevTools for Node.js which was not excruciatingly hard to achieve, I thought of giving Jetbrains' Spy-js a try and so far I've had no luck.
The app is run from inside a Docker container, and the code is transpiled with babel-cli on the fly so this surely complicates things a bit. Even though I could probably get it working outside Docker and somehow connect it to the other containers, I could not go as far as to try that since I haven't managed to run the app with Spy-js.
Spy-js differs from DevTools in that it doesn't just connect with the app through the native inspector's debugging port, but rather requires the app to be run from the tool so that it can also intercept and modify script execution on the fly (as per their docs).
Since I'm using babel-node to run the app, I've tried creating a new Run/Debug configuration in WebStorm pointing to it (from a fresh global install of babel-cli) as the "Node interpreter" value in the options window. I've also already added all of the app's required environment variables to the options.
With the above setup, attempting to run the new Spy-js configuration results in the following errors:
Undefined handler Super
session (ak133): Error while instrumenting '<app directory here>/node_modules/p-locate/index.js'
(g is not a function)
session (ak133): Unexpected identifier
<app directory here>/node_modules/boom/lib/index.js:249
constructor(message, options undefined {}) {
^^^^^^^^^
Which looks like it's having trouble transpiling dependencies (boom). The original source for this was options = {} so I'm not sure why it would be converted to that either.
As much as I know this is not officially supported yet, I'd really appreciate being able to get it running somehow as Spy-js seems to do its own thing and isn't just another wrapper for the native v8 profiler, so any help would be appreciated.
Try using -r babel-register instead of babel-node - does it make things any better?
Of course, you need adding .babelrc to your project, like
{
"presets": ["env"]
}

Webpack: Separate production and dev builds

I have recently started to evaluate webpack. Having used grunt previously I am used to the fact that I can start grunt with various parameters to configure what is going to happen during the build. For example:
grunt watch
would run a debug build and enable the watch task. While:
grunt build
would trigger a fully minimized production build that has all development specific functionality disabled.
I am wondering if webpack has a similar feature that lets me easily switch between different configurations. I have done some research already but I did not like the approaches I have seen so far:
I saw a suggestion to specify NODE_ENV=production before calling webpack, but this is not platform independend (e.g. does not work on windows).
Using the -p switch, but that seems to only affect minimization
Using a separate config file for webpack, but I would prefer a solution where I do not have to maintain two separate files.
I understand that webpack is not actually a task runner such as grunt or gulp, but rather a module bundler. But its being promoted as a replacement for grunt or gulp see this Medium.com Blog.
What I would really like to see is the ability to get a development build with something like webpack watch and a production build with webpack or webpack build is that possible with webpack
First of all, if you use webpack-dev-server it is quite easy to understand you are in dev mode:
let isDevMode = process.argv[1].endsWith('webpack-dev-server') || process.argv[1].endsWith('webpack-dev-server.js');
First condition is for Linux / mac, the second is for Windows.
and then use this to configure your files.
If you are not using dev server you can pass any parameter while running the webpack as you would do with any nodejs script (I use minimist to read the parameters but it is just a sugar, don't use if you don't need to):
let argv = require('minimist')(process.argv.slice(2));
let isDevMode = argv.dev; // or watch or whatever you want to pass
and then call it that way:
webpack --dev
This is actually a very flexible way of doing lots of things, not only specifying dev mode. I use it also to specify bundle names, etc. The only thing you need to care about is avoiding using the parameters which are served by webpack itself.

Javascript library uses require() but I don't have or use nodeJS?

I've encountered several JavaScript projects and libraries that use this require() function, in order to include other files, like this:
require('somefile')
I never heard of that, and apparently it's something of node.js, which I don't have and don't use.
I just intend to use these JavaScript libraries in my own websites, but I'm seeing all sorts of instructions involving "npm" (whatever that may be). Then there is supposedly a replacement for that called required.js, but that seems to use a different syntax, like forcing to use require([...]) or something whereas the projects I need to include just do require(...).
What is the easiest way to deal with this require(...) stuff when using JavaScript projects in regular html5 websites? (i.e. all supposed to run client side)
Addition: I already tried require.js, but it doesn't seem to work. For example, the first line in somelibrary.js is this:
var assert = require('assert')
when I previously included require.js, and then somelibrary.js, I'm getting this error:
Uncaught exception: Error: Module name "assert" has not been loaded
yet for context: _. Use require([])
And this happens with anything that contains require()
Another addition: I noticed people mentioning 'browserify'. And some of the js projects I'm trying to include also recommend this. Apparently this is supposed to generate one single ready to use .js file that I can Include. But
Why don't they just publish this browserified .js directly? Is there a reason why I need to compile it myself? it's supposed to be something universal for all browsers or websites, right?
This browserify thing, which is apparently to avoid node.js, actually seems to require node.js itself (the instructions all mention "npm -g install browserify" etc)
Libraries should ideally support the following, depending on its environment. Lets say you are using a library called "MyLib.js".
No module loader detected
window.MyLib
Requirejs detected
define(['MyLib'], function (MyLib) {
// Do something
return {};
});
CommonJS detected, like node or use of browserify or bower
var MyLib = require('MyLib');
Not all libs conform to this, but they should. Maybe the lib you were looking at only supports Node. Looking at the source of jQuery you see something like this:
if ( typeof module === "object" && typeof module.exports === "object" ) {
// For CommonJS and CommonJS-like environments where a proper window is present,
// execute the factory and get jQuery
// For environments that do not inherently posses a window with a document
// (such as Node.js), expose a jQuery-making factory as module.exports
// This accentuates the need for the creation of a real window
// e.g. var jQuery = require("jquery")(window);
// See ticket #14549 for more info
module.exports = global.document ?
factory( global, true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}
Node.js is now used a lot to manage JavaScript projects, even if the project is client side. For example, Grunt, Bower, Browserify, Gulp and plenty other build tools run on Node.js, even though you can use them on client-side projects. Using those tools doesn't make your project depend on Node in production. Node is only used for development. To install those tools, one uses npm, which is a package manager. Like Maven or Ivy, npm will install packages and their dependencies by downloading them from the internet.
Libraries which install instructions involve npm are meant to be used in Node, but may be used in the browser after they have been converted with Browserify. Download the library with npm, then convert it to browser style using Browserify (which you install using npm, because itself runs on Node). You should get a single JavaScript file that you can import in your client-side project.
Libraries that are especially targeted for the browser will often refer to Bower as the install method instead of npm. Bower is also a package manager, but it is designed to download and install library written for browsers, not Node. If a library you want is available on Bower, you are able to download it and all its dependencies with bower install <lib>. Bower will put all files in a bower_components folder in the current directory. You can then copy those files to your project, or make your project import them directly from this folder.
So, browserify is simply a tool which makes it possible to use node-style modules in the browser. Yes, you do need to have node.js installed in order to use npm and browserify. But these times you need node.js for the most of your frontend toolsets.
npm is full of modules that are written in JavaScript and also run in the browser. With browserify you can use these modules in the browser.
It works by shimming the whole require mechanism and making it work in the browser. This also means that you can organize your code in modules:
// add.js
module.exports = function(x, y) {
return x + y;
}
// app.js
var add = require('./add.js');
var result = add(7, 8);
Now you could generate your bundle (the only script you need to include in your html) by just running browserify app.js -o bundle.js.
If you don't like the browserify approach you can also use the --standalone option to generate a JavaScript file in the UMD format. You could then simply include this in your html and use it with window.add for the previous example.
The require statement is handled by require.js, which can be used standalone in a javascript environment. It is a module loader which optimises loading dependencies in the browser. There is a Node.js implementation for it, but that doesn't mean that you have to use Node, you can just include require in your project.
(p.s: npm is Node Package Manager, and would be unnecessary for your project unless you're using Node. It streamlines the inclusion of javascript node modules into your project.)

Categories