Fixing Gruntfile.js after updating version - node.js

I have a Sails.js app with some legacy code. The original developer of the app followed this Stackoverflow answer to organize grunt tasks and the directory structure for them. However, with Grunt ^1.0.4, Gruntfile.js throws the following error when building:
Loading "Gruntfile.js" tasks...ERROR
>> TypeError: tasks[taskName] is not a function
Any idea of how to fix this? Will I need to scrap this code and load each task manually based on the path? Any help would be greatly appreciated!
* Gruntfile
* This Node script is executed when you run `grunt` or `sails lift`.
* It's purpose is to load the Grunt tasks in your project's `tasks`
* folder, and allow you to add and remove tasks as you see fit.
* For more information on how this works, check out the ``
* file that was generated in your `tasks` folder.
* Unless you know what you're doing, you shouldn't change this file.
* Check out the `tasks` directory instead.
module.exports = function(grunt) {
// Load the include-all library in order to require all of our grunt
// configurations and task registrations dynamically.
var includeAll;
try {
includeAll = require('include-all');
} catch (e0) {
try {
includeAll = require('sails/node_modules/include-all');
catch(e1) {
console.error('Could not find `include-all` module.');
console.error('Skipping grunt tasks...');
console.error('To fix this, please run:');
console.error('npm install include-all --save`');
grunt.registerTask('default', []);
* Loads Grunt configuration modules from the specified
* relative path. These modules should export a function
* that, when run, should either load/configure or register
* a Grunt task.
function loadTasks(relPath) {
return includeAll({
dirname: require('path').resolve(__dirname, relPath),
filter: /(.+)\.js$/
}) || {};
* Invokes the function from a Grunt configuration module with
* a single argument - the `grunt` object.
function invokeConfigFn(tasks) {
for (var taskName in tasks) {
if (tasks.hasOwnProperty(taskName)) {
// Load task functions
var taskConfigurations = loadTasks('./tasks/config'),
registerDefinitions = loadTasks('./tasks/register');
// (ensure that a default task exists)
if (!registerDefinitions.default) {
registerDefinitions.default = function (grunt) { grunt.registerTask('default', []); };
// Run task functions to configure Grunt.
"dependencies": {
"angular": "^1.7.8",
"angular-google-maps": "^2.4.1",
"angular-multiple-select": "^1.1.3",
"async": "^2.6.2",
"aws-sdk": "^2.441.0",
"bluebird": "^3.5.4",
"blueimp-md5": "^2.10.0",
"bootstrap-select": "^1.13.10",
"browserify": "^16.2.3",
"buffer-equal-constant-time": "^1.0.1",
"csv": "^5.1.1",
"ejs": "^2.6.1",
"grunt": "^1.0.4",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-concat": "~1.0.1",
"grunt-contrib-copy": "~1.0.0",
"grunt-contrib-cssmin": "~3.0.0",
"grunt-contrib-less": "2.0.0",
"grunt-contrib-watch": "~1.1.0",
"grunt-sails-linker": "~1.0.4",
"grunt-sync": "~0.8.0",
"include-all": "^4.0.3",
"is-my-json-valid": "^2.19.0",


when I use gulp I get a weird js output?

I'm using gulp with reactjs and browserify
Here's my gulp file
var gulp = require('gulp'),
browserify = require('browserify'),
source = require('vinyl-source-stream'),
reactify = require('reactify'),
rename = require('gulp-rename')
gulp.task('js-build', function() {
// converts jsx to js
var b = browserify({
entries: ['./lib/main.jsx'],
transform: [reactify],
extensions: ['.js','.jsx'],
debug: false,
cache: {},
packageCache: {},
fullPaths: false
function build(file) {
return b
.plugin('minifyify', {
map: false
gulp.task('default', ['js-build']);
When I run gulp to convert my jsx to one js file, my js file output is really long and complicated and has functions that are beyond what I specified in my jsx files? Like there is a function called cleanUpNextTick() for example that I never declared.
Is this normal?
Here's my package.json
"dependencies": {
"browserify": "^11.0.1",
"expect": "^1.9.0",
"gulp": "^3.9.0",
"gulp-concat": "^2.6.0",
"gulp-react": "^3.0.1",
"gulp-rename": "^1.2.2",
"gulp-watch": "^4.3.4",
"jest-cli": "^0.5.0",
"jquery": "^2.1.4",
"marked": "^0.3.5",
"minifyify": "^7.0.5",
"react": "^0.13.3",
"react-tools": "^0.13.3",
"reactify": "^1.1.1",
"vinyl-source-stream": "^1.1.0"
"jest": {
"moduleFileExtensions": [
"scriptPreprocessor": "preprocessor.js",
"unmockedModulePathPatterns": [
"devDependencies": {
"jest-cli": "^0.4.19"
Yes it's normal, your code is been transpiled into Javascript ES5 by reactify, which uses ReactTools.transform under the hood.
The new features of the language are being replaced with ES5-compatible code, and new functions can be added to the final code during the transformation.
Also, browserify bundles all the dependencies you referenced to with require (or ES6's import), so you'll see also third-party code in your final bundle.
Yes its definitely normal. The bundle file compiles ALL javascript in your project, including your node module. This means youll be able to see functions from anything you require, cleanUpNextTick if probably from one of the libraries youre requiring, like react's CSSTransitionGroup for example

Gulp Task Failing - Browserify/Babel Incompatibility?

I've inherited a rather unusual website that is a hybrid of C# and Node JS (using TypeScript). We have a continuous integration environment set up on Azure DevOps to build the website and deploy it to a test environment. We've not had to build the website since March, and now the build process has suddenly broken. We had to change the reference to 'gulp' in package.json from "github:gulpjs/gulp#4.0" (which no longer exists) to "github:gulpjs/gulp#71c094a51c7972d26f557899ddecab0210ef3776", but now the step of the build process that calls gulp ("node node_modules\gulp\bin\gulp.js package") is failing with the following error (this is from the DevOps build log):
2018-12-04T22:38:48.9501268Z [22:38:48] TypeError in plugin "gulp-babel"
2018-12-04T22:38:48.9501465Z Message:
2018-12-04T22:38:48.9501806Z Path must be a string. Received undefined
If I run "node node_modules\gulp\bin\gulp.js package" locally I get the following:
[11:54:45] Error: TypeScript error: node_modules/#angular/router/src/router_module.d.ts(140,41): Error TS1110: Type expected.
at formatError (C:\.....\node_modules\gulp\node_modules\gulp-cli\lib\versioned\^4.0.0\format-error.js:20:10)
at Gulp.<anonymous> (C:\.....\node_modules\gulp\node_modules\gulp-cli\lib\versioned\^4.0.0\log\events.js:31:15)
at emitOne (events.js:120:20)
at Gulp.emit (events.js:210:7)
at Object.error (C:\.....\node_modules\undertaker\lib\helpers\createExtensions.js:61:10)
at handler (C:\.....\node_modules\now-and-later\lib\mapSeries.js:43:14)
at f (C:\.....\node_modules\once\once.js:25:25)
at f (C:\.....\node_modules\once\once.js:25:25)
at tryCatch (C:\.....\node_modules\async-done\index.js:24:15)
at done (C:\.....\node_modules\async-done\index.js:40:12)
This link - - seems to suggest a problem with browserify (or at least an incompatibility between browserify and babel-core)? The only suggestion is to drop the use of browserify. The mystery to me is why this worked previously but is now failing when all we've changed is the reference to gulp.
Could anyone explain to me what is causing the error and how to resolve it? Any help will be greatly appreciated.
The gulp task that is raising the error is this:
gulp.task("bundle", function () {
return browserify({
basedir: '.',
debug: true,
entries: [config.appMain],
cache: {},
packageCache: {}
.pipe(babel({ presets: ['env'] }))
.pipe(sourcemaps.write('./', { includeContent: false, sourceRoot: '../' }))
config.appMain = "App/main.ts"
config.jsDest = "./wwwroot/js"
The relevant 'requires' at the top of gulpfile.js are:
var gulp = require('gulp');
var browserify = require("browserify");
var tsify = require("tsify");
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var sourcemaps = require('gulp-sourcemaps');
var babel = require('gulp-babel');
var uglify = require("gulp-uglify");
var config = require('./gulp.config')();
The package.json devDependencies versions are:
"#types/core-js": "^0.9.34",
"#types/node": "^6.0.45",
"babel-preset-env": "^1.7.0",
"browserify": "^16.2.3",
"concurrently": "^3.4.0",
"del": "^2.2.2",
"gulp": "github:gulpjs/gulp#71c094a51c7972d26f557899ddecab0210ef3776",
"gulp-babel": "^6.1.2",
"gulp-clean": "^0.3.2",
"gulp-clean-css": "^3.0.4",
"gulp-concat": "^2.6.1",
"gulp-copy": ">=0.0.2",
"gulp-cssmin": "^0.2.0",
"gulp-htmlmin": "^3.0.0",
"gulp-load-plugins": "^1.3.0",
"gulp-rename": ">=1.2.2",
"gulp-rimraf": ">=0.2.0",
"gulp-sourcemaps": "^2.6.0",
"gulp-uglify": "^3.0.0",
"gulp-util": "^3.0.8",
"gulp-watch": ">=4.3.9",
"jasmine-core": "2.4.1",
"merge-stream": "^1.0.1",
"nodemon": "^1.11.0",
"tsify": "^3.0.1",
"tslint": "^3.15.1",
"typescript": "^2.0.0",
"typings": "^1.3.2",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^2.0.0"
I've tried using babelify, so the gulp task becomes:
gulp.task("bundle", function () {
return browserify({
basedir: '.',
debug: true,
entries: [config.appMain],
cache: {},
packageCache: {}
.transform(babelify, { presets: ['env'] })
.pipe(sourcemaps.write('./', { includeContent: false, sourceRoot: '../' }))
but I get exactly the same error when I execute "node node_modules\gulp\bin\gulp.js package" locally.
Please let me know if you need any more details or code. Thanks for any help you can give.
A colleague of mine worked this out. The solution is, of course, to use babelify. However, I got the implementation wrong. The usage in the gulp task that works is:
gulp.task("bundle", function () {
return browserify({
transform: [["babelify", { "presets": ["#babel/preset-env"] }]],
basedir: '.',
debug: true,
entries: [config.appMain],
cache: {},
packageCache: {}
.pipe(babel({ presets: ["#babel/preset-env"] }))
.pipe(sourcemaps.write('./', { includeContent: false, sourceRoot: '../' }))
The packages and versions used in package.json devDependencies are:
"browserify": "^16.2.3",
"#babel/core": "^7.2.0",
"#babel/preset-env": "^7.2.0",
"babelify": "^10.0.0",
"gulp-babel": "8.0.0",

grunt-karma cannot find templateCache templates using grunt-angular-templates in generator-cg-angular scaffolded project Gruntfile

I used (Yeoman) generator-cg-angular to scaffold my AngularJS web-app, and I'm trying to run unit tests without using the html2js preprocessor, but alas it looks like I'm missing something.
I changed the folders tree
As per customer request, I moved index.html, app.js and app.less within a folder named app, so now the folder structure is something like the following:
|--- Gruntfile.js //the Gruntfile.js is in the root folder, just like this generator does out-of-the-box
My karma task
karma: {
options: {
frameworks: ['jasmine'],
files: [ //this files data is also updated in the watch handler, if updated change there too
'<%= %>',
'<%= ngtemplates.main.dest %>',
autoWatch: false, //watching is handled by grunt-contrib-watch
singleRun: true,
htmlReporter: {
outputFile: 'unit-test-results/unit-tests'+'yyyymmdd') +'.html',
// Optional
pageTitle: 'Unit Tests',
groupSuites: true,
useCompactStyle: true
all_tests: {
browsers: ['Chrome','Firefox']
during_watch: {
browsers: ['PhantomJS']
The test-directive-spec.js
describe('testDirective', function() {
beforeEach(module('directive/test-directive/test-directive.html')); //manually written
var scope,compile;
beforeEach(inject(function($rootScope,$compile) {
scope = $rootScope.$new();
compile = $compile;
it('should ...', function() {
var element = compile('<test-directive></test-directive>')(scope);
expect(element.text()).toBe('hello world');
grunt test fails
When I run grunt test configured like this
the html report file says he the tests failed because the templates were not found
Error: [$injector:modulerr] Failed to instantiate module directive/test-directive/test-directive.html due to:
Error: [$injector:nomod] Module 'directive/test-directive/test-directive.html' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
So I tried adding the ngtemplates task to grunt test like this
configuring ngtemplates like this
ngtemplates: {
main: {
options: {
htmlmin:'<%= htmlmin.main.options %>',
url: function(url){ return url.replace('app/','')}
src: [createFolderGlobs('*.html'),'!'+ indexHtmlPath +'index.html','!_SpecRunner.html'],
dest: 'temp/templates.js'
and produces the following templates.js in a temp folder
angular.module('myApp').run(['$templateCache', function($templateCache) {
'use strict';
"<div>hello world</div>"
But the html reporter still says that the templates are not found.
What am I doing so wrong?
Here's my package.json
"name": "myApp",
"version": "0.0.0",
"devDependencies": {
"eslint": "^3.16.1",
"eslint-config-angular": "^0.5.0",
"eslint-plugin-angular": "^1.6.1",
"grunt": "~0.4",
"grunt-angular-templates": "~0.5",
"grunt-browser-output": "0.1.0",
"grunt-contrib-clean": "~0.5",
"grunt-contrib-concat": "~0.3",
"grunt-contrib-connect": "~0.6",
"grunt-contrib-copy": "~0.5",
"grunt-contrib-cssmin": "~0.7",
"grunt-contrib-htmlmin": "~0.1",
"grunt-contrib-jshint": "~0.9",
"grunt-contrib-less": "~0.8",
"grunt-contrib-uglify": "~0.2",
"grunt-contrib-watch": "~0.6",
"grunt-dom-munger": "~3.4",
"grunt-file-exists": "^0.1.4",
"grunt-karma": "~0.8.3",
"grunt-ng-annotate": "^1.0.1",
"grunt-replace": "^1.0.1",
"grunt-timer": "^0.6.0",
"karma": "~0.12.6",
"karma-chrome-launcher": "~0.1.3",
"karma-firefox-launcher": "~0.1.3",
"karma-htmlfile-reporter": "^0.3.5",
"karma-jasmine": "~0.1.5",
"karma-mocha-reporter": "^2.2.2",
"karma-ng-html2js-preprocessor": "^1.0.0",
"karma-phantomjs-launcher": "~0.1.4",
"load-grunt-tasks": "~0.2"
After a lot of keyboard facerolling, I've come to this solution:
remove that directive/**/*.html from karma.options.files task configuration, since a) it's not enforcing project "folders-by-feature" structure and b) instead getting the templates from '<%= ngtemplates.main.dest %>' it's solid enough, you just need to change the grunt test task into grunt.registerTask('test',['dom_munger:read','ngtemplates','karma:all_tests']);
remove beforeEach(module('directive/test-directive/test-directive.html')); from test-directive-spec.js, since it looks like it clashes with the previously described ngtemplates mechanism, making the template unavaiable;

NPM and loading external libraries in angular2 typescript

I am using Ionic2 (Browserify), Typescript with NPM.
I am trying to understand how typescript generates the typescript bundle of code and what is included in it. In some cases my node require files are referenced and in other cases they are not.
What seems to be happening is that in some instances e.g jquery i am forced to add a script tag manually in other cases like lodash these are resolved auto-magically and bundled?
What is determining what is correctly referenced as part of the typescript compilation process and what has to happen outside of the process?
In typescript i am using:
import * as jQuery from 'jquery'; -- need to manually add script tag to index.html
import * as _ from 'lodash'; --do not need to add script tag - this is "automagically" added
See image below - some libraries are loaded others are not from the node_modules folder.
Is there something i am missing or is this use case specific to Ionic platform bundling?
Package Json below.
"name": "ionic-conference-app",
"description": "Ionic Conference App",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": ""
"dependencies": {
"#angular/common": "2.0.0-rc.4",
"#angular/compiler": "2.0.0-rc.4",
"#angular/core": "2.0.0-rc.4",
"#angular/forms": "0.2.0",
"#angular/http": "2.0.0-rc.4",
"#angular/platform-browser": "2.0.0-rc.4",
"#angular/platform-browser-dynamic": "2.0.0-rc.4",
"#angular/router": "^2.0.0-rc.2",
"angular2-jwt": "^0.1.18",
"angular2-moment": "^0.8.2",
"breeze-client": "^1.5.10",
"es6-shim": "0.35.0",
"fullcalendar": "^3.0.0-beta",
"ionic-angular": "2.0.0-beta.11",
"ionic-native": "^1.1.0",
"ionicons": "3.0.0",
"jquery": "^3.1.0",
"lodash": "^4.15.0",
"moment": "^2.14.1",
"momentjs": "^1.1.14",
"reflect-metadata": "0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "0.6.12"
"devDependencies": {
"del": "2.2.0",
"gulp": "3.9.1",
"gulp-tslint": "^5.0.0",
"gulp-watch": "4.3.5",
"ionic-gulp-browserify-typescript": "^1.1.0",
"ionic-gulp-fonts-copy": "^1.0.0",
"ionic-gulp-html-copy": "^1.0.0",
"ionic-gulp-sass-build": "^1.0.0",
"ionic-gulp-scripts-copy": "^2.0.0",
"ionic-gulp-tslint": "^1.0.0",
"run-sequence": "1.1.5",
"tslint": "^3.10.1",
"tslint-ionic-rules": "^0.0.3"
"cordovaPlugins": [
"locator": "",
"id": "com.verso.cordova.clipboard"
"locator": "",
"id": "cordova-plugin-splashscreen"
"cordovaPlatforms": [
Standard Ionic2 Gulpfile
var gulp = require('gulp'),
gulpWatch = require('gulp-watch'),
del = require('del'),
runSequence = require('run-sequence'),
argv = process.argv;
* Ionic hooks
* Add ':before' or ':after' to any Ionic project command name to run the specified
* tasks before or after the command.
gulp.task('serve:before', ['watch']);
gulp.task('emulate:before', ['build']);
gulp.task('deploy:before', ['build']);
gulp.task('build:before', ['build']);
// we want to 'watch' when livereloading
var shouldWatch = argv.indexOf('-l') > -1 || argv.indexOf('--livereload') > -1;
gulp.task('run:before', [shouldWatch ? 'watch' : 'build']);
* Ionic Gulp tasks, for more information on each see
* Using these will allow you to stay up to date if the default Ionic 2 build
* changes, but you are of course welcome (and encouraged) to customize your
* build however you see fit.
var buildBrowserify = require('ionic-gulp-browserify-typescript');
var buildSass = require('ionic-gulp-sass-build');
var copyHTML = require('ionic-gulp-html-copy');
var copyFonts = require('ionic-gulp-fonts-copy');
var copyScripts = require('ionic-gulp-scripts-copy');
var tslint = require('ionic-gulp-tslint');
var isRelease = argv.indexOf('--release') > -1;
gulp.task('watch', ['clean'], function(done){
['sass', 'html', 'fonts', 'scripts'],
gulpWatch('app/**/*.scss', function(){ gulp.start('sass'); });
gulpWatch('app/**/*.html', function(){ gulp.start('html'); });
buildBrowserify({ watch: true }).on('end', done);
gulp.task('build', ['clean'], function(done){
['sass', 'html', 'fonts', 'scripts'],
minify: isRelease,
browserifyOptions: {
debug: !isRelease
uglifyOptions: {
mangle: false
}).on('end', done);
gulp.task('sass', buildSass);
gulp.task('html', copyHTML);
gulp.task('fonts', copyFonts);
gulp.task('scripts', copyScripts);
gulp.task('clean', function(){
return del('www/build');
gulp.task('lint', tslint);
The issue is most likely due to the jQuery import not being used. In such situations, TypeScript won't emit a require call - and without a require call, the jquery module will not make it into the bundle. Instead, you can use this import syntax:
import 'jquery';
There is a discussion regarding this TypeScript feature in this GitHub issue.

Why is my gulp task not converted jsx when using reactify transform with browserify and glob

I have been working on converting a grunt task to gulp. The grunt file looks like this:
browserify: {
options: {
transform: [ require('grunt-react').browserify ]
client: {
src: ['react/**/*.jsx'],
dest: 'public/js/browserify/bundle.js'
I saw many examples of browserify and gulp but all of them had just a single file start point. To get round this I tried using glob. After several false starts I came up with the following. It runs without error and creates a single bundle.js file, but reactify doesn't seem to be working correctly, as jsx does not seem to be converted so I end up with the error:
Uncaught Error: Cannot find module './components/NoteApp.jsx'
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var glob = require('glob');
var reactify = require('reactify');
gulp.task('browserify', function (cb) {
glob('./react/**/*.jsx', {}, function (err, files) {
var b = browserify();
files.forEach(function (file) {
ddprrt requested some further details on structure so here is how the react folder is laid out. The code is taken from this article which uses this github zip source to demonstrate react and reflux. The project was very close to what I needed as a start point but uses Grunt instead of Gulp.
The react folder is structured like this:
react \ App.jsx
\ Bootstrap.jsx
\ components \ NoteApp.jsx
\ NoteCreationBox.jsx
\ Note.jsx
\ NoteListBox.jsx
\ NoteList.jsx
\ TextArea.jsx
The error is coming from a line in the App.jsx file:
var React = require('react');
var NoteApp=require('./components/NoteApp.jsx');
but changing this line causes the gulp talk to fail with a missing file error.
I guess I got the answer now. It was really some version mixup, reactify seems to be more advanced and handle things differently than the reactify in the original did. Might be because both are still in experimental state. I also guess that React/Reflux moved on, so you ended up with some versions which didn't quite comply. However, you still can fix it and run you app:
var gulp = require('gulp');
var browserify = require('browserify');
var source = require('vinyl-source-stream');
var glob = require('glob');
var reactify = require('grunt-react').browserify;
gulp.task('browserify', function (cb) {
glob('./react/Bootstrap.jsx', function (err, files) {
var b = browserify({
entries: files
Instead of using require('reactify'), we take the reactify provided by grunt-react. See the code above. You should just be able to switch the middleware. Also, don't go over all the files, just your main entry point, which is in that case Bootstrap.jsx.
I know that this is rather inconvenient, maybe when you try your own app, start with a fresh setup.
** Update**
that was my package.json afterwards, just working into the previous project:
"name": "react-note-app",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www",
"main": "./bin/www"
"engines": {
"node": ">= 0.10.0"
"dependencies": {
"body-parser": "~1.8.1",
"cookie-parser": "~1.3.3",
"debug": "~2.0.0",
"ejs": "~0.8.5",
"express": "~4.9.0",
"express-session": "^1.8.2",
"morgan": "~1.3.0",
"node-jsx": "^0.11.0",
"react": "^0.11.2",
"reflux": "^0.1.13",
"serve-favicon": "~2.1.3"
"devDependencies": {
"browserify": "^9.0.7",
"glob": "^5.0.3",
"grunt": "^0.4.5",
"grunt-browserify": "^3.0.1",
"grunt-contrib-watch": "^0.6.1",
"grunt-nodemon": "^0.3.0",
"grunt-react": "^0.9.0",
"gulp": "^3.8.11",
"react-tools": "^0.11.2",
"reactify": "^1.1.0",
"vinyl-source-stream": "^1.1.0"