I have a node module file which I have broswerifed using browserify
// myMath.js file
// --------------
module.exports = {
add: function(a, b){
return a + b;
}
}
Now to use it in another JavaScript application, I am using following code
// index.js file
// -------------
var myMath = require("./myMath");
var result = myMath.add(1, 2);
console.log("the result is", result);
Now I am using broswerify:
browserify index.js -o app.js
But this apporach requires involving index.js file as well. Is there any way to directly include broswerified myMath.js file into my JavaScript application ??
Related
My Project structure looks like this -
src
|- main.js
|- math.js
math.js is just an AMD module and I am requiring it in main.js
I have installed require.js using npm and requiring it in main.js
//main.js
var rjs = require('requirejs');
rjs.config({
//Pass the top-level main.js/index.js require
//function to requirejs so that node modules
//are loaded relative to the top-level JS file.
nodeRequire: require,
});
rjs(["./math.js"], function(math) {
console.log(math.add(2, 3));
});
//math.js
define("math", function() {
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
function divide(a, b) {
return a / b;
}
return { add, subtract, multiply, divide };
});
While running r.js ./src/main.js, I am getting the below error.
rjs.config is not a function
at /Users/dheerajmahra/Desktop/learning/different-module-formats/src/main.js:3:5
at /Users/dheerajmahra/Desktop/learning/different-module-formats/src/main.js:14:2
at Script.runInThisContext (vm.js:96:20)
at Object.runInThisContext (vm.js:303:38)
....
Based of reading the requirejs-docs, it seems that you are conflating the two approaches here, one being through the node-package, the other one being through the r.js standalone file.
It seems like you either haven't done npm i requirejs or, you are not running through the node process.
If you are using the r.js file directly, replace require('requirejs') with require('./path/to/r.js').
I am using gulp to concatenate and minify a number of standalone *.js scripts used on my web site. Basically this is just a catchall folder where I place little utility scripts that run on page load. For example, one of them starts a carousel slider, another adds a class to the header that shrinks it on scroll, etc. Each of these "features" has its own standalone *.js file.
Now, I would like to use the popular js-cookie library in one of those scripts. Unfortunately, since my project is not set up as an ES6 module, I am not able to able to import the js-cookie library the way it's specified in the docs, like this:
import Cookies from 'js-cookie'
When I do this, I get the error message Uncaught SyntaxError: Cannot use import statement outside a module.
I tried changing it to this:
window.Cookies = require('js-cookie')
but that gave me this error:
Uncaught ReferenceError: require is not defined
Here is my gulpfile, followed by the feature.js script in which I'm trying to use the js-cookie library:
gulpfile.js
// Initialize modules
const { src, dest, watch, series, parallel } = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
var replace = require('gulp-replace');
var merge = require('merge-stream');
// File paths (note that src paths are arrays)
const files = {
scssSrcPath: [
'scss/*.scss',
'scss/_pageContentModules/*.scss'
],
jsSrcPath: [
'js/*.js',
'node_modules/slick-carousel/slick/slick.js'
],
scssDstPath: '../web/css',
jsDstPath: '../web/js'
}
// Sass task: compiles SCSS files into style.css
function scssTask(){
return merge(files.scssSrcPath.map(function (file) {
return src(file)
}))
.pipe(sourcemaps.init()) // initialize sourcemaps first
.pipe(sass()) // compile SCSS to CSS
.pipe(postcss([ autoprefixer(), cssnano() ])) // PostCSS plugins
.pipe(sourcemaps.write('.'))
.pipe(dest(files.scssDstPath));
}
// JS task: concatenates and uglifies JS files to script.js
function jsTask(){
return merge(files.jsSrcPath.map(function (file) {
return src(file)
}))
.pipe(concat('app.js'))
.pipe(uglify())
.pipe(dest(files.jsDstPath));
}
// Watch task: watch SCSS and JS files for changes
// If any change, run scss and js tasks simultaneously
function watchTask(){
watch(files.scssSrcPath, scssTask);
watch(files.jsSrcPath, jsTask);
}
// Export the default Gulp task so it can be run
// Runs the scss and js tasks simultaneously
// then watch task
exports.default = series(
parallel(scssTask, jsTask),
watchTask
);
js/feature.js
import Cookies from 'js-cookie';
const rs = cookies.get('referral_source');
if (typeof rs !== 'undefined') {
console.log('referral_source = ' + rs);
}
How can I get this working? Is there a way to do it using my simple Gulp setup, or do I need to go beyond and set up a full-on Webpack setup (with all the complexity that adds)?
Unfortunately, as far as I know, Gulp does not support the ability to use ES6 modules. If you want to use them, you will need to use Webpack.
But js-cookie does have a jsDelivr CDN: <script src="https://cdn.jsdelivr.net/npm/js-cookie#3.0.1/dist/js.cookie.min.js"></script>. By including this before your JS script, like this:
<script src="https://cdn.jsdelivr.net/npm/jscookie#3.0.1/dist/js.cookie.min.js"></script>
<script src="./js/feature.js"></script>
I am enumerating the subdirectories in a directory. For each sub directory I would like to apply a number of gulp activities like less compilation, and then create an output file specific to that subdirectory.
I would like the gulp process to continue, as further transformation steps need to be performed later.
Can someone help me understand how I can create these files half way through the "gulp pipeline"?
This seems quite interesting to achieve and gulp has no limitations at all.
I will give you detailed example how I have managed to accomplish such a task a while ago.
Let assume that you have directoryA. Subdirectories childA, childB and childC are contained into directoryA. So basically your tree structure looks like:
directoryA
--childA
--childB
--childC
I am always looking for a flexible solutions so I would suggest to include a JSON file in each subdirectory naming the tasks you would like to running. Using fs you can access these files. You can also use run-sequence to execute gulp tasks synchronously.
For demo purposes place a file named manifest.json inside childA subdirectory.
Manifest.json contains the following declarations:
{
"filesToProccess" : ["./childA/*.js", "./childB/*.js"],
"tasksToRun" :["taskA", "taskB"]
}
Finally gulpfile would like this:
'use strict';
//dependencies declared into package.json
//install them using npm
var gulp = require('gulp'),
fs = require('fs'),
runSequence = require('run-sequence'),
path = require('path');
//these two array will keep the actions you have included into manifest file.
var filesHolder = [], tasksHolder = [];
gulp.task('taskA', function () {
return gulp.src(filesHolder)
.pipe(whatever)
.pipe(gulp.dest('whatever')); //chailed actions
});
gulp.task('taskB', function () {
return gulp.src(filesHolder)
.pipe(whatever)
.pipe(gulp.dest('whatever'));
});
//a simple utility function to read all subdirectories of directoryA
function getDirectories(srcpath) {
return fs.readdirSync(srcpath).filter(function(file) {
return fs.statSync(path.join(srcpath, file)).isDirectory();
});
}
//finally insert the default gulp task
gulp.task('default', function(){
var manifest;
//map directory's A subdirectories
var availableDirs = getDirectories("./directoryA");
//finally loop the available subdirectories, load each manifest file and
availableDirs.forEach(function(subdir) {
manifest = require("./directoryA/"+subdir+"manifest.json");
filesHolder = manifest.filesToProccess;
tasksHolder = manifest.tasksToRun;
runSequence( tasksHolder , function () {
console.log( " Task ended :" + tasksHolder + " for subdirectory : " + subdir);
});
});
});
I use Gulp to build a small web application based on the React framework.
To compile the client scripts, my task starts like that :
gulp.task( 'buildClientScripts', function () {
// Get all the js and jsx scripts
// Starts with the app.js file
return gulp.src( [
'app/app.js',
'app/clientScripts/**/*.jsx',
'app/clientScripts/**/*.js',
] )
The order of the files is my problem. For this file structure :
- clientScripts
---- components
-------- subComponents
------------ mysubComponent.js
-------- myComponent.js
---- main.js
The load order will be : main.js, myComponent.js, mysubComponent.js. But obviously, my top files need the deeper files to work.
How do I ask gulp to load the deepest files first ?
You can use gulp-sort to order the files after gulp.src reads them.
Count slashes in path as crude way to determine depth.
var sort = require('gulp-sort');
var path = require('path');
gulp.task( 'buildClientScripts', function () {
// Get all the js and jsx scripts
// Starts with the app.js file
return gulp.src( [
'app/app.js',
'app/clientScripts/**/*.jsx',
'app/clientScripts/**/*.js',
] )
.pipe(sort(function(file1, file2) {
return countSlashes(file2) - countSlashes(file1);
function countSlashes(file) {
return file.path.split(path.sep).length - 1;
}
})
I have a library lib.js that I want to create from lib/a.js and lib/b.js and to be able to use it from a script client.js using var a = require('lib/a.js'); and that it works when I just include the compiled lib.js library before client.js (therefore, lib.js has to declare a require function that knows about lib/a.js)
I guess I have to use external and alias but I am not sure what is the proper way to do it
Also, is it possible to have a Gulp file that creates all the alias automatically for the folders in my library? eg. creates an alias for all the files in the lib/ dir?
Here are a couple of gulp tasks that would help to build your common lib.js and the client.js bundles separately.
Note that you have to tell browserify to b.require() lib/*.js when bundling lib.js, and you have to tell it to b.external() the libraries that will be loaded separately when bundling client.js
var path = require('path');
var gulp = require('gulp');
var browserify = require('browserify');
var concat = require('gulp-concat');
var transform = require('vinyl-transform');
gulp.task('build-lib', function () {
// use `vinyl-transform` to wrap around the regular ReadableStream returned by b.bundle();
// so that we can use it down a vinyl pipeline as a vinyl file object.
// `vinyl-transform` takes care of creating both streaming and buffered vinyl file objects.
var browserified = transform(function(filename) {
// basename, for eg: 'a.js'
var basename = path.basename(filename);
// define the exposed name that your client.js would use to require();
// for eg: require('lib/a.js'); // -> exposed name should be 'lib/a.js'
var expose = 'lib/' + basename;
return browserify(filename)
.require(filename, { expose: expose})
.bundle();
});
return gulp.src(['./lib/*.js'])
.pipe(browserified)
.pipe(concat('lib.js'))
.pipe(gulp.dest('./dist'));
});
gulp.task('build-client', function () {
var browserified = transform(function(filename) {
// filename = './client.js'
// let browserify know that lib/a.js and and lib/b.js are external files
// and will be loaded externally (in your case, by loading the bundled lib.js
// for eg: <script src='dist/lib.js'>)
return browserify(filename)
.external('lib/a.js')
.external('lib/b.js')
.bundle();
});
return gulp.src(['./client.js'])
.pipe(browserified)
.pipe(gulp.dest('./dist'));
});
gulp.task('default', ['build-lib', 'build-client']);
Are you looking for external requires?
To use with gulp-browserify, check the README
.on('prebundle', function(bundle) {
bundle.external('domready');
bundle.external('react');
})
Should work with bundle.require as well.