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命令。
源代碼
總結
這是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