Using Gulp to build requireJS project - gulp-requirejs

元气小坏坏 提交于 2019-11-28 16:34:24
Drew Noakes

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.

Olga

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.

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.

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'));

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'));
});

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

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(''));
});
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!