How to deploy node that uses Gulp to heroku - node.js

I'm using gulp and also gulp plugins like gulp-minify-css, gulp-uglify etc (that listed as npm dependencies for my application).
Also I don't commit npm_modules folder and public folder, where all generated files are. And I can't figure out how to build my app (I have gulp build command) after deploy and setup my server (it's already looking for public folder).
It seems me a bad idea to commit before upload. Maybe there are some gentle decisions... Any thoughts?
Forked from: How to deploy node app that uses grunt to heroku

I was able to get this to work by adding this into my "package.json" file:
"scripts": {
"start": "node app",
"postinstall": "gulp default"
}
The postinstall script is run after the build pack. Check this for more information. The only annoying thing is that all of your dependencies have to live under "dependencies" instead of having separate "devDependencies"
I didn't need to do anything else with buildpacks or configuration. This seems like the simplest way to do it.
I wrote about the process I used here

You can do it!
There were a few key measures that helped me along the way:
heroku config:set NODE_ENV=production - to set your environment to 'production'
heroku config:set BUILDPACK_URL=https://github.com/krry/heroku-buildpack-nodejs-gulp-bower - to enable a customised Heroku buildpack. I incorporated elements of a few to make one that worked for me.
A gulp task entitled heroku:production that performs the build tasks that need to happen on the heroku server when NODE_ENV===production. Here's mine:
var gulp = require('gulp')
var runSeq = require('run-sequence')
gulp.task('heroku:production', function(){
runSeq('clean', 'build', 'minify')
})
clean, build, and minify are, of course separate gulp tasks that do the magic gulpage
If your application lives in /app.js, either:
(A) make a Procfile in the project root that contains only: web: node app.js, or
(B) add a start script to your package.json:
"name": "gulp-node-app-name",
"version": "10.0.4",
"scripts": {
"start": "node app.js"
},
And like #Zero21xxx says, put your gulp modules in your normal dependencies list in package.json, not in the devDependencies, which get overlooked by the buildpack, which runs npm install --production

The easiest way I found was:
Setup gulp on package.json scripts area:
"scripts": {
"build": "gulp",
"start": "node app.js"
}
Heroku will run build before starting the app.
Include gulp on dependencies instead of devDevependencies, otherwise Heroku won't be able to find it.
There is more relevant info about it on Heroku Dev Center: Best Practices for Node.js Development

How to deploy to Heroku (or Azure) with git-push
// gulpfile.js
var gulp = require('gulp');
var del = require('del');
var push = require('git-push');
var argv = require('minimist')(process.argv.slice(2));
gulp.task('clean', del.bind(null, ['build/*', '!build/.git'], {dot: true}));
gulp.task('build', ['clean'], function() {
// TODO: Build website from source files into the `./build` folder
});
gulp.task('deploy', function(cb) {
var remote = argv.production ?
{name: 'production', url: 'https://github.com/<org>/site.com', branch: 'gh-pages'},
{name: 'test', url: 'https://github.com/<org>/test.site.com', branch: 'gh-pages'};
push('./build', remote, cb);
});
Then
$ gulp build --release
$ gulp deploy --production
See also
https://github.com/koistya/git-push
https://github.com/kriasoft/react-starter-kit (tools/deploy.js)

There's a specific startup script that Heroku provides;
"scripts": {
"start": "nodemon app.js",
"heroku-postbuild": "gulp"
}
note that in your gulpfile.js (gulpfile.babel.js if you es6-ifed your gulp build process), you should have a task name default which will be automatically run after the dependencies are installed via Heroku.
https://devcenter.heroku.com/articles/nodejs-support#heroku-specific-build-steps

Heroku finds that there is a gulpfile in your project and expects there to be a heroku:production task (in the gulpfile). So all you need to do is register a task that matches that name:
gulp.task("heroku:production", function(){
console.log('hello'); // the task does not need to do anything.
});
This is enough for heroku to not reject your app.

I had to take a slightly different to get this working because I'm using browsersync:
package.json
"scripts": {
"start": "gulp serve"
}
gulp.js
gulp.task('serve', function() {
browserSync({
server: {
baseDir: './'
},
port: process.env.PORT || 5000
});
gulp.watch(['*.html', 'css/*.css', 'js/*.js', 'views/*.html', 'template/*.html', './*.html'], {cwd: 'app'}, reload);
});
Setting the port to be environment port is important to prevent error when deploying in Heroku. I did not need to set a postinstall script.

It's possible to piggyback any command you want over the top of npm install. Much like the linked question in your post, you can add an install directive in scripts within package.json that will run after all the node deps have been installed that does the build.
Your main issue will be sorting out the correct relative paths for everything.
{
...
scripts:{
install: "YOUR GULP BUILD COMMAND"
}
...
}

Related

Run npm script with nodemon command

I am testing GraphQL Server from Apollo and what to integrate nodemon to it. Here's sample file structure :
build/
src/
server.js
Here my npm scripts looks like this
"scripts": {
"start": "babel --presets es2015,stage-2 server.js -d build/ && node build/server.js",
"dev": "nodemon server.js" // Sample code here
}
What npm run start would do is to convert ES6 code into build/server.js using babel and execute it. This would start the server correctly.
What I want is to watch for changes in server.js or in src/ and restart the server if changes occur. Here I want to execute npm run start command if any changes occur. What is the correct 'nodemon' command to my need. Its better if I could use npm run dev like command to start development using nodemon.
you can use gulpjs to watch any changes in specific folders and then command it to do something.
With your sample, you want to convert the code to es6 too. so it also need gulp-bable and . you can include babel-preset-stage-2 if you want. So you can simply put the code below in gulpfile.js
gulp.task('build-es2015', () => {
return gulp.src('server.js')
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest('build'));
});
gulp.task('watch', () => {
gulp.watch(['./app/*.js'], ['build-es2015'])
})
Basically, the task 'watch' will keep watching the specific files. When they are saved then it will to execute the task 'build-es2015' to convert to es6.
And then nodemon, it needs gulp-nodemon then you can do on gulpfile.js
gulp.task('server', () => {
nodemon({
script: 'build/server.js',
ext: 'js',
ignore: [
'server.js',
'node_modules/**',
'test/**',
'build/**'
]
})
.on('restart', () => { console.log(`Server restarted!`) })
})
The above will keep watching build/server.js'. whenever it is changed, nodemon will automatically restart the server.
And the last piece for gulpfile.js
gulp.task('dev', ['server', 'watch'])
Include the tasks that need to be executed for gulp command.
$ gulp dev
or with npm command
"scripts": {
"start": "gulp dev"
}
so you can npm run start as well.
And dont forget to require all packages in gulpfile.js
const gulp = require('gulp')
const babel = require('gulp-babel')
const nodemon = require('gulp-nodemon')

How to run 2 different commands on deploy and restart using Node.js on Heroku?

I am writing a Node.js app and using Heroku to host it. And also I use Webpack + Babel to bundle all my server files into one and to use ES2015 syntax. But the thing is, I need to build my app before running it. So I put this command into package.json:
"scripts": {
"start": "webpack && node build/server.js"
},
This works, but the problem is, when I run heroku restart, my app runs only after rebuild. And the same story when my app crashes.
So I guess I need 2 different commands: one on deploy (webpack) and one in npm start (node build/server.js)
How can I accomplish this?
Actually it was not that hard. Just had to change my package.json to
"scripts": {
"heroku-postbuild": "webpack",
"start": "node build/server.js"
}
(according to this article: Heroku Node.js Support)

What to define as 'host' when deploying my node gulp app to heroku?

I am trying to push my gulp node app to heroku. In the package.json I have "postinstall": "gulp serveprod" to run a gulp command that starts a webserver.
In package.json
"scripts": {
"start": "node app",
"postinstall": "gulp serveprod",
...etc
}
My gulp task:
gulp.task('serveprod', function() {
connect.server({
root: 'app',
host: '',
port: process.env.PORT,
livereload: false,
open: false
});
});
When I run 'gulp serveprod' in the terminal the app works fine on localhost. However when I run 'gulp push heroku" I get the following that stays until it timesout:
postinstall /tmp/build_c27e9c799bef2671ed033b271feecf87
remote: > gulp serveprod
remote:
remote: [03:54:36] Using gulpfile /tmp/build_c27e9c799bef2671ed033b271feecf87/gulpfile.js
remote: [03:54:36] Starting 'serveprod'...
remote: [03:54:36] Finished 'serveprod' after 12 ms
remote: [03:54:36] Server started http://localhost:8080
My understanding is that the gulp server is using localhost by default and I need to specify the host where heroku will host the app. However I have no idea what to put as 'host'.
I looked at this answer and tried '0.0.0.0' which didn't work. I have also tried http://infinite-lowlands-6023.herokuapp.com/ which is the name of my app which got a similar result, pushing to heroku would just stop at this gulp task. I have followed this question that helped me get through other issues but I am now well and truly stuck on this one.
What do I need to do to deploy this to Heroku successfully? What information needs to go in the 'host' value?
Thanks :)

Running a Grunt build task on Heroku

I am deploying a Node.js application on Heroku. My production deployment is based on a Grunt task that minifies js and css files, placing them in a /dist folder from which they are called.
How can I add this step on the Heroku deployment?
Use a postinstall script, as outlined in Heroku's DevCenter docs for node:
https://devcenter.heroku.com/articles/node-with-grunt
eg:
"scripts": {
"postinstall": "grunt uglify",
"start": "node server.js"
}

Error running Grunt Build on Heroku

So I am installing a simple Backbone application on Heroku that I generated using the Yeoman Backbone generator. I have a very simple node.js server file to serve up the Backbone application, but had trouble deploying to Heroku due to missing dependencies:
Output:
remote: Loading "Gruntfile.js" tasks...ERROR
remote: >> Error: Cannot find module 'connect-livereload'
remote: Warning: Task "build" not found. Use --force to continue.
Server.js
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
app.use(express.static(__dirname + '/app'));
app.listen(port, function() {
console.log('App is running on port ' + port);
});
packages.json
{
"name": "ssi",
"version": "0.0.0",
"dependencies": {
...
},
"devDependencies": {
"bower": "^1.4.1",
"connect": "^3.3.5",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
...
},
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"start": "node server.js",
"test": "mocha",
"postinstall": "bower install && grunt build"
}
}
Originally I had problems running bower install because I hadn't added bower to the dependencies in packages.json, so I thought, "maybe I have to add it to the normal dependencies list instead of devDependencies, since this is my deployment process.
So I added bower and grunt to the dependencies list, but then it would fail while running grunt build because now it couldn't find any of the required grunt modules used during the build task. I figured there must be a better way to let Heroku see these dependencies without adding them to the production dependencies list.
I already tried setting the NODE_ENV variable to "development" like so:
$ heroku config:set NODE_ENV=development
But that didn't seem to have any effect. So since I am answering my own question, the hypothetical question in question is:
"How do I get Heroku to run bower install and grunt build without having to move all my dependencies into the production dependencies list?"
N.B. - I realise that a "proper" deployment process might instead add all this stuff to a distribution folder, including the dependencies. This question and answer are aimed at those, like me, who are instead attempting to just push their current build to Heroku without having to set up a "better" deployment process just yet.
In the end the solution was very simple. In the first few lines of the console output when pushing my app to Heroku, is the following line:
remote: NPM_CONFIG_PRODUCTION=true
It appears that changing this environment variable to false will cause NPM to install the devDependencies list as well. So just type in the following:
$ heroku config:set NPM_CONFIG_PRODUCTION=false
And you should then see Heroku build and deploy successfully.

Resources