How to pass browserify --require file to angular module? - javascript

I have engineered a build for an Angular SPA using NPM to call the browserify script to bundle it, i.e. you can run from the terminal npm run build:js which calls the following script in package.json:
"build:js": "browserify -r ./params-dev.js -e src/app/index.js -o build/index.js"
What I'm trying to do now is to create two different config objects for prod and QA. Each one will require a different file: params-dev.js or params-prod.js (like in the command above).
I am wondering how to access these variables in the resulting bundle? They are environment specific and some of it points to analytics codes, etc. Furthermore, I'm trying to move them out of the global scope, where they currently live.
Here is a sample of the params files I'd like to include with the bundles. There will be one for prod and one for QA:
var merge = require('merge'),
params = require('./params')
exports.config = merge(params, {
env: 'prod',
analyticsCode: 'blah08yweblah2e823lnblah',
otherProps: '...etc...'
})
So how do I access these variables now in my AngularJS module? I feel like I'm missing something obvious here.
Anyone have any ideas? Please let me know if you need more info.
In case it helps, my index.js looks like
(function () {
// common app require statements
require('blah')
require('blah-2')
angular.module('app', [require('angular-route')])
// etc etc
})()

I figured it out. :) If I add the target to the end of the required file path in the command like so:
"build:js": "browserify -r ./params-dev.js:params -e src/app/index.js -o build/index.js"
I can access the object by adding var params = require('params') to my angular file.

Related

Pass command line arguments to NodeJS script from NPM script

I have a main script (publish-all.js) from which I want to invoke the npm publish script of an Angular project, which also has a sub-script (publish.js that does general stuff (creating folders, copying files, moving folders...) after ng build.
I need to pass some environment variables to that second script.
I am using shelljs to run unix-like commands.
I tried using:
npm run publish -- VERSION=${productVersion} DESTDIR=${productDestinationPath}
From publish-all.js where productVersion and productDestinationPath are constants declared above that line, and which invokes the following script from the package.json:
"publish": "ng build --prod && node ./scripts/publish.js"
But the actual command line I get is
ng build --prod && node ./scripts/publish.js "VERSION=value" "DESTDIR=value"
Finally, in my publish.js script I tried getting those variables the following way:
let version = process.env.VERSION;
let destinationPath = process.env.DESTDIR;
But I get undefined values.
What am I doing wrong? Is the a better way of doing all this?
Should I maybe use process.argv instead??
I am using this strategy because it is what I were told to do, but I would like to know if there is a less confusing way.รง
EDIT 2021-07-13
I tried using export (with shelljs, since I am in Windows and using powershell) but I am getting an exception.
I have the following code in publish-all.js now:
shelljs.exec(`export VERSION=${productVersion}`);
shelljs.exec(`export DESTDIR=${productDestinationPath}`);
shelljs.exec('npm run publish');
And in the publish.js script from the ANGULAR project:
version = process.env.VERSION;
destinationPath = process.env.DESTDIR;
Though it does not get to publish.js. It gets stuck in the shelljs.exec('npm run publish'), with the following exception:
I had to hide the project folder because of privacy policies, but it is a subfolder inside the folder where I am executing publish-all.js.
Environmental variables go BEFORE the command. So, instead of passing them after you can add them BEFORE:
VERSION=${productVersion} DESTDIR=${productDestinationPath} npm run publish
Or,
You can export the variables first then run the script:
export VERSION=${productVersion}
export DESTDIR=${productDestinationPath}
npm run publish

Accessing module.exports with a browserified node app

We are trying to Browserify our node app
Sample File (index.js)
module.exports = {
index: () => 'test',
};
Browserify command
browserify src/index.js > dist/bundle.js --node
If we use a file to require and console
console.log(require('src/index')); // { index: [Function: index] }
console.log(require('dist/bundle')); // { }
Our expectation is that bundle.js would export the same as index.js.
Can anyone point us at what we are doing wrong or missing?
Additional Info
~This is not our app, this is a sample to demonstrate the issue
We are currently sending our entire app zipped to AWS Lambda with the entry point src/index.index and the objective is to just send the bundle.js file and be able to to have the entry point bundle.index
bundle.js
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
module.exports = {
index: () => 'test',
};
},{}]},{},[1]);
You need to use the --standalone flag. If I reproduce the setup you describe in your question and execute:
$ browserify src/index.js --standalone mylib > dist/bundle.js
Then I can run an interactive Node session on it and use the library in the way you expect it to be used:
$ node
> require("./dist/bundle").index()
'test'
The --standalone flag tells Browserify to wrap your code in a UMD stub which allows loading the bundle as CommonJS module, an AMD module, or as a plain script (i.e. does not use a module system). The argument you pass with --standalone indicates what name your library will take in the "plain script" case. So in the example above, if you were to load the library in a browser without any module system, you'd be able to run index as mylib.index().
You can use serverless for this, pretty easy to configure. No need to use browserify cli for this.
Keep following following official documentations to setup serverless cli.
Installation
AWS - Credentials
Quick Start
Once everything is setup and you are able to deploy your lambda functions to AWS using serverless cli. Follow following steps to setup browserify.
Install browserify as a dev dependecy.
Install serverless-plugin-browserifier as a dev dependency.
Add the plugin to your serverless.yml file and set package.individually to true. (Ref)
plugins:
- serverless-plugin-browserifier
package:
individually: true
Note: Personally tried this and is working.

browserify and babelify very slow due to large data js files

I have a nodejs project which uses large dictionary lists (millions of entries), stored in js files, that look like this:
module.exports = ["entry1", "entry2", "entry3", "entry4", "entry5", etc.];
and then I use them from the other files like this:
var values = require('./filePath');
This works great and it works in the browser too (using browserify), however bundling takes ages - about 10 minutes.
I use the following command to create the bundle:
browserify "./src/myModule.js" --standalone myModule -t [ babelify --presets [ es2015 stage-2 ] --plugins ["transform-es2015-classes", {"loose": true}]
I have tried to avoid parsing of my dictionary js files using --noparse ["path1", "path2", "path3", etc.] but it did not make any difference.
Ideally I would like to just speed up the browserify\babelify process, however if that's not possible I would be very happy to find another way (ie. avoid require) to store and use my lists, so that they don't slow the process down but that crucially work in node and in the browser too.
You can bundle the data files separately, so you'll only need to rebundle them when they change. This is possible using the --require -r and --external -x options.
To create the data bundle, do something like this:
browserify -r ./path/to/data.js -r ./path/to/other/data.js > data-bundle.js
The resulting data-bundle.js will define the require function globally which can be used to obtain any file you listed in the command above. Just make sure you include this bundle in a script tag before your main bundle.
It would be nice to be able to --require a glob pattern, but unfortunately browserify does not support this. If you try to use the shell to expand a pattern, the -r option will only apply to the first, which sucks. You can probably write a shell script that builds a command from an ls or something, to avoid having to list all of the data files explicilty, but that's beyond the scope of the question, I think.
To create your main bundle without rebuilding the data files, simply add an option like this to your command:
-x './path/to/data/*.js'
This tells browserify to basically ignore them and let them be pulled in through the global require function created by your other bundle. As you can see, this does support glob patterns, so it's a bit easier.
Update:
To make the two bundles into one, just put something like this at the end of a shell script that starts with the browserify command that builds your main bundle:
cat data-bundle.js main-bundle.js > bundle.js
rm main-bundle.js
Unfortunately this will always have to write a copy of data-bundle.js to disk, which may be the ultimate cause of the slowdown, as I mentioned in the comments below. Worth giving a shot, though.
If even that doesn't work, there are some other, much more hacky approaches you might take. I'll pass on going into those for now though, because I don't think they're worth it unless you absolutely must have it as one file and have no other way of doing it. :\
If you have files with data - just load them in separate way and don't include them into build process
Format your big data files as JSON
On the server use:
let fs = require('fs');
let yourContent = JSON.parse(fs.readFileSync('path/to/file'));
On client use:
let request = require("client-request"); // do npm install client-request
var options = {
uri: "http://.com/path/to/file",
json: true
}
var req = request(options, function callback(err, response, body) {
console.log(response.statusCode)
if (body) {
let yourContent = body
}
})
Or use any other library which makes HTTP request which you prefer

uglifyjs-folder remove console.log & alert from minified files

I am minifying multiple files in a folder using uglifyjs-folder in npm package.json like :
"uglifyjs": "uglifyjs-folder js -eyo build/js"
It is working as intended & minify all files in folder.
I want to remove any console.log & alert while minify but not able to find any option with uglifyjs-folderhttps://www.npmjs.com/package/uglifyjs-folder
Please help.
Short Answer
Unfortunately, uglifyjs-folder does not provide an option to silence the logs.
Solution
You could consider writing a nodejs utility script which utilizes shelljs to:
Invoke the uglifyjs-folder command via the shelljs exec() method.
Prevent logging to console by utilizing the exec() methods silent option.
The following steps further explain how this can be achieved:
Install
Firstly, cd to your project directory and install/add shelljs by running:
npm i -D shelljs
node script
Create a nodejs utility script as follows. Lets name the file: run-uglifyjs-silently.js.
var path = require('path');
var shell = require('shelljs');
var uglifyjsPath = path.normalize('./node_modules/.bin/uglifyjs-folder');
shell.exec(uglifyjsPath + ' js -eyo build/js', { silent: true });
Note: We execute uglifyjs-folder directly from the local ./node_modules/.bin/ directory and utilize path.normalize() for cross-platform purposes.
package.json
Configure the uglifyjs script inside package.json as follows:
{
...
"scripts": {
"uglifyjs": "node run-uglifyjs-silently"
...
},
...
}
Running
Run the script as per normal via the command line. For example:
npm run uglifyjs
Or, for less logging to the console, add the npm run --silent or shorthand equivalent -s option/flag. For example:
npm run uglifyjs -s
Notes:
The example gist above assumes that run-uglifyjs-silently.js is saved at the top-level of your project directory, (i.e. Where package.json resides).
Tip: You could always store run-uglifyjs-silently.js in a hidden directory named .scripts at the top level of your project directory. In which case you'll need to redefine your script in package.json as follows:
{
...
"scripts": {
"uglifyjs": "node .scripts/run-uglifyjs-silently"
...
},
...
}
uglify-folder (in 2021, now?) supports passing in terser configs like so:
$ uglify-folder --config-file uglifyjs.config.json ...other options...
and with uglifyjs.config.json:
{
"compress": {
"drop_console": true
}
}
And all options available here from the API reference.

How to use npm modules on grunt?

Earlier when I was using node.js without grunt I had to simply write the following code to include an external module.
var express = require('express');
After I switched to grunt I am trying to use the following module qr-image.
I am stuck with the use of this module as whenever I use the following command my code breaks.
[ This is as per an official example. ]
var qr = require('../');
To Install this module in my node_modules directory I changed the package.json by adding the following dependency in
"devDependencies": {
.
.
.
"qr-image": "^2.0.0"
},
And then ran npm install command at the root directory level of my app.
Thus, Stuck with the implementation of this node.js qr-image module on grunt. Any help will be appreciated.
I believe the right way to do this is:
var qr = require('qr-image');
You can find an example in the project's readme.

Categories