2

I'm using gulp with browserify and tsify. This has been working quite well. Then I decided to add ng-annotate using browserify-ngannotate.

I've added the ng-annotate browserify transform but it seems that if tsify is added as a plugin the ng-annotate transform is never called.

If I remove the tsify plugin then ng-annote gets called. I've played around and switched around the plugin/transform registration. Am I missing something here, or should I go and log an issue at browserify/tsify?

var browserify = require('browserify');
var browserSyncConfig = require('../config').browserSync;
var browserSync = require('browser-sync').get(browserSyncConfig.instance);
var watchify = require('watchify');
var tsify = require('tsify');
var ngAnnotate = require('browserify-ngannotate');
var mergeStream = require('merge-stream');
var bundleLogger = require('../util/bundleLogger');
var gulp = require('gulp');
var handleErrors = require('../util/handleErrors');
var source = require('vinyl-source-stream');
var config = require('../config').browserify;
var _ = require('lodash');

var browserifyTask = function (devMode) {

    var browserifyThis = function (bundleConfig) {

        if (devMode) {
            // Add watchify args and debug (sourcemaps) option
            _.extend(bundleConfig, watchify.args, {debug: true});
            // A watchify require/external bug that prevents proper recompiling,
            // so (for now) we'll ignore these options during development. Running
            // `gulp browserify` directly will properly require and externalize.
            bundleConfig = _.omit(bundleConfig, ['external', 'require']);
        }

        var b = browserify(bundleConfig);

        if (bundleConfig.tsify) {
            b = b.plugin(tsify, {
                noImplicitAny: false,
                target: 'ES5',
                noExternalResolve: false,
                module: 'commonjs',
                removeComments: false
            });
        }

        if (bundleConfig.ngAnnotate) {
            b = b.transform(ngAnnotate);
        }

        var bundle = function () {
            // Log when bundling starts
            bundleLogger.start(bundleConfig.outputName);

            return b
                .bundle()
                // Report compile errors
                .on('error', handleErrors)
                // Use vinyl-source-stream to make the
                // stream gulp compatible. Specify the
                // desired output filename here.
                .pipe(source(bundleConfig.outputName))
                // Specify the output destination
                .pipe(gulp.dest(bundleConfig.dest))
                .pipe(browserSync.stream());
        };

        if (devMode) {
            // Wrap with watchify and rebundle on changes
            b = watchify(b, {
                poll: true
            });

            // Rebundle on update
            b.on('update', bundle);
            bundleLogger.watch(bundleConfig.outputName);
        } else {
            // Sort out shared dependencies.
            // b.require exposes modules externally
            if (bundleConfig.require) b.require(bundleConfig.require);
            // b.external excludes modules from the bundle, and expects
            // they'll be available externally
            if (bundleConfig.external) b.external(bundleConfig.external);
        }

        return bundle();
    };

    // Start bundling with Browserify for each bundleConfig specified
    return mergeStream.apply(gulp, _.map(config.bundleConfigs, browserifyThis));

};

gulp.task('browserify', function () {
    return browserifyTask()
});

// Exporting the task so we can call it directly in our watch task, with the 'devMode' option
module.exports = browserifyTask;
Tersius
  • 267
  • 4
  • 17

2 Answers2

2

I realized I had this problem too, when I added uglifyify to the bundle transforms to produce minified builds.

An important aspect of my solution is that the missing, explicit $inject statements, that ng-annotate should have inserted, doesn't matter until the code is actually minified. Luckily, UglifyJS2, which does the actual minification in uglifyify, got support for handling ng-annotate's ngInject comments in version 2.4.9 (in January, 2014).

So, the solution that worked for me was to install uglifyify:

npm install --save-dev uglifyify

and add the following uglifyify transform to the Browserify bundle:

b.transform({
            global: true,
            mangle: false,
            comments: true,
            compress: {
                angular: true
            }
        }, 'uglifyify');

This will make UglifyJS2 insert the appropriate $inject statements into your code before it is minified.

So, to summarize, I did not have a solution for only using ng-annotate, but my solution will add the necessary $inject statements before the code is minified, which is what matters in most cases.

Martin Thorsen Ranang
  • 2,394
  • 1
  • 28
  • 43
  • If the answer works for you, it would be great if you accept it as the answer – so that other users can benefit from knowing that the answer works. If you had any issues, please let me know. – Martin Thorsen Ranang Dec 08 '15 at 20:54
2

You can solve it by specify extensions in ng-annotate options.

bundler.transform(ngAnnotate, { ext: ['.ts', '.js'] });

gauss
  • 177
  • 12