Can i use wild card with browserify require? - javascript

Currently for loading a module in a folder, i need to explicitly call each file:
require('path/to/file/someFile.js')
Is there a way to require all modules in a folder using a wild card? something like:
require('path/to/file/*.js')

You can use a browserify transform such as bulkify:
var bulk = require('bulk-require');
var whatever = bulk(__dirname, [ '*.js' ]);

Related

Gulp- Versioning for javascript files

I am doing bundling and minification for javascript files. I am doing this using gulp. Now I want that if I make any change in any of my file and hit gulp then it generate a new bundled and minified file with version number like:
<script src="https://cdn.test.com/bundle-1.0.0-min.js/"></script>
then
<script src="https://cdn.test.com/bundle-1.0.1-min.js/"></script>
I want to do this using gulp because I am already using gulp for other purposes. And one more thing if this is possible then is there any way that I don't specify version no in my html page every time I make a change and my html page get the latest version by its own somehow.
This is just a rename of the file in general. But this should really not be an automated task to increment the version number. Otherwise you will be quickly getting a version like 1.0.2092 what is not helpful. I would suggest to read the version out of the package.json and use it for the name of the file. Should be pretty easy, if you already worked with gulp.
If you don't want to use the global version (version entry) of your package.json, you could add an own entry for your bundle version. Or even use a different file than package.json. You could even use that as config for which files should be bundled, to have everything in one place:
{
"bundle": {
"version": "1.0.1",
"files": [
"path/to/file-one.js",
"another/file.js",
"..."
]
}
}
Just a quick example:
var pkg = require("./package.json");
var gulp = require("gulp");
var rename = require("gulp-rename");
gulp.src(pkg.bundle.files)
.concat("bundle.js")
.pipe(uglify())
.pipe(rename(function(path) {
path.extname = "-" . pkg.bundle.version + "-min" + path.extname;
}))
.pipe(gulp.dest("./"));
Note: instead of rename you can just set the concat name, but I like to split this. But just to be complete:
.concat("bundle-" + pkg.bundle.version + "-min.js")
About the second parts of your question, to replace things in your files:
This would be possible if you build your html pages too, and replace/inject the relevant path into it. You could use the version of the package.json again, to build it and replace. Or use tools like gulp-inject. That simple tool can add js and css files into your html templates. Just create an area where they should be placed in the html file, like: <!-- inject:js --><!-- endinject -->. Afterwards it is a simple gulp taks too:
var pkg = require("./package.json");
var gulp = require("gulp");
var inject = require("gulp-inject");
gulp.src("dev/index.html")
.pipe(inject("bundle-" + pkg.bundle.version + "-min.js"))
.pipe(gulp.dest("prod/"));

How to set up gulp to bundle several files into one?

This seems like a very simple question, but spent the last 3 hours researching it, discovering it can be slow on every save on a new file if not using watchify.
This is my directory tree:
gulpfile.js
package.json
www/
default.htm
<script src="toBundleJsHere/file123.js"></script>
toBundletheseJs/
componentX/
file1.js
componentY/
file2.js
componentZ/
file3.js
toPutBundledJsHere/
file123.js
Requirements.
On every creation or save of a file within the folder toBundleTheseJs/ I want this file to be rebundled into toBundleJsHere/
What do I need to include in my package.json file?
And whats the minimum I need to write into my gulp file?
This should be as fast as possible so think I should be using browserify and watchify. I want to understand the minimum steps so using package manager like jspm is overkill a this point.
thanks
First you should listen to changes in the desired dir:
watch(['toBundletheseJs/**/*.js'], function () {
gulp.run('bundle-js');
});
Then the bundle-js task should bundle your files. A recommended way is gulp-concat:
var concat = require('gulp-concat');
var gulp = require('gulp');
gulp.task('bundle-js', function() {
return gulp.src('toBundletheseJs/**/*.js')
.pipe(concat('file123.js'))
.pipe(gulp.dest('./toPutBundledJsHere/'));
});
The right answer is: there is no legit need for concatenating JS files using gulp. Therefore you should never do that.
Instead, look into proper JS bundlers that will properly concatenate your files organizing them according to some established format, like commonsjs, amd, umd, etc.
Here's a list of more appropriate tools:
Webpack
Rollup
Parcel
Note that my answer is around end of 2020, so if you're reading this in a somewhat distant future keep in mind the javascript community travels fast so that new and better tools may be around.
var gulp = require('gulp');
var concat = require('gulp-concat');
gulp.task('js', function (done) {
// array of all the js paths you want to bundle.
var scriptSources = ['./node_modules/idb/lib/idb.js', 'js/**/*.js'];
gulp.src(scriptSources)
// name of the new file all your js files are to be bundled to.
.pipe(concat('all.js'))
// the destination where the new bundled file is going to be saved to.
.pipe(gulp.dest('dist/js'));
done();
});
Use this code to bundle several files into one.
gulp.task('scripts', function() {
return gulp.src(['./lib/file3.js', './lib/file1.js', './lib/file2.js']) //files separated by comma
.pipe(concat('script.js')) //resultant file name
.pipe(gulp.dest('./dist/')); //Destination where file to be exported
});

Node.js utility module structure

While working on many differente Node.js projects, I began having common code that I want to move out in a new Node.js package in order to not rewrite the same code multiple times. I've a new Node.js module and I'm using it in my projects using npm link.
Now, I'm a bit confused as to how to structure this common library in order to properly modularize it. This is what I have right now in my common library:
// "my-common-lib"'s app.js
module.exports = {
math: require("./math/mathLib"),
network: require("./network/networkLib")
};
--
//mathLib.js
exports.pi = 3.14;
This works, I can do the following in another node.js project:
var commonLibrary = require("my-common-lib");
var commonMath = commonLibrary.Math;
console.log("Pi: " + commonMath.pi);
While this solves the issue, I would prefer something similar to how lodash does it:
var commonMath = require("my-common-lib/math");
console.log("Awesome pi: " + commonMath.pi);
I can't quite figure out how lodash does it, and I would definitely like to avoid having a humongous main js file.
TL;DR I want to modularize a node.js module so I can require submodules (require("my-common-lib\myCommonMathLib")), how can I do this?
lodash does it with a dedicated modular build. Look at the ES6 build for example. Every "sub-project" has a dedicated module, in a dedicated '.js' file. The aggregating file (lodash.js) simply imports all other modules.
If you want the nice lib/module convention, simply have a your lib.js file (aggregator) at the top level, next to a directory by the same name where all internal modules are kept.
Another option for the require("lib") part is to have a "main": "lib.js" configuration in your package.json
If you want to use lodash/array for example, LoDash has an array.js file, with the following:
module.exports = {
'chunk': require('./array/chunk'),
'compact': require('./array/compact'),
So you can easily have math.js inside your main folder, which has something like:
module.exports = {
pi: 3.14
// OR
pi: require('./math/pi'); // and have file pi.js inside math folder
}
This way you can use it as a short:
var math = require('my-common-lib/math');
math.pi; // 3.14

How does one specify a custom search path with Browserify?

I have a large project that consists of hundreds of source files broken into several folders.
Something like this:
src/
AAA.js
subdir/
DDD.js
I would like to be able to specify dependencies with non-relative paths.
For instance, in DDD.js I would like to do this:
var AAA = require('AAA');
...rather than this:
var AAA = require('../AAA');
How can I achieve this with Browserify?
As stated in the documentation, Browserify uses browser-resolve under the hood.
When using the node API (as opposed to the CLI), you can specify a paths option which contains a list of directories to pass to browser-resolve.
The solution for my example would thus be something like this:
var browserify = require('browserify');
var b = browserify({
paths: [
__dirname + '/src'
]
});
b.add(__dirname + '/src/AAA.js');
b.bundle().pipe(process.stdout);
Or if you want to do it from the command line you can add your directory to the node search path:
NODE_MODULES=$NODE_MODULES:src browserify -o output.js input.js

Compiling dynamically required modules with Browserify

I am using Browserify to compile a large Node.js application into a single file (using options --bare and --ignore-missing [to avoid troubles with lib-cov in Express]). I have some code to dynamically load modules based on what is available in a directory:
var fs = require('fs'),
path = require('path');
fs.readdirSync(__dirname).forEach(function (file) {
if (file !== 'index.js' && fs.statSync(path.join(__dirname, file)).isFile()) {
module.exports[file.substring(0, file.length-3)] = require(path.join(__dirname, file));
}
});
I'm getting strange errors in my application where aribtrary text files are being loaded from the directory my compiled file is loaded in. I think it's because paths are no longer set correctly, and because Browserify won't be able to require() the correct files that are dynamically loaded like this.
Short of making a static index.js file, is there a preferred method of dynamically requiring a directory of modules that is out-of-the-box compatible with Browserify?
This plugin allows to require Glob patterns: require-globify
Then, with a little hack you can add all the files on compilation and not executing them:
// Hack to compile Glob files. Don´t call this function!
function ಠ_ಠ() {
require('views/**/*.js', { glob: true })
}
And, for example, you could require and execute a specific file when you need it :D
var homePage = require('views/'+currentView)
Browserify does not support dynamic requires - see GH issue 377.
The only method for dynamically requiring a directory I am aware of: a build step to list the directory files and write the "static" index.js file.
There's also the bulkify transform, as documented here:
https://github.com/chrisdavies/tech-thoughts/blob/master/browserify-include-directory.md
Basically, you can do this in your app.js or whatever:
var bulk = require('bulk-require');
// Require all of the scripts in the controllers directory
bulk(__dirname, ['controllers/**/*.js']);
And my gulpfile has something like this in it:
gulp.task('js', function () {
return gulp.src('./src/js/init.js')
.pipe(browserify({
transform: ['bulkify']
}))
.pipe(rename('app.js'))
.pipe(uglify())
.pipe(gulp.dest('./dest/js'));
});

Categories