GULP - How to use gulp in production /deployment? - gulp

I have not much experience with gulp and wonder what to do when deploying? How do I exclude certain tasks (like my 'sass' task for example) when deploying or how does gulp work for production - what would I do? I'm not sure if I use the wrong words or just don't understand it, but I couldn't find much online so far.
My gulp file:
var gulp = require('gulp');
var sass = require('gulp-sass');
var browserSync = require('browser-sync').create();
var cleanCSS = require('gulp-clean-css');
var rename = require("gulp-rename");
var uglify = require('gulp-uglify');
// Compiles SCSS files from /scss into /css
gulp.task('sass', function() {
return gulp.src('scss/main.scss')
.pipe(sass())
.pipe(gulp.dest('css'))
.pipe(browserSync.reload({
stream: true
}))
});
// Minify compiled CSS
gulp.task('minify-css', ['sass'], function() {
return gulp.src('css/main.css')
.pipe(cleanCSS({
compatibility: 'ie8'
}))
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest('css'))
.pipe(browserSync.reload({
stream: true
}))
});
// Minify custom JS
gulp.task('minify-js', function() {
return gulp.src('js/scripts.js')
.pipe(uglify())
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest('js'))
.pipe(browserSync.reload({
stream: true
}))
});
// Copy vendor files from /node_modules into /vendor
// NOTE: requires `npm install` before running!
gulp.task('copy', function() {
gulp.src([
'node_modules/bootstrap/dist/**/*',
'!**/npm.js',
'!**/bootstrap-theme.*',
'!**/*.map'
])
.pipe(gulp.dest('vendor/bootstrap'))
gulp.src(['node_modules/jquery/dist/jquery.js',
'node_modules/jquery/dist/jquery.min.js'])
.pipe(gulp.dest('vendor/jquery'))
gulp.src(['node_modules/jquery-easing/*.js'])
.pipe(gulp.dest('vendor/jquery-easing'))
})
// Default task
gulp.task('default', ['sass', 'minify-css', 'minify-js', 'copy']);
// Configure the browserSync task
gulp.task('browserSync', function() {
browserSync.init({
server: {
baseDir: ''
},
})
})
// Dev task with browserSync
gulp.task('dev', ['browserSync', 'sass', 'minify-css', 'minify-js'], function() {
gulp.watch('scss/*.scss', ['sass']);
gulp.watch('css/*.css', ['minify-css']);
gulp.watch('js/*.js', ['minify-js']);
// Reloads the browser whenever HTML or JS files change
gulp.watch('*.html', browserSync.reload);
gulp.watch('js/**/*.js', browserSync.reload);
});

It depends entirely on your hosting solution and what deployment process you prefer to use. Some of your former questions have the Heroku tag so I assume you use Heroku. If not you can use the second strategy.
One method of using Gulp with Heroku is to automatically run Gulp when you push to the Heroku branch. This is done by having a postinstall script in package.json. Like so:
"scripts": {
..
"postinstall": "gulp"
}
When you push to the remote branch, Heroku will run the build process as normal. After the build process is done it will run the postinstall script. That will run the default task in the gulpfile. This will, of course, run on your Heroku dyno, not on localhost.
If you want to change the different sub tasks that are run during postinstall you can make a new task like this:
gulp.task('deployment', ['minify-css', 'minify-js', 'copy']);
and change the postinstall script to this:
"postinstall": "gulp deployment"
The deployment task will now run instead of the default task.
For this to work you need all the gulp packages in dependencies rather than devDependencies. devDependencies are, after all, not installed on Heroku.
The files that Gulp builds should be added to the .gitignore file. The files that Gulp outputs are often sent to a folder called dist which is kept out of the repository completely. You don't need to have them in the repository as they are being built on Heroku instead.
Another method is to build the files manually yourself before deployment. That means you don't have gulp in the postinstall script (or don't have the postinstall script at all) and keep the gulp packages in devDependencies. The files that are being built should also not be in .gitignore.
Before you deploy you build the files with gulp deployment and then commit them. When you push to Heroku the files will be uploaded like normal, instead of being built there.
This strategy is usually used when you have an ordinary web hosting service.

Related

Confused with combining gulp and webpack with watch

I'm trying to create a gulpfile that allows me to compile scss and js files.
Calling webpack from a gulp task seems to work as expected (simply followed the webpack-stream intro.
However, I'm failing setting up watching for files. It's working as expected for scss files, but not for webpack compilation. It occurs once at launch, block the console, but does not recompile files.
Here is my gulpfile:
'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var webpackConfig = require('./webpack.config.js');
var webpack = require('webpack-stream');
gulp.task('default', function () {
// place code for your default task here
});
gulp.task('watch', ['sass:watch','webpack:watch']);
gulp.task('sass', function () {
return gulp.src('./Styles/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write(".",{ ext: '.map' }))
.pipe(gulp.dest('./wwwroot/styles'));
});
gulp.task('sass:watch', function () {
gulp.watch('./Styles/**/*.scss', ['sass']);
});
gulp.task('webpack', function(){
return gulp.src('App/entry.js')
.pipe(webpack( webpackConfig ))
.pipe(gulp.dest('./'));
});
gulp.task('webpack:watch', function(){
var watch = Object.create(webpackConfig);
watch.watch = true;
return gulp.src('App/entry.js')
.pipe(webpack(webpackConfig))
.pipe(gulp.dest('./'));
});
When I run gulp watch, I get this output:
c:\Data\projets\someproject>gulp watch
[13:30:18] Using gulpfile c:\Data\projets\someproject\gulpfile.js
[13:30:18] Starting 'sass:watch'...
[13:30:18] Finished 'sass:watch' after 13 ms
[13:30:18] Starting 'webpack:watch'...
[13:30:22] Version: webpack 1.12.13
Asset Size Chunks Chunk Names
./wwwroot/dist/bundle.js 498 kB 0 [emitted] main
./wwwroot/dist/bundle.js.map 616 kB 0 [emitted] main
[13:30:22] Finished 'webpack:watch' after 3.92 s
[13:30:22] Starting 'watch'...
[13:30:22] Finished 'watch' after 11 µs
However, even if the console does not returns to the prompt, no bundle file is updated, if I update my sources.
I don't believe the issue is in my webpack.config.js file. If I run webpack --watch --color --progress in the prompt, I see the recompilation of bundle whenever a file is modified.
Thanks for clarification, I'm learning javascript ecosystem the hard way :)
In your console output, you should get 'webpack is watching for changes' if you do everything correctly. You have set watch.watch to true, but in the next step you have referenced to the old webpackConfig, for which the watch parameter is not true. You should use:
return gulp.src('App/entry.js')
.pipe(webpack(watch))
.pipe(gulp.dest('./'));
It worked after this change and the gulp watch polls for both the changes. You will also see in your console 'webpack is watching for changes'.
I hope this solves the issue.

Gulp not watching correctly

I'm new to using gulp and I think I have it setup correctly, but it does not seem to be doing what it should be doing.
My gulpfile.js has
gulp.task('compass', function() {
return gulp.src('sites/default/themes/lsl_theme/sass/**/*.scss')
.pipe(compass({
config_file: 'sites/default/themes/lsl_theme/config.rb',
css: 'css',
sass: 'scss'
}))
.pipe(gulp.dest('./sites/default/themes/lsl_theme/css'))
.pipe(notify({
message: 'Compass task complete.'
}))
.pipe(livereload());
});
with
gulp.task('scripts', function() {
return gulp.src([
'sites/default/themes/lsl_theme/js/**/*.js'
])
.pipe(plumber())
.pipe(concat('lsl.js'))
.pipe(gulp.dest('sites/default/themes/lsl_theme/js'))
// .pipe(stripDebug())
.pipe(uglify('lsl.js'))
.pipe(rename('lsl.min.js'))
.pipe(gulp.dest('sites/default/themes/lsl_theme/js'))
.pipe(sourcemaps.write())
.pipe(notify({
message: 'Scripts task complete.'
}))
.pipe(filesize())
.pipe(livereload());
});
and the watch function
gulp.task('watch', function() {
livereload.listen();
gulp.watch('./sites/default/themes/lsl_theme/js/**/*.js', ['scripts']);
gulp.watch('./sites/default/themes/lsl_theme/sass/**/*.scss', ['compass']);
});
when I run gulp, the result is
[16:14:36] Starting 'compass'...
[16:14:36] Starting 'scripts'...
[16:14:36] Starting 'watch'...
[16:14:37] Finished 'watch' after 89 ms
and no changes are registered.
for file structure, my gulpfile.js is in the root directory and the sass, css, and js are all in root/sites/default/themes/lsl_theme with the sass folder containing the folder 'components' full of partials.
My assumption is that you are on windows? Correct me if I'm wrong.
There is this problem that gulp-notify tends to break the gulp.watch functions. Try commenting out
// .pipe(notify({
// message: 'Scripts task complete.'
// }))
and see if the problem still exists.
If that does fix the issue, a solution from this thread may be helpful.
You can use the gulp-if
plugin in combination with
the os node module
to determine if you are on Windows, then exclude gulp-notify, like
so:
var _if = require('gulp-if');
//...
// From https://stackoverflow.com/questions/8683895/variable-to-detect-operating-system-in-node-scripts
var isWindows = /^win/.test(require('os').platform());
//...
// use like so:
.pipe(_if(!isWindows, notify('Coffeescript compile successful')))
It turns out that a large part of my issue was just simply being a rookie with Gulp. When I removed 'scripts' from my gulp watch it started working.
I then made the connection that it was watching the same directory that it was placing the new concatenated and minified js files in so it was putting the new file, checking that file, and looping over and over causing memory issues as well as not allowing 'compass' to run.
After creating a 'dest' folder to hold the new js everything started working just peachy.

How to temporarily disable browsersync?

How can I temporarily disable browsersync, so that it doesn't inject/modify HTML pages? (For testing and debugging.)
There doesn't seem to be a configuration option to do just this, but one hacky workaround is to use snippetOptions to specify a string that will will never be found in the HTML:
snippetOptions: {
rule: {
match: /qqqqqqqqq/
}
}
If this string cannot be found in the HTML, the snippet will never be injected, and browsersync will be inert.
You can use Yargs to send parameters and enable or disable 'watch' task.
Remember this command line to install required components:
npm i --save gulp browser-sync yargs runSequence
On gulpfile.js file:
browserSync.init({
port: 80,
notify: false,
cors: true,
browser: 'chrome',
open: 'local'
});
gulp.task('watch', ['browserSync'], function (){
gulp.watch('dev/*.html', browserSync.reload);
gulp.watch('dev/**/*.js', browserSync.reload);
gulp.watch('dev/**/*.css', browserSync.reload);
});
gulp.task('default', function(callback) {
var sequence = ['browserSync'];
if (args.sync){
sequence.push('watch')
}
runSequence(sequence,callback);
});
This if (args.sync) lines use truthy/falsy searching for sync values and enable/disable 'watch' task.
BrowserSync with watch:
gulp --sync true
BrowserSync without watch:
gulp or gulp --sync false

Gulp Watch and Nodemon conflict

Short of it: started using Gulp recently (convert from Grunt), and am trying to use both Gulp's default watch task (not gulp-watch from npm) for SASS/JS/HTML and gulp-nodemon (from npm) to restart an Express server upon changes. When running just gulp watch, it works fine; and when running gulp server (for nodemon) that works fine. However, using both together (shown below in the configuration of the default task), the watch stuff isn't working. The task is running, and on the CLI gulp shows 'Starting' and 'Finished' for the watch tasks, but the files don't update.
Relevant task configurations:
Concat javascript:
gulp.task('js:app', function(){
return gulp.src([
pathSource('js/application/modules/**/*.js'),
pathSource('js/application/_main.js')
])
.pipe(concat('application.js'))
.pipe(gulp.dest('./build/assets/js')).on('error', utils.log);
});
Nodemon, restart on changes to express app:
gulp.task('express', function(){
return nodemon({script:'server.js', ext:'js', cwd: __dirname + '/express', legacyWatch: true})
.on('restart', function(){
//gulp.run('watch'); // doesn't work :(
});
});
Watch javascript changes, and run js:app for concat'ing.
gulp.task('watch', function(){
gulp.watch(pathSource('js/application/**/*.js'), ['js:app']);
});
Default task, to initialize gulp watch and nodemon simultaneously:
gulp.task('default', ['watch', 'express']);
If anyone has any ideas, thanks in advance!
gulp.run calls have been deprecated, so I'd try a different approach. Since you're already using gulp, may I suggest giving gulp-nodemon a try?
As per gulp-nodemon documentation, you can pass it an array of tasks to execute:
UPDATE: Here's the full gulpfile.js file, together with a working sample on github.
'use strict';
// Main dependencies and plugins
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var nodemon = require('gulp-nodemon');
var assets = 'assets/js/**/*.js';
var publicDir = 'public/javascripts';
// Lint Task
gulp.task('lint', function () {
return gulp.src(assets)
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'));
});
// Concatenate and minify all JS files
gulp.task('scripts', function () {
return gulp.src(assets)
.pipe(concat('global.js'))
.pipe(gulp.dest(publicDir))
.pipe(rename('global.min.js'))
.pipe(uglify())
.pipe(gulp.dest(publicDir));
});
// Watch Files For Changes
gulp.task('watch', function () {
gulp.watch(assets, ['lint', 'scripts']);
});
gulp.task('demon', function () {
nodemon({
script: 'server.js',
ext: 'js',
env: {
'NODE_ENV': 'development'
}
})
.on('start', ['watch'])
.on('change', ['watch'])
.on('restart', function () {
console.log('restarted!');
});
});
// Default Task
gulp.task('default', ['demon']);
This way, you spawn the watch task upon nodemon's start and ensure that the watch task is again triggered whenever nodemon restarts your app.
EDIT: seems you should be calling the on-change event from gulp-nodemon, which will handle compile tasks before the restart event triggers.
EDIT: It seems nodemon's on('change', callback) is removed from their API
FWIW, it seems that using the cwd parameter on gulp-nodemon's configuration actually sets the entire gulp cwd to that directory. This means future tasks will be executed in the wrong directory.
I had this problem when running gulp watch tasks on my frontend server at the same time as nodemon tasks on my backend server (in the same gulpfile), there was a race condition wherein if the nodemon command was executed first, the frontend stuff would actually build into (Home)/backend/frontend instead of (Home)/frontend, and everything would go pearshaped from there.
I found that using watch and script params on gulp-nodemon worked around this (although it still looks like nodemon is watching my entire project for changes rather than the built backend directory).

gulp watch terminates immediately

I have a very minimal gulpfile as follows, with a watch task registered:
var gulp = require("gulp");
var jshint = require("gulp-jshint");
gulp.task("lint", function() {
gulp.src("app/assets/**/*.js")
.pipe(jshint())
.pipe(jshint.reporter("default"));
});
gulp.task('watch', function() {
gulp.watch("app/assets/**/*.js", ["lint"]);
});
I cannot get the watch task to run continuously. As soon as I run gulp watch, it terminates immediately.
I've cleared my npm cache, reinstalled dependencies etc, but no dice.
$ gulp watch
[gulp] Using gulpfile gulpfile.js
[gulp] Starting 'watch'...
[gulp] Finished 'watch' after 23 ms
It's not exiting, per se, it's running the task synchronously.
You need to return the stream from the lint task, otherwise gulp doesn't know when that task has completed.
gulp.task("lint", function() {
return gulp.src("./src/*.js")
^^^^^^
.pipe(jshint())
.pipe(jshint.reporter("default"));
});
Also, you might not want to use gulp.watch and a task for this sort of watch. It probably makes more sense to use the gulp-watch plugin so you can only process changed files, sort of like this:
var watch = require('gulp-watch');
gulp.task('watch', function() {
watch({glob: "app/assets/**/*.js"})
.pipe(jshint())
.pipe(jshint.reporter("default"));
});
This task will not only lint when a file changes, but also any new files that are added will be linted as well.
To add to OverZealous' answer which is correct.
gulp.watch now allows you to pass a string array as the callback so you can have two separate tasks. For example, hint:watch and 'hint'.
You can then do something like the following.
gulp.task('hint', function(event){
return gulp.src(sources.hint)
.pipe(plumber())
.pipe(hint())
.pipe(jshint.reporter("default"));
})
gulp.task('hint:watch', function(event) {
gulp.watch(sources.hint, ['hint']);
})
This is only an example though and ideally you'd define this to run on say a concatted dist file.