I use gulp as a build system in my web project
I have a number of CSS files (well, actually, LESS, but it does not matter)
I do link image files from my CSS rules in this way:
.my-rule {
background-image: url('/images/kitten.svg');
}
Next, I'm embedding those images as Base-64 into my production CSS files.
That is a gulp task:
var gulp = require("gulp"),
...
base64 = require('gulp-base64');
gulp.task("sass", function () {
return gulp.src(paths.styles)
.pipe(base64())
.pipe(concat("concatedstyles.css"))
.pipe(gulp.dest(paths.webroot + "css"));
});
The problem is:
When I link to non-existing file:
.my-rule {
background-image: url('/images/non-existing-kitten.svg');
}
the build system does not report me about failure.
It just leave this line as is.
So, I'm not aware about error at build time, only at runtime.
I tried to play with .pipe(sass.sync().on("error", sass.logError)), but no luck.
Any advice?
Related
This is basically the code I am using and lighthouse says my (almost empty!) css bundle is delaying my initial load.
So how do I put a link to critical.scss in the
<head><style>DONT_WANT_TO_WRITE_STUFF_INLINED</style>...</head>
Is there a better solution than https://www.npmjs.com/package/critical or writing everything inlined?
And how do I delay the load of the main styles.scss until the prerendered Universal content is loaded in the browser? The server-app's config in angular-cli.json does not contain styles or assets, so I don't understand why styles.scss is loaded initially
Regarding delaying the load of the main styles.scss, I rely on two things:
First of all, I build the application with the --extract-css=false flag. That ensures that the styles bundle will be a JavaScript file.
Second, I defer the loading of that file. To do so I rely on a small script that I called defer.styles.js and that runs at the end of the build process. That script simply looks for the script tag that loads the styles, and adds a defer to it.
const path = require('path');
const htmlPath = path.join(__dirname, 'dist', 'browser', 'index.html');
fs.readFile(htmlPath, 'utf8', (err, data) => {
if (err) {
console.log(err);
return;
}
const index = data.search(`src="styles.`);
if (index > -1) {
const output = [data.slice(0, index), 'defer ', data.slice(index)].join('');
console.log(output);
fs.writeFile(htmlPath, output, 'utf8', () => {
console.log('Styles succesfully deferred');
})
}
});
Regarding your other question - how to load the critical css -. I still didn't find a way of comfortably doing it.
I'm new to NodeJS and I'm using Express to serve my pug files/view. Furthermore I'm using "express-sass-middleware" to compile and serve the scss/css files. Everything works very well but unfortunately, the CSS are not applied.
My app.js files looks like:
var express = require('express');
var sassMiddleware = require('express-sass-middleware');
var app = express();
app.set('view engine', 'pug');
app.get('/css/bootstrap.css', sassMiddleware({
file: 'css/bootstrap.scss', // the location of the entry point,
// this can also be a directory
precompile: true, // should it be compiled on server start
// or deferred to the first request
// - defaults to false
}));
app.get('/', function (req, res) {
res.render('index', {
varTitle: 'Hello World'
});
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
And my simple css file looks like:
// $icon-font-path: /3rdparty/fonts;
// #import 'bootstrap/bootstrap';
// #import './node_modules/bootstrap-sass/assets/stylesheets/bootstrap/variables';
body
{
background-color: green;
font-size: 100px;
}
My index.pug file is:
doctype html
html(lang='en')
head
title= varTitle
link(ref='stylesheet' type='text/css' href='/css/bootstrap.css')
body
h1= varTitle
Now, when I start my webserver using "node app.js", accessing http://localhost:3000, I see "Hello World" but unfortunately the body background isn't green and the text is also not 100px. That means that the css file is not applied. But when I access http://localhost:3000/css/bootstrap.css, I see the valid, css file.
Anyone know what I'm missing here? I'm a bit confused that I see the CSS source when accessing it directly but the browser doesn't apply the css styling. I already tried different browsers without any success. None of them applying the css file.
You have typing error in index.pug file for loading css file. You had mentioned ref whereas it should be rel.
link(rel='stylesheet' type='text/css' href='/css/bootstrap.css')
Happy to help you.
you don't seem to be serving the static files from your nodejs server code. You have to add your css dir in order to allow access from your html code:
app.use('/static', express.static('public'))
Now, you can load the files that are in the public directory from the /static path prefix.
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html
I am attempting to make the switch from GruntJS to Gulp and have run into a problem with my Gulp task for processing my SASS files via Compass. The files compile just fine into the single CSS file as they did under my GruntJS implementation, but I am missing the line number comments that show me where the CSS rules come from such as:
/* line 26, ../_components/sass/_base.scss */
The code from my gulpfile.js for the task is:
gulp.task('compass', function() {
gulp.src(sassSources)
.pipe(compass({
comments: true,
sass: '_components/sass',
image: 'builds/dev/images',
style: 'nested'
})
.on('error', gutil.log))
.pipe(gulp.dest('builds/dev/css'))
});
Am I missing something?
Be careful with gulp-compass, it is not a gulp plugin (albeit named so) and has been blacklisted by the Gulp community for quite a while. It does not what Gulp plugins are supposed to do (e.g. it's possible to run them without gulp.src and gulp.dest), and other plugins are already doing its work perfectly fine. One of those plugins is gulp-ruby-sass. This setup might work for you:
var sass = require('gulp-ruby-sass');
gulp.task('compass', function() {
return sass(sassSources, {
compass: true,
lineNumbers: true
}).on('error', gutil.log))
.pipe(gulp.dest('builds/dev/css'))
});
This uses gulp-ruby-sass which is able to run with the compass extension. You see that I activated lineNumbers here to give you said output.
I see from your Gulpfile that you might have some extension requiring some images, I don't know exactly what that does, but if it's mandatory to your setup, you might better call compass directly (the command line tool) using require('child_process').exec(...)
You should add sass_options = { :line_numbers => true } to your config.rb file even if gulp-compass module doesn't support lineNumbers as an option.
important part of config.rb file
css_dir = 'app/assets/style/'
sass_dir = 'app/assets/style/sass/'
images_dir = 'app/assets/image/'
javascripts_dir = 'app/assets/script/'
sass_options = { :line_numbers => true }
And your gulp task should look like this
important part of gulpfile.js file
return gulp.src('./app/assets/style/sass/*.scss')
.pipe(plugins.compass({
config_file: './config.rb', // if you don't use a config file , you should start using immediately
css: './app/assets/style/',
sass: './app/assets/style/sass/',
image: './app/assets/image/',
line_comments: true,
sourcemap: true
}))
.pipe(gulp.dest('./app/assets/style/'));
I had trouble generating the line number comments using gulp-compass also. I tried a lot of things including matching all the plugin versions to the sample code I used to even completely discarding my code and use the full sample instead to no avail.
On top of its lack of compliance with gulp standards as #ddprrt suggested, gulp-compass seems to be broken now. Besides generating a stylesheet on the destination folder, it also generates another under the {app_root}/css folder. I suspect, the latter is some sort of caching, but that functionality is currently broken. As can be seen here, if you delete that stylesheet and re-run the task, the line number comments will finally show up. Below, I automated this by installing and using the gulp-clean-dest plugin. I have no tried using other plugins, but this hack handles the issue.
var gulp = require("gulp")
, compass = require("gulp-compass")
, cleanDest = require("gulp-clean-dest")
;
gulp.task("compass", function() {
gulp.src("components/sass/style.scss")
.pipe(compass(
{ "sass": "components/sass"
, "image": "builds/development/images"
, "style": "expanded"
, "comments": true
})
.on("error", gutil.log)
)
.pipe(gulp.dest("builds/development/css"))
.pipe(cleanDest("css"))
});
Currently I have a stylus file that imports another stylus file. This second file uses the URL function like this, and I want it to be inlined (e.g. to a base 64 data-url). However this isn't working when run through my gulp pipeline
lines.styl:
vertical-img = 'vertical.svg';
#import "../tree";
tree.styl
background-image: url(vertical-img)
What I want to get as a result is:
background-image: url('data:image/svg+xml;utf8,<svg>[...]</svg>');
But I get this:
background-image: url("vertical.svg")
And my gulpfile is as follows:
return gulp.src('src/css/*/*.styl')
.pipe(gstylus({
set: ['resolve url']
}))
.pipe(rename(function (file) {
file.dirname = "";
file.extname = ".css";
}))
.pipe(gulp.dest(DEST))
Basically it seems like the 'resolve url' option isn't being passed to stylus. I'm aware that I need it, since it says in the Stylus Docs that:
By default Stylus doesn’t resolve the urls in imported .styl files, so if you’d happen to have a foo.styl with #import "bar/bar.styl" which would have url("baz.png"), it would be url("baz.png") too in a resulting CSS.
But you can alter this behavior by using --resolve-url (or just -r) CLI option to get url("bar/baz.png") in your resulting CSS.
The correct option for image inlining is url (not resolve url) see http://learnboost.github.io/stylus/docs/functions.url.html. To use it in gulp-stylus you should pass url option to options object (see https://github.com/jenius/accord/blob/master/docs/stylus.md#url). For example:
return gulp.src('src/css/*/*.styl')
.pipe(gstylus({
url: { name: 'url', limit: false }
}))
.pipe(rename(function (file) {
file.dirname = "";
file.extname = ".css";
}))
.pipe(gulp.dest(DEST))
I want to write an empty file even the destination file is empty.
Is it possible?
The error I get is "destination not written because minified css was empty".
I'm using grunt-contrib-cssmin module.
Only using grunt-contrib-cssmin, you cannot.
A good place to start when wondering about something specific to a piece of open source software: the source code itself — the task is only ~70 lines. From the source we can see the "error" you're getting:
if (min.length === 0) {
return grunt.log.warn('Destination not written because minified CSS was empty.');
}
You might want to look into "touching" the file. If you are familiar with *nix, you'll know that touch will create the file if it doesn't exist and not truncate it if it does. In Grunt (node.js) you might want to look into node-touch or grunt-exec.
As for your Gruntfile, you'd need only one of the following two tasks:
module.exports = function (grunt) {
var touch = require('touch');
grunt.initConfig({
'cssmin': {
'combine': {
'files': { 'path/to/output.css': ['path/to/input_one.css', 'path/to/input_two.css'] }
}
},
'exec': {
'touch': { 'command': 'touch path/to/output.css' }
}
});
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-exec');
grunt.registerTask('touch', touch.sync.bind(undefined, 'path/to/output.css'));
grunt.registerTask('minifycss1', ['cssmin', 'exec:touch']); // 1
grunt.registerTask('minifycss2', ['cssmin', 'touch']); // 2
};
Uses grunt-exec.
Uses node-touch.