Using Gulp to build requireJS project - gulp-requirejs
Asked Answered
B

7

21

I am trying to use gulp-requirejs to build a demo project. I expect result to be a single file with all js dependencies and template included. Here is my gulpfile.js

var gulp = require('gulp');
var rjs = require('gulp-requirejs');
var paths = {
  scripts: ['app/**/*.js'],
  images: 'app/img/**/*'
};

gulp.task('requirejsBuild', function() {
    rjs({
        name: 'main',
        baseUrl: './app',
        out: 'result.js'
    })
    .pipe(gulp.dest('app/dist'));

});

// The default task (called when you run `gulp` from cli)
gulp.task('default', ['requirejsBuild']);

The above build file works with no error, but the result.js only contains the content of main.js and config.js. All the view files, jquery, underscore, backbone is not included.

How can I configure gulp-requirejs to put every js template into one js file? If it is not the right way to go, can you please suggest other method?

Edit

config.js

require.config({
    paths: {
        "almond": "/bower_components/almond/almond",
        "underscore": "/bower_components/lodash/dist/lodash.underscore",
        "jquery": "/bower_components/jquery/dist/jquery",
        "backbone": "/bower_components/backbone/backbone",
        "text":"/bower_components/requirejs-text/text",
        "book": "./model-book"
    }
});

main.js

// Break out the application running from the configuration definition to
// assist with testing.
require(["config"], function() {
    // Kick off the application.
    require(["app", "router"], function(app, Router) {
        // Define your master router on the application namespace and trigger all
        // navigation from this instance.
        app.router = new Router();

        // Trigger the initial route and enable HTML5 History API support, set the
        // root folder to '/' by default.  Change in app.js.
        Backbone.history.start({ pushState: false, root: '/' });
    });
});

The output is just a combination this two files, which is not what I expected.

Boustrophedon answered 1/6, 2014 at 9:19 Comment(8)
Can you post your main.js (require) file?Rubyeruch
@Rubyeruch yes, please find them below. Thank you!Boustrophedon
So currently, gulp-requirejs is on the blacklist and there is no recipe for how to do this :-/ github.com/gulpjs/plugins/blob/master/src/blackList.jsonStringent
I've found this tool which looks promising.Pulver
@AllenRice, what are the consequences of being on the blacklist?Halftrack
Here is some discussion that explains why RequireJS "shouldn't" be a gulp plugin.Halftrack
@DrewNoakes, "some discussion" is a stretch. That link provides no substantial discussion, never mind an explanation.Conflux
@AllenRice, it's unfortunate that the blacklist does not include reasons, which would have helped users assess whether the reason applied to their setup.Conflux
H
32

gulp-requirejs has been blacklisted by the gulp folks. They see the RequireJS optimizer as its own build system, incompatible with gulp. I don't know much about that, but I did find an alternative in amd-optimize that worked for me.

npm install amd-optimize --save-dev

Then in your gulpfile:

var amdOptimize = require('amd-optimize');
var concat = require('gulp-concat');

gulp.task('bundle', function ()
{
    return gulp.src('**/*.js')
        .pipe(amdOptimize('main'))
        .pipe(concat('main-bundle.js'))
        .pipe(gulp.dest('dist'));
});

The output of amdOptimize is a stream which contains the dependencies of the primary module (main in the above example) in an order that resolves correctly when loaded. These files are then concatenated together via concat into a single file main-bundle.js before being written into the dist folder.

You could also minify this file and perform other transformations as needed.


As an aside, in my case I was compiling TypeScript into AMD modules for bundling. Thinking this through further I realized that when bundling everything I don't need the asynchronous loading provided by AMD/RequireJS. I am going to experiment with having TypeScript compile CommonJS modules instead, then bundling them using webpack or browserify, both of which seem to have good support within gulp.

Halftrack answered 27/9, 2014 at 21:34 Comment(4)
What does blacklisted means in this particular context?Entice
@Entice - It's on this list: github.com/gulpjs/plugins/blob/master/src/blackList.jsonPosset
Blacklisted? Requirejs is the most essential JavaScript code ever made!Scissel
About amd-optimize: their GitHub readme states "This project is no longer actively maintained."Ethbin
M
11

UPDATE

My previous answer always reported taskReady even if requirejs reported an error. I reconsidered this approach and added error logging. Also I try to fail the build completely as described here gulp-jshint: How to fail the build? because a silent fail really eats your time. See updated code below.

Drew's comment about blacklist was very helpfull and gulp folks suggest using requirejs directly. So I post my direct requirejs solution:

var DIST = './dist';
var requirejs = require('requirejs');
var requirejsConfig = require('./requireConfig.js').RJSConfig;

gulp.task('requirejs', function (taskReady) {
    requirejsConfig.name = 'index';
    requirejsConfig.out = DIST + 'app.js';
    requirejsConfig.optimize = 'uglify';
    requirejs.optimize(requirejsConfig, function () {
        taskReady();
    }, function (error) {
        console.error('requirejs task failed', JSON.stringify(error))
        process.exit(1);
    });
});

The file at ./dist/app.js is built and uglified. And this way gulp will know when require has finished building. So the task can be used as a dependency.

Mcilroy answered 17/7, 2015 at 17:31 Comment(0)
P
5

My solution works like this:

./client/js/main.js:

require.config({
    paths: {
        jquery: "../vendor/jquery/dist/jquery",
        ...
    },
    shim: {
        ...
    }
});

define(["jquery"], function($) {
    console.log($);
});

./gulpfile.js:

var gulp = require('gulp'),
    ....
    amdOptimize = require("amd-optimize"),
    concat = require('gulp-concat'),
    ...

gulp.task('scripts', function(cb) {

    var js = gulp.src(path.scripts + '.js')
        .pipe(cached('scripts'))
        .pipe(jshint())
        .pipe(jshint.reporter('default'))
        .pipe(remember('scripts'))
        .pipe(amdOptimize("main",
            {
                name: "main",
                configFile: "./client/js/main.js",
                baseUrl: './client/js'
            }
        ))
        .pipe(concat('main.js'));

        .pipe(gulp.dest(path.destScripts));
}
...

This part was important:

configFile: "./client/js/main.js",
baseUrl: './client/js'

This allowed me to keep my configuration in one place. Otherwise I was having to duplicate my paths and shims into gulpfile.js.

Psychodiagnostics answered 11/5, 2015 at 19:24 Comment(0)
P
2

This works for me. I seems that one ought to add in uglification etc via gulp if desired. .pipe(uglify()) ...

Currently I have to duplicate the config in main.js to run asynchronously.

    ....

    var amdOptimize = require("amd-optimize");

    ...

    var js = gulp.src(path.scripts + '.js')
        .pipe(cached('scripts'))
        .pipe(jshint())
        .pipe(jshint.reporter('default'))
        .pipe(remember('scripts'))
        .pipe(amdOptimize("main",
            {
                name: "main",
                paths: {
                    jquery: "client/vendor/jquery/dist/jquery",
                    jqueryColor: "client/vendor/jquery-color/jquery.color",
                    bootstrap: "client/vendor/bootstrap/dist/js/bootstrap",
                    underscore: "client/vendor/underscore-amd/underscore"
                },
                shim: {
                    jqueryColor : {
                        deps: ["jquery"]
                    },
                    bootstrap: {
                        deps: ["jquery"]
                    },
                    app: {
                        deps: ["bootstrap", "jqueryColor", "jquery"]
                    }
                }
            }

        ))
        .pipe(concat('main.js'));
Psychodiagnostics answered 3/3, 2015 at 20:31 Comment(0)
C
1

Try this code in your gulpfile:

// Node modules
var
    fs = require('fs'),
    vm = require('vm'),
    merge = require('deeply');    

// Gulp and plugins
var
    gulp = require('gulp'),    
    gulprjs= require('gulp-requirejs-bundler');

// Config
var
    requireJsRuntimeConfig = vm.runInNewContext(fs.readFileSync('app/config.js') + '; require;'),
    requireJsOptimizerConfig = merge(requireJsRuntimeConfig, {
        name: 'main',
        baseUrl: './app',
        out: 'result.js',
        paths: {
            requireLib: 'bower_modules/requirejs/require'
        },
        insertRequire: ['main'],
        // aliases from config.js - libs will be included to result.js
        include: [
            'requireLib',
            "almond",
            "underscore",
            "jquery",
            "backbone",
            "text",
            "book"
        ]
    });

gulp.task('requirejsBuild', ['component-scripts', 'external-scripts'], function (cb) {
    return gulprjs(requireJsOptimizerConfig)            
        .pipe(gulp.dest('app/dist'));
});
Cloison answered 30/9, 2014 at 5:57 Comment(0)
C
1

Sorry for my english. This solution works for me. (I used gulp-requirejs at my job)

I think you've forgotten to set mainConfigFile in your gulpfile.js. So, this code will be work

gulp.task('requirejsBuild', function() {
    rjs({
        name: 'main',
        mainConfigFile: 'path_to_config/config.js',
        baseUrl: './app',
        out: 'result.js'
    })
    .pipe(gulp.dest('app/dist'));

});

In addition, I think when you run that task in gulp, require can not find its config file and

Cuss answered 5/8, 2015 at 14:29 Comment(0)
G
1

This is not gulp-requirejs fault.

The reason why only main.js and config.js is in the output is because you're not requiring/defining any other files. Without doing so, the require optimizer wont understand which files to add, the paths in your config-file isn't a way to require them!

For example you could load a main.js file from your config file and in main define all your files (not optimal but just a an example).

In the bottom of your config-file:

// Load the main app module to start the app
requirejs(["main"]); 

The main.js-file: (just adding jquery to show the technique.

define(["jquery"], function($) {}); 

I might also recommend gulp-requirejs-optimize instead, mainly because it adds the minification/obfuscation functions gulp-requirejs lacks: https://github.com/jlouns/gulp-requirejs-optimize

How to implement it:

var requirejsOptimize = require('gulp-requirejs-optimize');

gulp.task('requirejsoptimize', function () {
  return gulp.src('src/js/require.config.js')
    .pipe(requirejsOptimize(function(file) {
      return {
        baseUrl: "src/js",
        mainConfigFile: 'src/js/require.config.js',
        paths: {
          requireLib: "vendor/require/require"
        },
        include: "requireLib",
        name: "require.config",
        out: "dist/js/bundle2.js"
      };
  })).pipe(gulp.dest(''));
});
Gumboil answered 3/10, 2016 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.