Gulp: minify handlebars files before compiling - minify

I see that at least gulp plugin gulp-ember-handlebars does not minifyes html. So I thought it would be nice to minify files before compiling. Something like this:
gulp.src(paths.tmplInput)
.pipe(minifyHTML({collapseWhitespace:true,removeComments:true}))
.pipe(handlebars({outputType: 'browser'}))
.pipe(concatStr('templates.js'))
.pipe(uglify())
.pipe(gulp.dest('./src'));
But then I noticed that {{action}} was removed too. That is not exactly what I want. Any solutions? Thanks.

According to this answer, https://stackoverflow.com/a/48361324/209288 (if you are using html-minifier with the gulp wrapper)
you could set this option like:
.pipe(minifyHTML({
collapseWhitespace:true,
removeComments:true,
ignoreCustomFragments: ["/{{[{]?(.*?)[}]?}}/"
]}
))

Related

Why is 'inline' called after 'scss' in this gulpfile?

I'm trying understand some of the details of this gulpfile from foundation-emails-template.
Here is an excerpt from the file for the part I am curious about:
// Build the "dist" folder by running all of the below tasks
gulp.task('build',
gulp.series(clean, pages, sass, images, inline));
As you can see, the build task calls a bunch of methods in order. One of them is the sass method, and one following that is the inline method:
// Compile Sass into CSS
function sass() {
return gulp.src('src/assets/scss/app.scss')
.pipe($.if(!PRODUCTION, $.sourcemaps.init()))
.pipe($.sass({
includePaths: ['node_modules/foundation-emails/scss']
}).on('error', $.sass.logError))
.pipe($.if(PRODUCTION, $.uncss( // <- uncss happening here
{
html: ['dist/**/*.html']
})))
.pipe($.if(!PRODUCTION, $.sourcemaps.write()))
.pipe(gulp.dest('dist/css'));
}
// Inline CSS and minify HTML
function inline() { // <- Inlining happening here
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, inliner('dist/css/app.css')))
.pipe(gulp.dest('dist'));
}
So, the sass method gets called first, which compiles the sass files into a single app.css. Part of this method also says to use uncss to remove unused css from the html files. The inline method is responsible for inlining the css into those html files.
I am confused why this works correctly. How is it that inline can be called after scss? The inline method places css in the html files that the scss method "uncss-es", yet it's called afterwards.
This seems to work correctly, so clearly I am just not understanding some sort of basic concept with gulp. Can anyone explain how this works?
Uncss removes unused css rules from your app.css file. It scans your html files and removes any rules for which it can find no selector, via querySelector() in the html file. So app.css has been cleansed before it is then inlined into your html files. This is order you would want. The css is cleaned, not the html.

Gulp-cssmin Preventing Inline Sourcemaps from Working

I have a Gulpfile that uses gulp-cssmin to minify my CSS, and I am also trying to get inline sourcemaps using gulp-sourcemaps (see code below). Without piping anything through Cssmin, my inline sourcemaps totally work. But when I try to pipe everything through Cssmin at the end of my 'sass' task, my inline sourcemaps stop working.
// Compile SASS to CSS, add vendor prefixes, write sourcemaps, then minify
gulp.task('sass', function(){
return gulp.src([paths.sass, '!./_styles/_sass/_partials/**/*.scss'])
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer(autoprefixerOptions))
.pipe(sourcemaps.write())
.pipe(cssmin())
.pipe(gulp.dest('./_styles'));
});
Anyone have any ideas as to what I'm missing here? Or if I've just got things in the wrong order? Do inline sourcemaps still work with minified CSS? Or is it something specifically with gulp-cssmin?
I couldn't find a previous answer on Stack Overflow that dealt specifically with sourcemaps in relation to gulp-cssmin, so please enlighten!
Thanks.
I'm assuming you are using https://www.npmjs.com/package/gulp-cssmin.
gulp-cssmin uses https://www.npmjs.com/package/clean-css for cleaning the css, and thus the options of clean-css apply. However, since the css delivered to cssmin already contains a source map, it needs to be forwarded to clean-css, but this apparently isn't currently happening:
should pass input source map to minify() as second arg as seen in the second example: https://github.com/jakubpawlowicz/clean-css/blob/master/README.md#how-to-work-with-source-maps
but minify() call here doesn't: https://github.com/chilijung/gulp-cssmin/blob/master/index.js#L42
Therefore it doesn't currently seem to be possible to configure gulp-cssmin to update source maps.
I have added issue https://github.com/chilijung/gulp-cssmin/issues/22 requesting to add the missing functionality.
UPDATE
I found https://www.npmjs.com/package/gulp-clean-css which also uses clean-css behind the scenes AND supports source maps!
You need to update your code to:
var cleanCSS = require('gulp-clean-css');
gulp.task('sass', function(){
return gulp.src([paths.sass, '!./_styles/_sass/_partials/**/*.scss'])
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer(autoprefixerOptions))
.pipe(cleanCSS())
.pipe(sourcemaps.write())
.pipe(gulp.dest('./_styles'));
});
i.e. move the cleanCSS() before sourcemaps.write().
In general, here is a good list of gulp plugins that support source maps: https://github.com/floridoo/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support

Gulp SASS Sourcemap sources are incorrect

I am struggling to get my SASS sourcemaps to work correctly. The problem seems to be the "sources" attribute within the sourcemap and how my SASS files are nested.
I have a Gulp task that compiles SASS to CSS. Here is an example of that
var paths = {
styles: {
src: './Stylesheets/SCSS/',
files: './Stylesheets/SCSS/**/*.scss',
dest: './Stylesheets/CSS/'
}
}
gulp.task('compile-sass', function (){
return gulp.src(paths.styles.files)
.pipe(sourcemaps.init())
.pipe(sass({
outputStyle: 'compressed',
includePaths : [paths.styles.src]
}))
.pipe(prefix({
browsers: ['last 2 Chrome versions'],
cascade: false
}))
.pipe(sourcemaps.write('../Maps/', {
includeContent: false,
sourceRoot: '../SCSS'
}))
.pipe(gulp.dest(paths.styles.dest));
});
The above works for everything else - writing maps to disk, prefixing etc. I am using latest nodejs, gulpjs and relevant npm packages.
An example of folder/asset structure from within my Stylesheets folder:
SCSS/print.scss
SCSS/sectionA/style.scss
SCSS/sectionA/partial/_partialA.scss
SCSS/sectionA/partial/_partialB.scss
SCSS/sectionB/... etc
For SASS files in the root of SCSS/ the sourcemaps work properly. Chrome will show where the source styles are.
For SASS files in a subfolder within SCSS/ the sourcemaps do not work. The problem is the "sources": attribute has the wrong file listed in it.
The print.scss map for example will correctly have "sources":["print.scss"]. But sectionA/style.scss map will have "sources":["style.css"] instead of "sources":["partial/_partialA.scss", "partial/_partialB.scss"] as I would expect.
I have confirmed moving /SCSS/sectionA/style.scss to /SCSS/style.scss and amending any import paths does solve the issue. But I need it to be nested, not in the root of /SCSS.
If I can provide more detail please let me know. I have tried the answer from Path to source map is wrong and it does not solve my issue. I have also tried manipulating mapSources with no avail.
# Update 2019-05-24
My answer talks about using CSSNext. CSSNext was deprecated. The theory in my answer is still applicable using postcss-preset-env.
# Update 2017-03-08
After experimenting with PostCSS, I have used CSSNext to process the CSS after SASS has converted it. CSSNext auto-prefixes and doing it this way retains the connection to the original scss files in the sourcemap.
See my GitHub repo for an example.
After following Mark's feedback and investigating the gulp-autoprefixer module I believe this issue raised on the GitHub repo for gulp-autoprefixer is related to the incorrect sourceroot problem.
Using a variation of the hack from ByScripts I am able to get sourcemaps with the correct sourceroot for nested scss files. The hack used in the ByScripts gulpfile inits the sourcemaps function twice. Once before prefixing, and once after.
I have created a GitHub repo to try and illustrate a reduced test case and a workaround. Inspecting the css produced by the workaround shows the correct relationship back to the source scss.

Why doesn't gulp find my bootstrap css files?

My gulp file has this in it:
gulp.task('bower2',function () {
return gulp.src(mainBowerFiles('**/*.css'), {debugging:true})
.pipe(gulp.dest(dist_path+'/styles'))
;
});
But it's not finding the CSS files, none of them. I've been successful with the js files though.
I'm not trying to do anything fancy, just build all of the css files into a single vendor.css file (in the case, font-awesome and bootstrap, that's it).
Thanks,
Nick
Try like this.
gulp.task('bower2',function () {
return gulp.src('**/*.css')
.pipe(gulp.dest(dist_path+'/styles'));
});
For some reason gulp has issue with mainBowerFiles() function when you are trying to use it for css task.

Gulp watch all files but render only one (sass)

I want to make gulp watch for all changes on my work folders but to generate only one file. Because I use scss which imports all required files, there is no need to compile all .css files, only main one.
Now, my gulpfile.js contains:
var gulp = require('gulp');
var util = require('gulp-util');
var sass = require('gulp-sass');
gulp.task('sass', function () {
return gulp.src('./sass/style.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./dist/css'));
});
gulp.task('watch', function() {
gulp.watch('./sass/**/*.scss', ['sass']);
});
And I have to go in ./sass/style.scss and save it to triger gulp watch.
I want gulp to watch all files (something like ./**/*.scss) but to render only one - ./sass/style.scss. How to achieve that?
Solution to this is simple, just edit watch part of the gulpfile.js to:
gulp.task('watch', function() {
gulp.watch('./**/*.scss', ['sass']);
});
Which says: watch for all .scss and on change run 'sass' taks.
'sass' taks compiles only ./sass/style.scss'
No need to change anything in gulpfile.js. There is another simpler method you need only add underscore to all SCSS files that are being imported with #import statement (like _*.scss), this will forbid compiler to create separate CSS files.
Example:
mymodular.scss => _mymodular.scss
Guidelines from SCSS documentation
Partials
You can create partial Sass files that contain little snippets of CSS that you can include in other Sass files. This is a
great way to modularize your CSS and help keep things easier to
maintain. A partial is a Sass file named with a leading underscore.
You might name it something like _partial.scss. The underscore lets
Sass know that the file is only a partial file and that it should not
be generated into a CSS file. Sass partials are used with the #use
rule.