minify css/js into their individual files - javascript

I have this default gulp file from a Visual Studio template:
/// <binding BeforeBuild='clean, minPreBuild' />
"use strict";
var gulp = require("gulp"),
rimraf = require("rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify");
var webroot = "./wwwroot/";
var paths = {
js: webroot + "js/**/*.js",
minJs: webroot + "js/**/*.min.js",
css: webroot + "css/**/*.css",
minCss: webroot + "css/**/*.min.css",
concatJsDest: webroot + "js/_site.min.js",
concatCssDest: webroot + "css/_site.min.css"
};
gulp.task("clean:js", function (cb) {
rimraf(paths.concatJsDest, cb);
});
gulp.task("clean:css", function (cb) {
rimraf(paths.concatCssDest, cb);
});
gulp.task("clean", ["clean:js", "clean:css"]);
gulp.task("min:js", function () {
return gulp.src([paths.js, "!" + paths.minJs], { base: "." })
.pipe(concat(paths.concatJsDest))
.pipe(uglify())
.pipe(gulp.dest("."));
});
gulp.task("min:css", function () {
return gulp.src([paths.css, "!" + paths.minCss])
.pipe(concat(paths.concatCssDest))
.pipe(cssmin())
.pipe(gulp.dest("."));
});
gulp.task("min", ["min:js", "min:css"]);
gulp.task("minPreBuild", ["min:js", "min:css"]);
The problem I'm having is one of my js files in the directory has a dependency on knockout, but I'm only using knockout on one of the pages on the site. I don't want to include knockout on my shared view, and the default bundling all files into a single file causes a JS error "ko is undefined" as one of the JS files is dependent on KO.
Is there a way that I can minify files individually, without concatting it into the main "site.min.css"?

First you need to exclude the Knockout file from your min:js task. Prepending a path with ! tells gulp to ignore that file:
gulp.task("min:js", function () {
return gulp.src([
paths.js,
"!" + paths.minJs,
"!js/path/to/knockout.js" // don't include knockout in _site.min.js
], { base: "." })
.pipe(concat(paths.concatJsDest))
.pipe(uglify())
.pipe(gulp.dest("."));
});
Then you need to create a new task min:knockout that does nothing but minify your Knockout file. You'll probably want the minified file to end with a .min.js extension so you'll have to install the gulp-rename plugin as well.
var rename = require('gulp-rename');
gulp.task("min:knockout", function () {
return gulp.src("js/path/to/knockout.js", { base: "." })
.pipe(rename("js/_knockout.min.js"))
.pipe(uglify())
.pipe(gulp.dest("."));
});
Finally you need to make sure your new min:knockout task is executed when running the min and minPreBuild tasks:
gulp.task("min", ["min:js", "min:knockout", "min:css"]);
gulp.task("minPreBuild", ["min:js", "min:knockout", "min:css"]);

Related

Modify gulpfile to read html files in subfolder and spit them out to build folder

I have been working on modifying this relatively simple gulpfile/project: https://github.com/ispykenny/sass-to-inline-css
The first issue I had was to update to gulp v4, but I've also tried to store variables for my src and destination folders which is a bit easier to control. So now my gulpfile looks like this:
const gulp = require('gulp');
const inlineCss = require('gulp-inline-css');
const sass = require('gulp-sass');
const browserSync = require('browser-sync').create();
const plumber = require('gulp-plumber');
const del = require('del');
const srcFolder = './src'; // TODO tidy this up once working
const buildFolder = srcFolder + '/build/'; // Tidy this up once working
const src = {
scss: 'src/scss/**/*.scss',
templates: 'src/templates/**/*.html'
}
const dest = {
build: 'build/',
css: 'build/css'
};
function processClean() {
return del(`${buildFolder}**`, { force: true });
}
function processSass() {
return gulp
.src(src.scss)
.pipe(plumber())
.pipe(sass())
.pipe(gulp.dest(dest.css))
.pipe(browserSync.stream())
}
function processInline() {
return gulp
.src('./*.html')
.pipe(inlineCss({
removeHtmlSelectors: true
}))
.pipe(gulp.dest('build/'))
}
function processWatch() {
gulp.watch(['./src/scss/**/*.scss'], processSass);
gulp.watch(srcFolder).on('change', browserSync.reload);
gulp.watch(distFolder).on('change', browserSync.reload);
}
const buildStyles = gulp.series(processSass, processInline);
const build = gulp.parallel(processClean, buildStyles);
gulp.task('clean', processClean);
gulp.task('styles', buildStyles);
gulp.task('sass', processSass);
gulp.task('inline', processInline);
gulp.task('build', build);
gulp.task('watch', processWatch);
But I am now wanting to create lots of template files, store them in a subfolder and have gulp spit out each file into the destination folder. if I have index.html, test1.html etc in the root it works fine.
I tried modifying this:
function processInline() { return gulp.src('./*.html')
To this:
function processInline() { return gulp.src(src.templates) // should equate to 'src/templates/**/*html'
Now I'm seeing this error in the console:
ENOENT: no such file or directory, open 'C:\Users\myuser\pathToApp\emailTemplates\src\templates\build\css\style.css'
In the head of index.html in the root is this:
<link rel="stylesheet" href="build/css/style.css">
I actually don't really care about the css file as the final output should be inline (for email templates). But I cannot get my head around why this is happening.
Does gulp create the css file and then read the class names from there? EDIT, Ah I guess it must because it has to convert the sass to readable css first before stripping out the class names and injecting the inline styles.
Years ago I worked with grunt a fair bit, and webpack, but haven't done much with gulp.
I hope it is obvious, but if you need more information just let me know.

How I can exclude path in gulp src?

How I can exclude part of gulp src path?
There are many paths:
folder/
folder.ru/
folder.com/
And I need to exclude only folders with .ru & .com at end
in my gulpfile
var gulp = require('gulp'),
uglify = require('gulp-uglify');
gulp.task('run', function () {
return gulp.src([
'!landing/*.ru/',
'!landing/*.com/',
'!folder/*.ru',
'!folder/*.com',
'!folder/*[^ru]',
'!folder/*[^com]',
'!folder/*[^ru]/',
'!folder/*[^com]/',
'folder/**/js/hello.js',
])
.pipe(uglify())
.pipe(gulp.dest(function (file) {
return file.base;
}))
and it does't work at all, minify all hello.js in all folders
Add this:
'!**/*.ru/**/*',
'!**/*.com/**/*',

Import / read variable from separate gulp file

I'm looking to split my gulpfile.js assets or src variables into separate files so that I can manage them better. For example:
....
var scripts = ['awful.js', 'lot.js', 'of.js', 'js.js', 'files.js']
....(somewhere down the line)
gulp.task('vendorjs', function() {
return gulp.src(scripts)
.pipe(concat('vendor.js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest(paths.root + 'dist'))
.pipe(notify({ message: 'vendorjs task completed' }));
});
So what I'm basically interested if theres a way to actually move to a separate file the scripts variable and be able to access it from gulpfile.js.
I've been looking into something like:
require("fs").readFile('gulp/test.js', function(e, data) {
//(test.js would be the file that holds the scripts var)
});
Howerver while it does read the contents of the file, I still can't access it from the gulpfile.js. Any tips or ideas are much appreciated.
Node.js allows you to import other files using require(). It supports three types of files:
JSON files. See DavidDomain's answer for that.
Binary Node.js addons. Not useful for your use case.
JavaScript files. That's what you want.
For JavaScript files the value returned from require() is the one that is assigned to module.exports in the imported file.
So for your use case:
gulp/test.js
var arrayOfFiles = ["awful.js", "lots.js"];
arrayOfFiles.push("of.js");
arrayOfFiles.push("js.js");
arrayOfFiles.push("files.js");
for (var i = 0; i < 10; i++) {
arrayOfFiles.push("some_other_file" + i + ".js");
}
module.exports = {
scripts: arrayOfFiles
};
gulpfile.js
var test = require('gulp/test.js');
gulp.task('vendorjs', function() {
return gulp.src(test.scripts)
.pipe(concat('vendor.js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest(paths.root + 'dist'))
.pipe(notify({ message: 'vendorjs task completed' }));
});
You could use a json file to store your assets or source file location in and load that into your gulp file.
For example:
// config.json
{
"scripts": ["awful.js", "lot.js", "of.js", "js.js", "files.js"]
}
And in your gulp file you would do
// gulpfile.js
var config = require('./config');
var scripts = config.scripts;
console.log(scripts);

Concatenate js files in correct order using Gulp

I am trying to concatenate a bunch of js files with gulp, but in a specific order. I want a file called ‘custom.js’ to be last (could be any other filename, though.
This is my gulp task:
gulp.task('scripts', function() {
return gulp.src(['src/scripts/**/!(custom)*.js','src/scripts/custom.js'])
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('default'))
//.pipe(gulp.src('src/scripts/**/*.js')) not needed(?)
.pipe(order([
'!(custom)*.js', // all files that end in .js EXCEPT custom*.js
'custom.js'
]))
.pipe(concat('main.js'))
.pipe(gulp.dest('static/js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest('static/js'))
.pipe(notify({ message: 'Scripts task complete' }));
});
However, this just concatenates files in alphabetical order. What can I do to solve this, except renaming the custom.js file to something like zzz-custom.js?
You need something along the lines of ....
gulp.task('scripts', function() {
return gulp.src(['src/scripts/**/*.js','!src/scripts/custom.js', 'src/scripts/custom.js'])
.pipe(concat('main.js'))
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('static/js'));
});
gulp.src
Globs all js files in src/scripts
Excludes src/scripts/custom.js
Loads src/scripts/custom.js
Concat the stream into main.js
Uglify the stream
Add '.min' suffix
Save to static/js
Key part is to first exclude custom.js from the glob and then adding it.
** EDIT **
Well, I suppose you could break down the steps. Not the most elegant but should do the job:
var sequence = require(‘run-sequnce’);
var rimraf = require(‘rimraf’);
// This gets called and runs each subtask in turn
gulp.task('scripts', function(done) {
sequence('scripts:temp', 'scripts:main', 'scripts:ugly', 'scripts:clean', done);
});
// Concat all other js files but without custom.js into temp file - 'main_temp.js'
gulp.task('scripts:temp', function() {
return gulp.src(['src/scripts/**/*.js','!src/scripts/custom.js'])
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('default'))
.pipe(concat('main_temp.js'))
.pipe(gulp.dest('static/js/temp'));
});
// Concat temp file with custom.js - 'main.js'
gulp.task('scripts:main', function() {
return gulp.src(['static/js/temp/main_temp.js','src/scripts/custom.js'])
.pipe(concat('main.js'))
.pipe(gulp.dest('static/js'));
});
// Uglify and rename - 'main.min.js'
gulp.task('scripts:ugly', function() {
return gulp.src('static/js/main.js')
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('static/js'));
});
// Delete temp file and folder
gulp.task('scripts:clean', function(done) {
rimraf('static/js/temp', done);
});
You could perhaps combine them back bit by bit if it works in this way and you want a "cleaner" file

Get Gulp watch to perform function only on changed file

I am new to Gulp and have the following Gulpfile
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
gulp.task('compress', function () {
return gulp.src('js/*.js') // read all of the files that are in js with a .js extension
.pipe(uglify()) // run uglify (for minification)
.pipe(gulp.dest('dist/js')); // write to the dist/js file
});
// default gulp task
gulp.task('default', function () {
// watch for JS changes
gulp.watch('js/*.js', function () {
gulp.run('compress');
});
});
I would like to configure this to rename, minify and save only my changed file to the dist folder. What is the best way to do this?
This is how:
// Watch for file updates
gulp.task('watch', function () {
livereload.listen();
// Javascript change + prints log in console
gulp.watch('js/*.js').on('change', function(file) {
livereload.changed(file.path);
gutil.log(gutil.colors.yellow('JS changed' + ' (' + file.path + ')'));
});
// SASS/CSS change + prints log in console
// On SASS change, call and run task 'sass'
gulp.watch('sass/*.scss', ['sass']).on('change', function(file) {
livereload.changed(file.path);
gutil.log(gutil.colors.yellow('CSS changed' + ' (' + file.path + ')'));
});
});
Also great to use gulp-livereload with it, you need to install the Chrome plugin for it to work btw.
See incremental builds on the Gulp docs.
You can filter out unchanged files between runs of a task using the gulp.src function's since option and gulp.lastRun

Categories