Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I insert content into a file during a gulp build?

I managed to accomplish my task using a gulp plugin called gulp-insert like this:

gulp.task('compile-js', function () {
  // Minify and bundle client scripts.
  var scripts = gulp.src([
    srcDir + '/routes/**/*.js',
    srcDir + '/shared/js/**/*.js'
  ])
    // Sort angular files so the module definition appears
    // first in the bundle.
    .pipe(gulpAngularFilesort())
    // Add angular dependency injection annotations before
    // minifying the bundle.
    .pipe(gulpNgAnnotate())
    // Begin building source maps for easy debugging of the
    // bundled code.
    .pipe(gulpSourcemaps.init())
    .pipe(gulpConcat('bundle.js'))
    // Buffer the bundle.js file and replace the appConfig
    // placeholder string with a stringified config object.
    .pipe(gulpInsert.transform(function (contents) {
      return contents.replace("'{{{appConfigObj}}}'", JSON.stringify(config));
    }))
    .pipe(gulpUglify())
    // Finish off sourcemap tracking and write the map to the
    // bottom of the bundle file.
    .pipe(gulpSourcemaps.write())
    .pipe(gulp.dest(buildDir + '/shared/js'));

  return scripts.pipe(gulpLivereload());
});

What I'm doing is reading our app's configuration file which is managed by the config module on npm. Getting our config file from server-side code is a snap using var config = require('config');, but we're a single-page app and frequently need access to the configuration settings on the client-side. To do that I stuff the config object into an Angular service.

Here's the Angular service before gulp build.

angular.module('app')
  .factory('appConfig', function () {
    return '{{{appConfigObj}}}';
  });

The placeholder is in a string so that it's valid JavaScript for some of the other gulp plugins that process the file first. The gulpInsert utility lets me insert the config like this.

.pipe(gulpInsert.transform(function (contents) {
  return contents.replace("'{{{appConfigObj}}}'", JSON.stringify(config));
}))

This works but feels a little hacky. Not to mention that it has to buffer the whole bundled file just so I can perform the operation. Is there a more elegant way to accomplish the same thing? Preferably one that allows the stream to keep flowing smoothly without buffering the whole bundle at the end? Thanks!

like image 876
Chev Avatar asked Jun 18 '15 21:06

Chev


2 Answers

Have you checked gulp-replace-task?

Something like

[...]
.pipe(gulpSourcemaps.init())
.pipe(replace({
  patterns: [{
    match: '{{{appConfigObj}}}',
    replacement: config
  }],
  usePrefix: false
})
.pipe(gulpUglify())
[...]
like image 94
tomtastico Avatar answered Oct 20 '22 05:10

tomtastico


Admittedly, this feels a bit hacky, too, but maybe slightly better... I'm using envify and gulp-env in a React project. You could do something like this.

gulpfile.js:

var config = require('config');
var envify = require('envify');

gulp.task('env', function () {
    env({
        vars: {
            APP_CONFIG: JSON.stringify(config)
        }
    });
});

gulp.task('compile-js', ['env'], function () {
  // ... replace `gulp-insert` with `envify`
});

factory:

angular.module('app')
  .factory('appConfig', function () {
    return process.env.APP_CONFIG;
  });
like image 35
Jeff Fairley Avatar answered Oct 20 '22 06:10

Jeff Fairley