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

jopen 8年前


这是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

</div>