如何在源目录中保存Gulp包?

时间:2015-11-08 03:57:04

标签: gulp

我正在关注Fast browserify builds with watchify recipe并让它正常运行,但希望将我的捆绑包写入原始源文件夹。

例如,我有以下代码(直接从配方中获取,但略有修改)

// add custom browserify options here
var customOpts = {
    entries: glob.sync("./dev/www/**/*-root.js"),
    debug: true
};
var opts = _.assign({}, watchify.args, customOpts);
var b = watchify(browserify(opts)); 



gulp.task('js', bundle); // so you can run `gulp js` to build the file
b.on('update', bundle); // on any dep update, runs the bundler
b.on('log', gutil.log); // output build logs to terminal


function bundle() {
    return b.bundle()
    // log errors if they happen
        .on('error', gutil.log.bind(gutil, 'Browserify Error'))
        .pipe(source('bundle.js'))
    // optional, remove if you don't need to buffer file contents
        .pipe(buffer())
    // optional, remove if you dont want sourcemaps
        .pipe(sourcemaps.init({ loadMaps: true })) // loads map from browserify file
    // Add transformation tasks to the pipeline here.
        .pipe(sourcemaps.write('./')) // writes .map file
        .pipe(gulp.dest((file) => {return file.base;}));
        //.pipe(gulp.dest('./dist'));
}

正如您在entries: glob.sync("./dev/www/**/*-root.js"),行中看到的那样,我正在扫描要捆绑的多个文件。

我遇到的问题是.pipe(gulp.dest((_file: any) => {return file.base;}));行,它返回根项目文件夹的路径,而不是原始源文件夹的路径。

如何获取写入的源文件夹路径?

修改

我发现http://fettblog.eu/gulp-browserify-multiple-bundles/描述了如何创建多个捆绑包,但它并没有使用watchify。看起来这个问题可能是乙烯基源流的限制?

1 个答案:

答案 0 :(得分:1)

花了很多功夫,但我想出了一个解决方案。

一般情况下,我遵循http://fettblog.eu/gulp-browserify-multiple-bundles/处找到的模式,但添加了每个创建的browserify对象的缓存(每页一个),并添加了watchify。

以下代码中添加了其他内容:

  • livereload
  • dev server launch
  • typescript(tsx)编译(包括链式源图)

完整解决方案(打字稿代码):

import gulp = require("gulp");
import browserify = require("browserify");
var watchify = require("watchify");

import source = require("vinyl-source-stream");

import buffer = require("vinyl-buffer");


import gutil = require("gulp-util");
import sourcemaps = require("gulp-sourcemaps");
var sourcemapsApply = require("vinyl-sourcemaps-apply");

import _ = require("lodash");


import glob = require("glob");
import vinyl = require("vinyl");


import rename = require("gulp-rename");

var minifyify = require("minifyify");

import path = require("path");

var tsify = require("tsify");


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

var closureCompiler = require("gulp-closure-compiler");

import uglify = require("gulp-uglify");
import http = require("http");
var st = require("st");  //module for serving static files.  used to create dev server.   https://www.npmjs.com/package/st

var eventStream = require("event-stream"); //module for merging multiple vinyl streams to return one when finishing task.   see http://fettblog.eu/gulp-browserify-multiple-bundles/

var rootPath = __dirname;

gulp.task("default", () => {
    gulp.start("tsxDevWatch");
});


gulp.task("devServer", (done) => {

    var rootPath = __dirname;
    //start server
    http.createServer(st({
        path: rootPath,
        index: true, //"index.html",
        cache: false,
    })).listen(8080,"localhost", done);

});

gulp.task("tsxDevWatch",["devServer"], () => {



    livereload.listen();

    //browserify+watchify of *-main.js files and compiles into *-main.bundle.js files IN SAME FOLDER

    //created mostly following the pattern described here: http://fettblog.eu/gulp-browserify-multiple-bundles/
    //but adds stupid source-filepath workaround for use with "source" (vinyl-source-stream needed for watchify)

    /** the files we are going to browserify bundle*/
    var entries = glob.sync("./dev/www/**/*-main.tsx", {
        realpath: true, //so paths are absolute.  This is required so our "bMaps" mappings stay intact, because watchify.on("update") always provides full filepath, 
    });
    /** we create one browserify instance for each file we are bundling.  this caches the browserify instance so it can be reused on watchify updates (decreasing compile time by A LOT) */
    var bMaps: { [key: string]: BrowserifyObject } = {};

    var tasks = entries.map((entry) => {    
        process.chdir(path.dirname(entry));

        var browserifyOptions = {
            entries: [entry],
            debug: true,
            plugin: [
                watchify,
                //tsify,
            ],
            cache: {}, packageCache: {}, fullPaths: true // Requirement of watchify
        };
        var b = browserify(browserifyOptions);


        b.plugin(tsify, { //options from here: http://json.schemastore.org/tsconfig
            jsx: "react",
            //inlineSourceMap: false,  //sourcemap options don't seem to matter, seems to be set by browserify or something.
            //sourceMap:true,
            module: "commonjs",
            target: "es5",
        });

        bMaps[entry] = b;

        b.on('update', (updatedFiles: string[]) => {
            console.log("!!!!!!!!!!!!!! \n!!!!!!!!!!!!!!!!!!!\n UPDATE CALLED FOR", JSON.stringify(updatedFiles));

            var rebuildAll = false;
            _.forEach(updatedFiles, (updatedFile) => {
                if (bMaps[updatedFile] == null) {
                    //a dependency needs to be rebuilt, skip rebuilding anything that changed and do EVERYTHING
                    rebuildAll = true;
                    return false;
                }
            });

            if (rebuildAll === false) {
                _.forEach(updatedFiles, (updatedFile) => {
                    console.log(" ============= update()", updatedFile);
                    //find the b for this file
                    var _b = bMaps[updatedFile];
                    //do a bundle for it
                    _createTsXBundle(_b, updatedFile);

                });
            } else {
                //this is a dependency, rebuild EVERYTHING!!!
                _.forEach(bMaps, (value_b, key_entry) => {
                    _createTsXBundle(value_b, key_entry);
                });
            }

        }); // on any dep update, runs the bundler
        b.on('log', gutil.log); // output build logs to terminal

        return _createTsXBundle(b, entry);
    });

    return eventStream.merge.apply(null, tasks);
});

/** worker to create a tsx bundle.  used by a task  */
function _createTsXBundle(b: BrowserifyObject, entry: string) {
    process.chdir(path.dirname(entry));
    console.log("================= doBundle()", entry);

    var bundledStream = b.bundle();
    bundledStream = <any>bundledStream.on('error', gutil.log.bind(gutil, 'Browserify Error'));

    var currentSource: vinyl;

    var targetName = path.basename(entry, ".tsx") + ".bundle.js";
    bundledStream
        .pipe(source(targetName))
        .pipe(buffer()) //need this to support chaining our vinyl source file

    ////////////////////////////////////////
    //// optional, remove if you dont want sourcemaps
    //  .pipe(sourcemaps.init({
    //      loadMaps: true,
    //      //debug: true
    //  })) // loads map from browserify file

    /////////////////////////  WORKS, BUT NEED TO ENABLE SOURCEMAPS plugin TO GET SOURCEMAPS
    //// uglify
    //.pipe(uglify({
    //  //preserveComments: "all",              
    //  output:<any> {
    //      max_line_len: 300,
    //      //screw_ie8: false,
    //      //beautify: true,
    //      //comments: true,
    //      //bracketize: true,
    //      //quote_keys: true,
    //      //width: 120,
    //      //semicolons:true,
    //  },
    //  compress: {
    //      unsafe:true,
    //  },
    //}))

    //// Add transformation tasks to the pipeline here.
    //  .pipe(sourcemaps.write())

        .pipe(gulp.dest((file: vinyl) => {
            //console.log("GULP.DEST(file)\n base=", file.base, "\n cwd=", file.cwd, "\n path=", file.path, "\n relative=", file.relative);
            return file.base;
        }))
        .pipe(livereload())

    ;

    return bundledStream;
}