Prepend custom strings to JS files while concatena

2019-05-19 09:16发布

I am trying to migrate our build process to gulp from existing custom bash build script. We concatenate several unminified opensource JS files like bootstrap, lazyload, ... and our own JS files. We uglify each JS file (removing their licenses as well) in an order, prepend custom license text to some of them as required and concatenate to create the output JS file. The custom license text are currently kept as strings in the bash script.

How to achieve this in gulp without creating intermediate files? Will it also be possible to selectively avoid uglifying some JS scripts?

1条回答
地球回转人心会变
2楼-- · 2019-05-19 09:30

Ok, I spent some time learning up gulp and it's plugins and here is a working version. The points here are using the foreach on each JS retrieved from the JSON config file, pushing the streams to an array and finally using merge on the array streams.

Here are the plugins used and the JSON structure defined:

var gulp = require('gulp');

var each = require('foreach');
var debug = require('gulp-debug');
var gulpif = require('gulp-if');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat-util');

var es = require('event-stream');
var cache = require('gulp-cached');
var remember = require('gulp-remember');

// Structure that holds the various JS files and their handling
var Config = {
  js: {
    output_dir: 'path/to/output/file/',
    output_file: 'outputfile.js',
    src: [{
      name: 'bootstrap',
      src: ['path/to/bootstrap.js'],
      run_lint: false,
      run_uglify: true,
      license: '/* bootstrap license */'
    }, {
      name: 'lazyload',
      src: ['path/to/lazyload.js'],
      run_lint: false,
      run_uglify: true,
      license: '/* lazyload license */'
    }, {
      name: 'inhouse-js',
      src: ['path/to/inhouse/ih-1.js', 'path/to/inhouse/ot/*.js'],
      run_lint: true,
      run_uglify: true,
      license: ''
    }]
  }
}

The build task, with caching as we will be using it in development also:

gulp.task('build', ['build:js']);

gulp.task('build:js', function() {
  var streams = [];

  each(Config.js.src, function(val, key, array) {
    var stream = gulp.src(val.src)
      .pipe(cache('scripts'))
      .pipe(gulpif(val.run_lint, jshint('.jshintrc')))
      .pipe(gulpif(val.run_lint, jshint.reporter('jshint-stylish')))
      .pipe(gulpif(val.run_uglify, uglify({
                                     compress: {
                                       drop_console: true
                                     }
      })))
      .pipe(concat.header(val.license + '\n'));

    streams.push(stream);
  });

  es.merge.apply(this, streams)
    .pipe(remember('scripts')) // add back all files to the stream
    .pipe(concat(Config.js.output_file))
    .pipe(gulp.dest(Config.js.output_dir));
});

If you would like to debug, a good option will be to insert debug plugin like this example around the 'gulp-remember' plugin call above:

.pipe(debug({title: 'before remember:'}))
.pipe(remember('scripts')) // add back all files to the stream
.pipe(debug({title: 'after remember:'}))

And here's the watch task:

gulp.task('watch', function() {
  var watch_list = [];
  each(Config.js.src, function(val, key, array) {
    watch_list.push.apply(watch_list, val.src);
  });

  // Watch .js files
  var watcher = gulp.watch(watch_list, ['build']);

  watcher.on('change', function(event) {
    console.log('File '+ event.path +' was '+ event.type +', running tasks..');
    if (event.type === 'deleted') { // if a file is deleted, forget it
      delete cache.caches['scripts'][event.path];
      remember.forget('scripts', event.path);
    }
  })
});

You can use lazypipe() to reuse parts of the build:js task with normal build.

查看更多
登录 后发表回答