Gulp系列教程:使用Browserify处理JavaScript

这是Gulp系列教程的第五部分。今天我会展示如何使用Browserify来打包JavaScript并使用CommonJS模块在浏览器中运行node模块。

Browserify

这个任务稍微复杂一些,因为我使用Browserify来打包JavaScript。如果它太复杂了超出了你的需求你也可以使用gulp-concat来把所有JavaScript文件打包成一个文件。

Browserify是一个超棒的工具,你可以在浏览器中使用node模块。超过70%的node模块可以正确运行!并且它会打包所有依赖。如果你想了解更多关于给Browserify编写CommonJS模块的内容请查阅文档。

这个任务我是在gulp-starter中发现的。它确实有点长但是很智能。它可以通过Browserify创建多个文件。我创建了两个。一个在网页头部加载包括了Modernizr并另一个包含所有其余JavaScript的文件在底部加载。

使用Browserify创建JavaScript文件

安装这个任务所需的node模块:

$ npm install --save-dev browserify@11.2.0 vinyl-source-stream@1.0.0 watchify@3.4.0 gulp-util@3.0.1 pretty-hrtime@1.0.1 gulp-notify@2.0.0

config.js文件中创建入口:

//gulp/config.js

browserify: {
  // Enable source maps
  debug: true,
  // Additional file extensions to make optional
  extensions: ['.coffee', '.hbs'],
  // A separate bundle will be generated for each
  // bundle config in the list below
  bundleConfigs: [{
    entries:    './' + srcAssets + '/javascripts/application.js',
    dest:       developmentAssets + '/js',
    outputName: 'application.js'
  }, {
    entries:    './' + srcAssets + '/javascripts/head.js',
    dest:       developmentAssets + '/js',
    outputName: 'head.js'
  }]
}

//gulp/tasks/development/scripts.js

var gulp         = require('gulp');
var browsersync  = require('browser-sync');
var browserify   = require('browserify');
var source       = require('vinyl-source-stream');
var watchify     = require('watchify');
var bundleLogger = require('../../util/bundleLogger');
var handleErrors = require('../../util/handleErrors');
var config       = require('../../config').browserify;

/**
 * Run JavaScript through Browserify
 */
gulp.task('scripts', function(callback) {

  browsersync.notify('Compiling JavaScript');

  var bundleQueue = config.bundleConfigs.length;
  var browserifyThis = function(bundleConfig) {
    var bundler = browserify({
      // Required watchify args
      cache: {}, packageCache: {}, fullPaths: false,
      // Specify the entry point of your app
      entries: bundleConfig.entries,
      // Add file extentions to make optional in your requires
      extensions: config.extensions,
      // Enable source maps!
      debug: config.debug
    });

    var bundle = function() {
      // Log when bundling starts
      bundleLogger.start(bundleConfig.outputName);

      return bundler
        .bundle()
        // Report compile errors
        .on('error', handleErrors)
        // Use vinyl-source-stream to make the
        // stream gulp compatible. Specifiy the
        // desired output filename here.
        .pipe(source(bundleConfig.outputName))
        // Specify the output destination
        .pipe(gulp.dest(bundleConfig.dest))
        .on('end', reportFinished);
    };

    if(global.isWatching) {
      // Wrap with watchify and rebundle on changes
      bundler = watchify(bundler);
      // Rebundle on update
      bundler.on('update', bundle);
    }

    var reportFinished = function() {
      // Log when bundling completes
      bundleLogger.end(bundleConfig.outputName)

      if(bundleQueue) {
        bundleQueue--;
        if(bundleQueue === 0) {
          // If queue is empty, tell gulp the task is complete.
          // https://github.com/gulpjs/gulp/blob/master/docs/API.md#accept-a-callback
          callback();
        }
      }
    };

    return bundle();
  };

  // Start bundling with Browserify for each bundleConfig specified
  config.bundleConfigs.forEach(browserifyThis);
});

这个任务包含一些额外的工具来处理错误并日志输出压缩过程。把这些内容放到gulp目录的util目录中:

//gulp/util/bundleLogger.js

/* bundleLogger
   ------------
   Provides gulp style logs to the bundle method in browserify.js
*/

var gutil        = require('gulp-util');
var prettyHrtime = require('pretty-hrtime');
var startTime;

module.exports = {
  start: function(filepath) {
    startTime = process.hrtime();
    gutil.log('Bundling', gutil.colors.green(filepath));
  },

  end: function(filepath) {
    var taskTime = process.hrtime(startTime);
    var prettyTime = prettyHrtime(taskTime);
    gutil.log('Bundled', gutil.colors.green(filepath), 'in', gutil.colors.magenta(prettyTime));
  }
};

//gulp/util/handleErrors.js

var notify = require("gulp-notify");

module.exports = function() {

  var args = Array.prototype.slice.call(arguments);

  // Send error to notification center with gulp-notify
  notify.onError({
    title: "Compile Error",
    message: "<%= error.message %>"
  }).apply(this, args);

  // Keep gulp from hanging on this task
  this.emit('end');
};

使用CommonJS模块

编写CommonJS模块非常棒。你只需要输出函数,对象,字符串,整数以及任何想要作为模块或独立输出的内容。

//math.js

exports.add = function() {
  var sum = 0, i = 0, args = arguments, 1 = args.length;
  while (i < 1) {
    sum += args[i++];
  }
  return sum;
};

//navigation.js

module.exports = {
  toggleNavigation: function() {
    ...
  }
};

随后你导入模块并使用:

//increment.js

var add = require('./math').add;

exports.increment = function(val) {
  return add(val, 1);
};

//application.js

var navigation = require('./navigation');
var triggerNavigation = document.querySelector('.toggle- navigation');

document.addEventListener('DOMContentLoaded', function() {
  triggerNavigation.addEventListener('click', navigation.toggleNavigation);
});

加载非CommonJS文件

但是还有个问题:我如何使用不含CommonJS语法的JavaScript文件?例如Modernizr或jQuery?

我需要安装browserify-shim

$ npm install --save-dev browserify-shim@3.8.0

打开package.son文件并添加以下新行:

//package.json

{
  "...": "...",
  "browser": {
    "modernizr": "./app/_bower_components/modernizr/modernizr.js",
    "jquery": "./app/_bower_components/jquery/dist/jquery.js"
  },
  "browserify-shim": {
    "modernizr": "Modernizr",
    "jquery": "$"
  },
  "browserify": {
    "transform": [
      "browserify-shim"
    ]
  },
  "devDependencies": {
    "...": "..."
  }
}

browser区块中指定browserify-shim到想要shim的资源。我使用Bower并将包安装到app/_bowser_components中。选择的名字就是随后在JavaScripts中加载的名字。

"browserify-shim"中定义将依赖映射到哪里。要载入jQuery或Modernizr你需要加入以下内容:

//app/_assets/javascripts/head.js

require('modernizr');

// app/_assets/javascripts/application.js
require('jquery');

$(function() {
  console.log("jQuery and Modernizr loaded");
});

一旦在package.json文件中添加新的入口你需要运行nam install命令。

源代码

在Github上查看源码

总结

这是Gulp系列教程的第五部分的总结。我们学习了如何使用Browserify打包JavaScript文件,如何使用CommonJS模块在浏览器中运行node,以及如何使用非CommonJS的JavaScript文件。

本文根据@Stefan Imhoff的《Introduction to Gulp.js 5: Bundling JavaScript with Browserify》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://stefanimhoff.de/2014/gulp-tutorial-5-javascripts-browserify/

Blueed

现居上海。正在学习前端的道路上,欢迎交流。个人博客:Blueed.me,微博:@Ivan_z3

如需转载,烦请注明出处:http://www.w3cplus.com/workflow/gulp-tutorial-5-javascripts-browserify.html

返回顶部