Using npm to build and deploy Hugo
After moving to Hugo I wanted an easy way to deploy new posts. Opening an FTP client every time is far too much work!
As I’m already using npm to minify the JS and CSS I decided to use that to handle the deploying too.
The following requires both rsync and curl (as well as npm) to be installed. I’ve tested this on Linux and Mac. It should work on Windows too as long as rsync and curl are installed.
First create the package.json
file and put the following in it:
{
"name": "example.com",
"version": "1.0.0",
"private": true,
"config" : {
"sitemap" : "https://www.example.com/sitemap.xml",
"destination" : "user@example.com:/home/example/public_html/"
},
"scripts": {
"clean": "rimraf ./public",
"prebuild": "npm run clean",
"build": "hugo",
"predeploy": "npm run build",
"deploy": "rsync -crtvz --progress ./public/ $npm_package_config_destination",
"ping-sitemap:google": "curl -so /dev/null --fail https://www.google.com/ping?sitemap=$npm_package_config_sitemap",
"ping-sitemap:bing": "curl -so /dev/null --fail https://www.bing.com/ping?sitemap=$npm_package_config_sitemap",
"ping-sitemap": "npm run ping-sitemap:google & ping-sitemap:bing"
},
"devDependencies": {
"rimraf": "^2.5.4"
}
}
Then change the sitemap and destination config values for your site and that’s it, ready to use!
Usage:
npm run deploy -- --dry-run
npm run deploy
npm run ping-sitemap
Using gulp
For comparrison, here is the gulp alternative:
npm install --save-dev gulp gulp-rsync rimraf minimist request
gulpfile.js:
const gulp = require('gulp');
const rsync = require('gulp-rsync');
const exec = require('child_process').exec;
const rimraf = require('rimraf');
const request = require('request');
const argv = require('minimist')(process.argv.slice(2));
function httpPing(url) {
return new Promise((resolve, reject) => {
request(url, function(err, response) {
if (err) {
reject(err);
} else if (response.statusCode !== 200) {
reject(Error('URL: ' + url + ' had status: ' + response.statusCode));
} else {
resolve();
}
});
});
}
gulp.task('clean', function (cb) {
rimraf('./public', cb);
});
gulp.task('build', ['clean'], function (cb) {
exec('hugo', function (err, stdout, stderr) {
console.log('\n-------- Hugo output--------\n');
console.log(stdout);
console.log('----------------------------\n');
cb(err);
});
});
gulp.task('deploy', ['build'], function () {
// TODO: Change the hostname, username and destination below
return gulp.src('public/**')
.pipe(rsync({
root: 'public/',
hostname: 'example.com',
username: 'ssh-user',
dryrun: !!argv['dry-run'],
incremental: true,
progress: true,
times: true,
compress: true,
destination: '/home/example.com/public_html'
}));
});
gulp.task('ping-sitemap', function (cb) {
// TODO: Change the sitemap URL
const sitemapUrl = 'https://www.example.com/sitemap.xml';
const sitemapParam = encodeURIComponent(sitemapUrl);
const googlePing = 'https://www.google.com/ping?sitemap=' + sitemapParam;
const bingPing = 'https://www.bing.com/ping?sitemap=' + sitemapParam;
Promise.all([
httpPing(googlePing),
httpPing(bingPing)
]).then(() => cb(), cb);
});
Usage:
gulp deploy --dry-run
gulp deploy
gulp ping-sitemap
The gulp version is more extensible but for my needs the NPM one works well!
Comments