Will require-dir scope my dependencies to each imported file? - javascript

I'm building a gulpfile and have split up the tasks into different files. At runtime I'm requireing all tasks at once with require-dir: https://github.com/aseemk/requireDir.
The structure is identical to the gulpfile found here: https://github.com/greypants/gulp-starter:
// ./gulpfile.js
var requireDir = require('require-dir');
requireDir('./gulp/tasks', { recurse: true });
The tasks it imports look like this:
// ./gulp/tasks/browserSync.js
var browserSync = require('browser-sync');
var gulp = require('gulp');
var config = require('../config').browserSync;
gulp.task('browserSync', ['build'], function() {
browserSync(config);
});
So there's no module.exports or exports.something. Because of that, I'm wondering whether requireDir will still automatically scope the dependencies to each task. Does it scope my dependencies or am I putting everything in the global namespace when I do this?

You're not required to use module.exports in a module. If in your second file (gulp/tasks/browserSync) you were to do this:
var localValue = "bar";
globalValue = "foo";
// and we never touch module.exports
Then node will create 1 local value which is not exported and 1 value in the global namespace, but that shouldn't be surprising.
If you were to do this in gulpfile.js:
var baz = requireDir('./gulp/tasks', { recurse: true });
Then baz would be:
{
...
"browserSync": {}, // the default value of
... // `module.exports` is an object ( {} )
}
And when you do this in one of your require()'d files:
var gulp = require("gulp");
Then require will return a cached response, because it has already loaded /node_modules/gulp/ before in your main file.
So yes, since you're not making global values (everything is prefixed with var), everything is kept contained within the task files themselves.

Related

How to use and merge JS modules into 1 file?

I would like to create 1 single javascript file out of multiple files and modules to ship as one single js file for a small library that will be used in the browser (and reuse some part on nodejs).
How can I achieve this?
(function() {
// Modules are minified
var blake = require('blakejs'); // The "entire" module in here ~350 lines...
// Other files are obfuscated
// File1.js
var first = function() {}
first.prototype.doHash = function() {}
// File2.js
var second = function() {}
second.prototype.doSomethingElse = function() {}
//OtherFile.js
//Webworker.js
}).call(this)
I'm using Javascript Obfuscator to obfuscate the script, but I'd like to apply other minification/obfuscation settings to modules, as they wouldn't need obfuscation, only minification.
gulp.task('minify', function () {
return gulp
.src('./src/file1.js')
.pipe(rename({suffix: '.min'}))
.pipe(javascriptObfuscator())
.pipe(gulp.dest('public'))
})
Is it possible?

How Gulp tasks added from different files persisting

So far my understand about JS modules were,
Unless function, objects etc. is not exported from the JS module its
useless and no code in module gets executed (except direct calls ex:
console.log(), somefunction() that too if its requir()'ed by other module).
So always let module to export
something.
Also every time require('moduleName') is called new object is returned
Function, variables declared in one module not accessible from other
modules (unless exported)
But while looking at one gulp tasks implementation today i am puzzled and wanted to understand why gulp task are getting added though declared/added in other JS files.
Following is the example
project/a/a.js file
var gulp= require('gulp');
gulp.task('task:a', function(){
console.log('module:a task task:a executed')
});
module.exports = {
strA: "strA"
}
project/b/b.js file
var gulp= require('gulp');
gulp.task('task:b', function(){
console.log('module:b task task:b executed')
});
module.exports = {
strB: "strB"
}
project/gulpfile.js file
var gulp = require('gulp');
// require() called without using exported elements
require('./a/a.js');
require('./b/b.js');
gulp.task('task:in:gulpfile');
Now if you try following in command line
cmd>gulp -T
op:
...
[--:10:07] ├── task:a
[--:10:07] ├── task:b
[--:10:07] └── task:in:gulpfile
cmd>gulp task:a
module:a task task:a executed
That's because gulp is a shared instance object. When you are requiring it in your a.js and b.js, as it's being required on gulpfile.js, the shared instance gulp is called when .task method is called.
If you look at the source code here: https://github.com/gulpjs/gulp/blob/master/index.js#L63
You can see that
var inst = new Gulp();
module.exports = inst;
You can read more about that here: https://nodejs.org/api/modules.html
Pretty much when you export an instantiated object, that object is cached in require as-is. If you were to use the same require, you will be getting that same instance.

How to output files to the parent of their source directory using Webpack in Gulp?

So far I have this code, which I got from here:
var gulp = require('gulp');
var webpack = require('webpack-stream');
var named = require('vinyl-named');
gulp.task('default', function() {
return gulp.src('*/lib/app.js', { base: '.' })
.pipe(named())
.pipe(webpack())
.pipe(gulp.dest('.'));
});
My folder structure is like:
site1/lib/app.js
site2/lib/app.js
I want to create the output files like the following, with each file containing only their respective lib/app.js file's code (and any require()s made in them):
site1/app.js
site2/app.js
However, the code I have now just outputs to the project's root directory. I've tried several combinations, such as removing the { base: '.' }, but nothing works. If I remove the named() and webpack() pipes, though, then the current code actually outputs to the correct directory. So, in the process, it seems like perhaps Webpack loses the originating directory information?
Also, it possible to get a solution that also works with Webpack's "watch: true" option, so that compiling modified files is quick, rather than using Gulp to always iterate through every single file on every file change?
I assume you want to create a app.js for each site that packs only the code for that site (and not the others).
In that case you can use gulp-foreach to effectively iterate over all your app.js files and send each one down its own stream. Then you can use the node.js built-in path module to figure out where the parent directory for each app.js file is and write it there with gulp.dest().
var gulp = require('gulp');
var webpack = require('webpack-stream');
var named = require('vinyl-named');
var foreach = require('gulp-foreach');
var path = require('path');
gulp.task('default', function() {
return gulp.src('*/lib/app.js')
.pipe(foreach(function(stream, file) {
var parentDir = path.dirname(path.dirname(file.path));
return stream
.pipe(named())
.pipe(webpack())
.pipe(gulp.dest(parentDir));
}));
});
If you want to use webpack({watch:true}) you'll have to use a different approach. The following uses glob to iterate over all the app.js files. Each app.js file is again send down its own stream, however this time all the streams are merged before being returned.
var gulp = require('gulp');
var webpack = require('webpack-stream');
var named = require('vinyl-named');
var path = require('path');
var merge = require('merge-stream');
var glob = require('glob');
gulp.task('default', function() {
return merge.apply(null, glob.sync('*/lib/app.js').map(function(file) {
var parentDir = path.dirname(path.dirname(file));
return gulp.src(file)
.pipe(named())
.pipe(webpack({watch:true}))
.pipe(gulp.dest(parentDir));
}));
});

Why Javascript function coming undefiend after compiling from webpack?

Hi i have used webpack to load my different modules into one bundle.js file , different function from this files are coming undefined in html but if call the same in my entry file ther working or making winndow.fnName .
here is my code
Test.js
var test=function(msg){
console.log(msg)}
module.exports=test;
lib.js
var lib=function(msg){console.log(msg)}
module.exports=lib;
Entire JS
var lib=require('./lib.js');
var test=require('./test.js');
index.html
test("test called");
lib("lib also called");
In output file created by webpack your code for Entire JS will look something like this:
/*****/
/* 0 */
/*****/ function(module, exports, __webpack_require__) {
'use strict';
var lib = __webpack_require__(1); // require('./lib.js')
var test = __webpack_require__(2); // require('./test.js');
/*****/ },
And since your variables lib and test are defined in function they aren't assign to window object.
You can workaround to export your lib and test to window object (I made this assumption based on that you want to use this variables in html file), by doing this:
var lib = require('./lib.js');
var test = require('./test.js');
window.lib = lib;
window.test = test;

Ordening files in Grunt with external file

I'm configuring Grunt with grunt-contrib-concat to concatenate like 20 javascript files. They have to be in a specific order and I'm wondering if there is a neat way to do this, without messing up my Gruntfile.js.
What I did and what worked well, was declaring an variable called 'libraries' with a function which returned a string with all the files in the right order.
var libraries = new (function () {
return [
'/javascript/libs/jquery.min.js',
'/javascript/libs/jquery.address.js',
'/javascript/libs/jquery.console.js'
];
});
And then concat (simplified, just an example):
concat: {
libs: {
files: {
'libs.js' : [libraries],
},
},
main: {
files: {
'main.js' : [main]
}
}
},
So when I call 'libraries' in my task configuration everything works fine, but I would like to declare this list in a separate file.
Unfortunately I couldn't find anything, nor do I know if this is even possible. Hope that someone could help me out! Thanks in advance :-)
I found a solution! Since Grunt is build on NodeJS, it's possible to use module.exports. What I did was setting an external file called libraries.js, which is in my Grunt directory.
var exports = module.exports = {};
exports.customLibrary = function () {
return [
// Path to a library
// Path to another library
// and so on...
];
};
exports.mainScripts = function () {
return [
// Path to a library
// Path to another library
// and so on...
];
};
Then I import this module by declaring a variable in Gruntfile.js
var libraries = require('../javascript/libraries.js');
To use the methods declared in libraries.js I set two more variables which returns a string with all the necessary files in the desired order:
var customLibrary = libraries.customLibrary();
var mainScripts = libraries.mainScripts();
I use these variables to define the source in the concat task. Hope this is helpful!

Categories