Gulp bundle only if source files changed - gulp

I'm pretty new to gulp, so hopefully this is an easy one.
I'm trying to genereate a number of bundles, each of which will be composed of a bunch of js/css files (sourced from a file), but I only want to build each bundle if any of it's source files changed.
My starting code looks like the following. What do I need to add to make it work?
gulp.task('bundle', function () {
return gulp
.src(sourceFile)
.pipe(bundle())
.pipe(gulp.dest(buildDest))
.pipe(bundle.results({
pathPrefix: '/bundlePath/',
dest: manifestDest
}));
});
sourceFile:
module.exports = {
bundle: {
"bundle1": {
"scripts": [
"file1.js",
"file2.js",
"file3.js"
],
"styles": "style1.css"
},
"bundle2": {
"scripts": [
"file1.js",
"file4.js"
],
"styles": [
"style1.css",
"style2.css"
]
}
}
}
For example, if only file1.js changes, I want both bundle1 and bundle2 rebuilt since they share file1.js. If only file4.js changes, only bundle2 should be rebuilt.
This process is kicked off when the release version of the project is built in VS2012.
I looked into alternative packages like gulp-changed, but they seem to only work with single files (correct me if I'm wrong).

Related

kagnax/html-minifier grunt plugin how to use multiple targets

I am trying to use html-minifier grunt plugin (https://github.com/gruntjs/grunt-contrib-htmlmin) and the documentation says we can use multiple targets; That is, we can specify different options for different build environment. In the below example 2 targets are configured 'dist' and 'dev'
grunt.initConfig({
htmlmin: {
dist: {
options: {
removeComments: true,
collapseWhitespace: true
},
files: {
'dist/index.html': 'src/index.html'
}
},
dev: {
files: {
'dist/index.html': 'src/index.html'
}
}
}
});
But my question is, while using grunt how can I instruct the plugin to use specific target? For example, for a production build I want to use "dist" target specified in plugin config. I can do grunt htmlmin but it triggers 'dev' target only.

Elixir: Keep asset information in rev-manifest.json when using different gulp flags

With gulpUtil.env.sass and gulpUtil.env.js I created two different flags to just run the Code I want. There is a flag --sassfor the stylesheet and a flag --js for the scripts.
The problem is, everytime I run these flags with gulp, the rev-manifest.json gets overwritten with either the stylesheet information or the scripts information, but it never keeps both. How can I achieve that?
var elixir = require('laravel-elixir');
var gulpUtil = require('gulp-util');
elixir(function(mix) {
if(gulpUtil.env.sass) {
mix.sass('../scss/main.scss'),
mix.version([
'public/css/main.css'
], 'public/');
}
if(gulpUtil.env.js) {
mix.copy([
'resources/assets/js/vendor/alertify.min.js',
'resources/assets/js/create.test.js',
'resources/assets/js/edit.test.js',
'resources/assets/js/imgpreview.js',
'resources/assets/js/whenAll.js',
], 'public/js')
mix.version([
'public/js/alertify.min.js',
'public/js/create.test.js',
'public/js/edit.test.js',
'public/js/imgpreview.js',
'public/js/whenAll.js'
], 'public/');
}
});
See also: https://github.com/sindresorhus/gulp-rev/issues/10

how to make webpack sourcemap to original files

I'm trying to debug an application written in Angular 2 build from webpack with VScode. I'm able to use the debugger for chrome extension in VSCode to attach my application. And it did hit the break point of the compiled js file. But it cannot find the sourcemap files.
It seems that webpack will have a webpack:// to host the files which the *.js file pointed to, like in the image:
And I can set the breakpoint inside the ts files inside webpack folder. However vscode is not able to find the ts files. So I change the configuration of webpack to
output: {
path:root('__build');
devtoolModuleFilenameTemplate: function(info){
return "file:///"+info.absoluteResourcePath;
}
},
And then all files seemed to map to the absolute paths of the original ts files. And in chrome developer tool it looks like this:
But both chrome and vscode said the files inside this file:// is different from the original ts files. So I'm wondering whether there's a way that in webpack's configuration could make *.js file sourcemap to original ts files. And here's all my configurations:
typescript configuration:
{
"compilerOptions": {
"outDir": "dist",
"target": "ES5",
"module": "commonjs",
"sourceMap": true
}
}
webpack config:
{
entry: "./src/app/bootstrap",
output: {
path: root('__build__'),
filename: env({
'development': '[name].js',
'all': '[name].[hash].min.js'
}),
devtoolModuleFilenameTemplate: function(info){
return "file:///"+info.absoluteResourcePath;
}
},
devtool:'source-map',
devServer: {
contentBase: "public/"
}
}
Another thing is that if in chrome developer tools, if I add the original files into the workspace and map the files from file:// to this folder, I can actually set breakpoints inside these files. So I'm wondering there's a way to map to local resources in vscode.
I changed this:
output: {
// ...snip...
devtoolModuleFilenameTemplate: function(info){
return "file:///"+info.absoluteResourcePath;
}
},
to this:
output: {
// ...snip...
devtoolModuleFilenameTemplate: function(info){
return "file:///"+encodeURI(info.absoluteResourcePath);
}
},
and now it encodes the spaces properly, and the sourcemap file works as expected.
Thanks to Rob Lourens, this problem is caused by spaces and other special characters in the file path that may break sourcemaps.

Gulp and Bower-files: Get js-files for developing and for production

I am having tried to read tutorials and browse other questions, but cannot find a good answer to how I can set up gulp so that I get javascript-files from (already installed) bower-components for development and for production.
First I tried a simple way. For development:
gulp.task('vendorScriptsDevelopment', function() {
return gulp.src(['bower_components/jquery/dist/jquery.js',
'bower_components/**/*.js',
'!bower_components/**/*.min.js'])
.pipe(filter('*.js'))
.pipe(concat('vendor-scripts.js'))
.pipe(gulp.dest('dev'))
});
And similar for production:
gulp.task('vendorScriptsProduction', function() {
return gulp.src(['bower_components/jquery/dist/jquery.min.js',
'bower_components/**/*.min.js'])
.pipe(filter('*.js'))
.pipe(concat('vendor-scripts.js'))
.pipe(gulp.dest('prod'))
});
I included jquery specifically first, since other plugins often depend on it.
But then I realize that some bower packages includes a lot of files, also various javascript-files that I do not want (I just want "the one" that typically also has a CDN-option (and are offered in two versions, normal js and minimized)).
One tutorial I have read uses the main-bower-files plugin for the development part, but then it goes on in the wrong direction and wants to make a minified version itself (as I understand, it is always best to use the packages included minified version, as that is optimized from the developers of the plugin).
How can I set up my two Gulp tasks so that they works as intended? Or am I forced to included all the files manually (like I included jquery manually in my examples)?
Ok, since nobody has replied, here is my attempt to answer my own question.
I created a function that generates an array of the filenames that I want. This uses main-bower-files and filters out the .js-files. If this is development, then that's it. If it is production, then I just change the file extension from .js to .min.js (and for safety checks if that file exists).
var concat = require('gulp-concat');
var mainBowerFiles = require('main-bower-files');
var fs = require('fs');
var vendorScripts = function (minified) {
var scripts = mainBowerFiles().filter(function (filename) {
return filename.match(/.+\.js$/)
});
if (minified) {
scripts = scripts.map(function (orgFilename) {
var minFilename = orgFilename.replace(/^(.+)\.js$/, '$1.min.js');
if (fs.existsSync(minFilename)) {
return minFilename
}
return orgFilename;
});
}
return scripts;
};
gulp.task('vendorScriptsDevelopment', function() {
return gulp.src(vendorScripts())
.pipe(concat('vendor-scripts.js'))
.pipe(gulp.dest('dev'))
});
gulp.task('vendorScriptsProduction', function() {
return gulp.src(vendorScripts(true))
.pipe(concat('vendor-scripts.js'))
.pipe(gulp.dest('dist'))
});
I should change my function to handle other assets too, like css.
If somebody has a better approach, I would be very glad for a suggestion!
Here is my solution for your problem enjoy:
Create a vendors.json file in your sources folder. Edit the file and make path to relevant files you want to include in the production folder. For example:
{
"js" : [
"lib/jquery/dist/jquery.js",
"lib/lodash/lodash.js",
"lib/angular/angular.js",
"lib/angular-sanitize/angular-sanitize.js",
"lib/angular-ui-router/release/angular-ui-router.js",
"lib/angular-ui-utils/ui-utils.js",
"lib/angular-bootstrap/ui-bootstrap-tpls.js",
"lib/chartjs/Chart.js",
"lib/pnotify/pnotify.core.js",
"lib/pnotify/pnotify.buttons.js",
"lib/angular-pnotify/src/angular-pnotify.js",
"lib/angular-prompt/dist/angular-prompt.js",
"lib/angular-mocks/angular-mocks.js"
],
"css" : [
"lib/bootstrap/dist/css/bootstrap.css",
"lib/bootstrap-rtl/dist/css/bootstrap-rtl.css",
"lib/bootstrap/dist/css/bootstrap-theme.css",
"lib/font-awesome/css/font-awesome.css",
"lib/pnotify/pnotify.core.css",
"lib/pnotify/pnotify.buttons.css"
],
"statics" : [
"lib/font-awesome/fonts/*"
]
}
Then in the gulpFile.js add this:
var sources = {
get 'vendor.js'(){
return getVendorSources().js;
},
get 'vendor.css'(){
return getVendorSources().css;
},
get 'vendor.statics'(){
return getVendorSources().statics;
}
};
function getVendorSources(){
return JSON.parse(fs.readFileSync('yourSourcesFolder/vendor.json', 'utf-8'));
}
gulp.task('vendor.css', function() {
return gulp.src(sources['vendor.css'])
.pipe(changed(paths.dist))
.pipe(gulp.dest(paths.dist));
});
and so on for the js and static files tasks.

Gruntfile to minify all HTML files of a folder?

I’m using https://github.com/jney/grunt-htmlcompressor to compress HTML files. But it’s requiring me to manually type-in all the HTML files which I want minified:
grunt.initConfig({
htmlcompressor: {
compile: {
files: {
'dest/index.html': 'src/index.html'
},
options: {
type: 'html',
preserveServerScript: true
}
}
}
});
Is there a way to specify that I want to minify all HTML files of the entire folder (and subfolders)?
Or, in case this html-compressor is limited, are you aware of a different npm package that does this HTML mification?
The glob pattern should be allowed for any grunt task by default. Then simply use dynamic files to build each one to your dest
Instead of:
files: {
'dest/index.html': 'src/index.html'
},
Go with:
files: [
{
expand: true, // Enable dynamic expansion.
cwd: 'src/', // Src matches are relative to this path.
src: ['**/*.html'], // Actual pattern(s) to match.
dest: 'dest/', // Destination path prefix.
},
],
As far as another plugin I would recommend grunts contrib version since it's more common and maintained by the grunt team.