Jekyll, critical CSS, HTML minify in one gulp task? - html

I have a website based on Jekyll and I want to make it as fast as possible. My goal is to have a gulp task that builds the Jekyll site, generates the critical CSS and minifies the HTML.
Part of my gulpfile looks something like this:
gulp.task("jekyll", function (gulpCallBack){
var spawn = require("child_process").spawn;
var jekyll = spawn('jekyll', ["build"], {stdio: "inherit"});
jekyll.on("exit", function(code) {
gulpCallBack(code === 0 ? null : "ERROR: Jekyll process exited with code: "+code);
});
});
gulp.task("html", function() {
gulp.src("./_site/index.html")
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(gulp.dest("./_site"))
gulp.src("./_site/*/*.html")
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(gulp.dest("./_site/./"))
});
gulp.task("critical", function() {
critical.generate({
base: '_site/',
src: 'index.html',
dest: 'css/critical.css',
minify: true,
extract: true,
width: 320,
height: 480
});
critical.inline({
base: '_site/',
src: 'index.html',
dest: 'index.html',
minify: true
});
})
If I run the tasks separately, gulp jekyll, then gulp html and finally gulp critical everything works fine and as I want to. Since I am lazy I do not want to run three tasks manually each time. My idea was to run them synchronously/one after the other by using the following code.
gulp.task("jekyll", function (gulpCallBack){};
gulp.task("html", ["jekyll"], function() {};
gulp.task("critical", ["html"], function() {};
I thought, I just could run gulp critical which waits for the html task to finish which waits for the jekyll task to finish. The site got build and minified but the critical CSS is not injected. The task run in the correct order.
➜ jonas.re git:(master) ✗ gulp critical
[19:21:18] Using gulpfile ~/dev/jonas.re/gulpfile.js
[19:21:18] Starting 'jekyll'...
Configuration file: /Users/j.reitmann/dev/jonas.re/_config.yml
Source: /Users/j.reitmann/dev/jonas.re
Destination: /Users/j.reitmann/dev/jonas.re/_site
Generating...
done.
Auto-regeneration: disabled. Use --watch to enable.
[19:21:18] Finished 'jekyll' after 528 ms
[19:21:18] Starting 'html'...
[19:21:18] Finished 'html' after 5.37 ms
[19:21:18] Starting 'critical'...
[19:21:18] Finished 'critical' after 1.63 ms
Again, by running them manually after each other, it works perfectly.
I heard of runSequence but I have to return a stream which I have no idea of to do that for the jekyll task (if that is even possible?). And maybe the error something different since this works:
➜ jonas.re git:(master) ✗ gulp jekyll
[19:27:49] Using gulpfile ~/dev/jonas.re/gulpfile.js
[19:27:49] Starting 'jekyll'...
Configuration file: /Users/j.reitmann/dev/jonas.re/_config.yml
Source: /Users/j.reitmann/dev/jonas.re
Destination: /Users/j.reitmann/dev/jonas.re/_site
Generating...
done.
Auto-regeneration: disabled. Use --watch to enable.
[19:27:50] Finished 'jekyll' after 549 ms
➜ jonas.re git:(master) ✗ gulp html
[19:27:54] Using gulpfile ~/dev/jonas.re/gulpfile.js
[19:27:54] Starting 'html'...
[19:27:54] Finished 'html' after 5.56 ms
➜ jonas.re git:(master) ✗ gulp critical
[19:27:57] Using gulpfile ~/dev/jonas.re/gulpfile.js
[19:27:57] Starting 'critical'...
[19:27:57] Finished 'critical' after 1.66 ms
I would be very thankful for any help. You can have a look for my whole gulpfile here.

The problem come from critical. I get it working like this :
_config.yml
As we need style.scss to be parsed in order to generate a css for crititical.
Remove /css/style.scss from the exclude array.
style.scss
./_sass path is useless a it is the default path for Jekyll sass processor.
In order to be processed, this file needs an empty front matter.
---
---
#import "_assets/fonts.scss";
#import "_assets/mixins.scss";
#import "_assets/reset.scss";
#import "_assets/colors.scss";
#import "_assets/syntax-highlighter.scss";
#import "_modules/header.scss";
#import "_modules/content.scss";
_includes/head.hmtl
Critical needs a link to original style sheet.
Remove the css loading script and replace it with
<link rel="stylesheet" href="{{ "/css/style.css" | prepend: site.baseurl }}">
The loading script will be inserted by critical.
gulpfile.js
You can now chain yours tasks. Note that I've changed the critical method to generateInline.
gulp.task("jekyll", function (gulpCallBack){
...
gulp.task("html", ["jekyll"], function() {
...
gulp.task("critical", ["html"], function() {
critical.generateInline({
base: '_site/',
src: 'index.html',
dest: 'css/critical.css',
htmlTarget: 'index.html',
minify: true,
extract: true,
width: 320,
height: 480
});
})
Bim !

It seems that there is not really a way to run gulp tasks synchronous. But your shell is able to run commands synchronous with the && operator.
I now use a gulp module called gulp-shell. Here is how my code looks:
gulp.task('build', shell.task([
'gulp jekyll && gulp critical && gulp html'
]));
So I am able to just run gulp build to run the gulp tasks jekyll, critical and html in order. Though this works, I am not really happy with this solution. If anybody knows a better solution, please let me know.

I typically use the _includes folder within Jekyll to do the inlining for me. All you have to do is gulp.dest('_includes') — you can call gulp.dest() multiple times in a row.
Sample task in gulpfile
Then add a line to your main page template in Jekyll:
<style type="text/css">{% include main.min.css %}</style>
See the Jekyll source code in context

Related

Struggling to get gulp v4 to watch tasks with babel plugin

When I try to gulp watch, I get the following error:
[15:46:56] Task never defined: watch
[15:46:56] To list available tasks, try running: gulp --tasks
Here are my functions from gulpfile.js.
function watchChanges(cb) {
watch(['assets/js/*.js'], parallel(buildSiteJS));
watch(['assets/scss/style.scss', 'assets/scss/**/*.scss'], parallel(compileStyleSCSS));
watch(['**/*.php'], parallel(reloadPage));
cb();
}
With the ending export statement like:
exports.default = parallel(serveBrowserSync, mainTasks, watchChanges);
I'm not sure if the syntax is incorrect causing the 'task never defined' error and I've tried a lot of searching online and not got anywhere with it.
Let me know if you need to see more of the gulpfile.js.
Gulp: 4.0.2
Gulp Babel: 8.0.0

gulp compass throws error

I am trying to use gulp-compass plugin to convert and minify my scss into css.
However I am getting below error:
$ gulp compass [02:14:32] Using gulpfile C:\Users\dell\Desktop\sassy -
copy\gulpfile.js [02:14:32] Starting 'compass'... [02:14:32] Finished
'compass' after 13 ms [02:14:33] LoadError on line ["55"] of C: cannot
load such file -- bourbon Run with --trace to see the full backtrace
events.js:160
throw er; // Unhandled 'error' event
^ Error: Compass failed
This is how my scss file looks like:
.scss file:
#import 'bower_components/bourbon/app/assets/stylesheets/bourbon';
#import 'bower_components/normalize-css/normalize';
#import 'bower_components/susy/sass/susy';
#import url('https://fonts.googleapis.com/css?family=Playfair+Display|Raleway');
#import 'partials/variables';
#import 'partials/base';
#import 'partials/footer';
#import 'partials/header';
#import 'partials/layout';
#import 'partials/modules';
Following is gulpfile.js:
var gulp = require('gulp'),
compass = require('gulp-compass'),
minifyCSS = require('gulp-minify-css');
gulp.task('compass', function() {
gulp.src('assets/scss/styles.scss')
.pipe(compass({
sass: 'assets/sass',
image: 'images',
require:['bourbon', 'normalize','susy']
}))
.pipe(minifyCSS())
.pipe(gulp.dest('css'));
});
I guess its not letting plugins like bourbon, normalize,susy to compile and convert. I might have done some wrong configuration I guess.
Tried installing gems but throws the following error:
gem install susy
gem install bourbon
c:\Users\Dell\Desktop\sassy - Copy>gulp compass
[23:23:59] Using gulpfile c:\Users\Dell\Desktop\sassy - Copy\gulpfile.js
[23:23:59] Starting 'compass'...
[23:23:59] Finished 'compass' after 14 ms
error assets/sass/styles.scss (Line 1: File to import not found or unreadable: bower_components/bourbon/app/assets/stylesheets/bourbon.
Load paths:
Compass::SpriteImporter
c:/Users/Dell/Desktop/sassy - Copy/assets/sass
C:/Ruby24/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets
C:/Ruby24/lib/ruby/gems/2.4.0/gems/susy-2.2.12/sass
C:/Ruby24/lib/ruby/gems/2.4.0/gems/bourbon-4.3.4/app/assets/stylesheets)
Compilation failed in 1 files.
events.js:160
throw er; // Unhandled 'error' event
^
Error: error assets/sass/styles.scss (Line 1: File to import not found or unreadable: bower_components/bourbon/app/assets/stylesheets/bourbon.
Load paths:
Compass::SpriteImporter
c:/Users/Dell/Desktop/sassy - Copy/assets/sass
C:/Ruby24/lib/ruby/gems/2.4.0/gems/compass-core-1.0.3/stylesheets
C:/Ruby24/lib/ruby/gems/2.4.0/gems/susy-2.2.12/sass
C:/Ruby24/lib/ruby/gems/2.4.0/gems/bourbon-4.3.4/app/assets/stylesheets)
Compilation failed in 1 files.
The reason is quite simple, the required are Ruby gems, not bower or node libraries.
From the doc,
Require the given Ruby library before running commands. This is used to access Compass plugins without having a project configuration file.
If you do not install the Ruby gems, you can require them.
gem install susy
gem install bourbon
It seems normalize-css does not have a Ruby gem.
The new error:
This question may help you Why is Compass is giving me an import error when trying to import partials, you need to use relative path, otherwise It will search the required Ruby gem path.(I think you have bower packages installed).
So changes #import 'bower_components/bourbon/app/assets/stylesheets/bourbon'; to
#import './bower_component/.. and all things alike.

EACCES: permission denied on gulp css minify, same src and dest

I have a gulp task to build up everything which runs for dev (works fine). On release gulp task we do the same but also tack on a bundle task which also minifies the css.
I want to just minify the css inline, meaning the same src and dest for the file; however, I am getting the below error when running.
Error: EACCES: permission denied, open
I don't think I'm hitting any race conditions since my build task shows as finished before the minify starts
[15:11:48] Finished 'build_client_lib' after 3.31 s
[15:11:48] Starting 'build'...
[15:11:48] Finished 'build' after 1.67 μs
[15:11:48] Starting 'minify-css'...
[15:11:48] 'minify-css' errored after 344 ms
The tasks in question are:
gulp.task('release', callback => {
gulpSequence('clean_packages', 'build', 'client_lib_bundle')(callback)
});
gulp.task('client_lib_bundle', ['minify-css'], () => {
});
gulp.task('minify-css', () => {
return gulp.src('build/client_lib/**/*.css')
.pipe(cleanCSS())
.pipe(gulp.dest('build/client_lib'));
});
It works fine is I specify an alternate dest path, but I'd prefer not to do that. How can I resolve this access issue?
Turns out the package I was using gulpSequence caused this, and a slew of other items, to run in an awkwardly async manner. Changing to the npm package run-sequence cleared all this up and ensures everything is running in the correct order.

Gulp tasks does not work sequentially

I have 4 tasks to clean the build, build styles & javascripts and to create asset manifest. My default task looks like this:
gulp.task('default', function(callback) {
runSequence('clean', ['styles', 'scripts'], 'version', callback);
});
So, this works out perfectly but the 'version' tasks. It does not create anything and has no effect.
gulp.task('version', function() {
gulp.src(utils.dst('**/*'))
// create content hashed filenames
.pipe(rev())
.pipe(gulp.dest(utils.dst()))
// create asset manifest
.pipe(rev.manifest())
.pipe(gulp.dest(utils.dst()))
});
If I run do the gulp clean; gulp styles; gulp scripts; gulp version; the version tasks will create the desired asset manifest.
This is the output of running the default task:
Starting 'default'...
Starting 'clean'...
Finished 'clean' after 6.87 ms
Starting 'styles'...
Finished 'styles' after 7.63 ms
Starting 'scripts'...
Finished 'scripts' after 2.96 ms
Starting 'version'...
Finished 'version' after 2.25 ms
Finished 'default' after 22 ms
Do anyone see the mistake I do? Maybe the build assets are not there yet when I run the version task, but that's why I made the tasks run sequentially.
Any suggestions how I could solve the problem?
You have to return the stream like so :
gulp.task('version', function() {
return gulp.src(utils.dst('**/*'))
// create content hashed filenames
.pipe(rev())
.pipe(gulp.dest(utils.dst()))
// create asset manifest
.pipe(rev.manifest())
.pipe(gulp.dest(utils.dst()))
});
Otherwise gulp can't know if your task is finished or not !

Compile Jade with grunt: failed

i'm trying to compile my jade files for an SPA with grunt, and it works ... well, "works..."
my folders:
app
views
build
any compiled .html
any .jade file
index.jade
index.html
and my gruntfile.coffee task:
jade:
compile:
options:
pretty: true
files:
[
extend: true
flatten: true
cwd: 'app/views'
src: '**/*.jade'
dest: 'app/views/build'
ext: '.html'
]
compileIndex:
options:
pretty: true
files: 'app/index.html': ['app/index.jade']
Well, i read another questions here like Grunt compiling Jade files but i can get it work fine, when i try to run grunt jade, two things happens; compileIdex works totally fine,but, when compile task run:
Running tasks: jade:compile
Running "jade:compile" (jade) task
Verifying property jade.compile exists in config...OK
Files: prueba.jade -> app/views/build
Options: namespace="JST", separator="\n\n", amd=false, pretty
>> Source file "prueba.jade" not found.
>> Destination not written because compiled files were empty.
So what i'm doing wrong here? I need to keep separate compilations, index and views.