Combine and minify all bower libraries with gruntjs - gruntjs

Is there a way to combine and minify all bower installed libraries into 1 file automatically?
First I tried the most basic approach: combine all .js files from all subdirectories:
uglify: {
options: {compress: true},
my_target: { files: {
'vendor.js': ['bower_components/**/*.js'],
} } }
But this is obviously a bad approach. It also doesn't work because of too many errors.
I manually deleted all the files and kept only 1 (main) file that each library has, and it worked.
Is there a way to do this all automatically?
Also, is it advisable to do it? (i.e. combine all vendor libraries into 1 file)

I recommend the combination of 2 nice grunt libraries, Wiredep and Usemin:
Wiredep: Load all dependencies of bower identified in bower.json inside your html automatically
Usemin: Detect all src inside two comments tags and all that source are minified and concatenated in dist folder, below are a little example of a grunt files using this packages, is based on the generator of angular to yeoman this is only a brief of that grunt
Grunt
wiredep: {
options: {
cwd: 'appFolder'
},
app: {
src: ['htmlCollections'],
ignorePath: /\.\.\//
}
},
useminPrepare: {
html: 'htmlCollections',
options: {
dest: 'distributionFolder',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
usemin: {
html: ['distributionFolder+HtmlFiles'],
css: ['distributionFolder+cssFiles'],
js: ['distributionFolder+javascriptFiles']
}
HTML
<!doctype html>
<html lang="en" ng-app="MobileDev" id="ng-app">
<head>
<!-- build:css(app) styles/vendor.css -->
<!-- bower:css -->
//This gonna be generated for the grunt by dependencies in bower
<!-- endbower -->
<!-- endbuild -->
<!-- build:css(.tmp) styles/main.css -->
//All the script inside this gonna be concatened and minified in
//the dist folder by the name of main.css
<link type="text/css" rel="stylesheet" href="styles/app.css"/>
<!-- endbuild -->
</head>
<body>
<!-- build:js(app) scripts/vendor.js -->
<!-- bower:js -->
//This gonna be generated for the grunt by dependencies in bower
//And in distribution all bower components added gonna be minified by usemin in
//vendor.js
<!-- endbower -->
<!-- endbuild -->
<!-- build:js({.tmp,app}) scripts/scripts.js -->
//All the script inside this gonna be concatened and minified in the dist
//folder by the name of scripts.js
<script type="text/javascript" src="scripts/numero1"></script>
<script type="text/javascript" src="scripts/numero2"></script>
<!-- endbuild -->
</body>

Just needed wiredep
uglify: {
options: { compress: true },
my_target: {
files: { 'public/vendor.js': require('wiredep')().js
} } },
cssmin: {
minify: {
files: { 'public/vendor.css': require('wiredep')().css
} } },

Related

How to get rid of grunt-processhtml "<link rel=....>" tags

I'm trying to dynamically load some css files from a Javascript.
Snippet:
if (theme === 'testtheme' || theme === 'testtheme/') {
css =
<!-- build:css({.tmp,app}) styles/main_testtheme.css -->
'<link rel="stylesheet" href="styles/css/main_testtheme.css" type="text/css" />'
<!-- endbuild -->
;
} else {
css =
<!-- build:css({.tmp,app}) styles/main.css -->
'<link rel="stylesheet" href="styles/css/main.css" type="text/css" />'
<!-- endbuild -->
;
}
However, the grunt-build task replaces all the text between the build comments with something like:
<link rel="stylesheet" href="styles/e59b065a.main.css">
thus removing the string quotes and rendering the code invalid.
How I would like to to run:
<!-- build:css({.tmp,app}) styles/main.css -->
css = 'styles/css/main.css';
<!-- endbuild -->
should result in:
css = 'styles/e59b065a.main.css';
That would allow testing both the unminified (unbuilt) and the minified versions. Grunt build takes around 5 minutes for me so I'm trying to avoid that while developing.
Edit:
I can probably override the default blockReplacement for css (see https://github.com/yeoman/grunt-usemin#blockreplacements ) but it will make it a pain for anyone coming afterwards to try and figure out why their stylesheet is not embedded properly.
I still was not able to find an acceptable solution for this, but here's one that works, for now:
Gruntfile.js snippet:
useminPrepare: {
html: ['<%= yeoman.app %>/index.html', '<%= yeoman.app %>/includes.html'],
options: {
dest: '<%= yeoman.dist %>',
flow: {
// i'm using this config for all targets, not only 'html'
steps: {
// Here you define your flow for your custom block
cssQuoted: ['concat', 'cssmin'],
// use the option below where you have minified files that you just want to concatenate
concatjs: ['concat'],
// Note that you NEED to redefine flow for default blocks...
// These below is default flow.
js: ['concat', 'uglifyjs'],
css: ['concat', 'cssmin']
},
// also you MUST define 'post' field to something not null
post: {}
}
}
},
usemin: {
//css_name: ['<%= yeoman.dist %>/{,*/}*.html'],
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
options: {
//patterns: {
// html: [
// [ /cssHrefString\s+=\s+['"]([^"']+)["']/gm, 'Update the HTML to reference our revved/min CSS and add quotes' ]
// ]
//},
blockReplacements: {
cssQuoted: function(block){
return '\'<link rel="stylesheet" href="' + block.dest + '">\'';
},
concatjs: function (block) {
return '<script src="' + block.dest + '"></script>';
}
}
}
},
script.js snippet:
var theme = getUrlParameter('theme');
var cssHrefString;
// we need fully qualified css tags below otherwise grunt build will not be able to pick them up
if (theme === 'testtheme' || theme === 'testtheme/') {
cssHrefString =
<!-- build:cssQuoted({.tmp,app}) styles/main_testtheme.css -->
'<link rel="stylesheet" href="styles/css/main_testtheme.css">'
<!-- endbuild -->
;
} else {
cssHrefString =
<!-- build:cssQuoted({.tmp,app}) styles/main.css -->
'<link rel="stylesheet" href="styles/css/main.css">'
<!-- endbuild -->
;
}
$('head').append(cssHrefString);
The grunt config file adds a definition for concatjs - a tasks which only concatenates minified files, does not run the uglifier on them. cssQuoted which takes the string between the blocks and replaces it with a quoted "link rel=..." tag.
Make sure your grunt-usemin plugin version is up-to-date - I lost several hours trying out options with an old version (~0.1.3). The code above works with 3.0.0.

How to get Bower Install to copy files to another directory before linking them in html file?

In my gruntfile.js I am using bower install to create the necessary script tags in my index.html for all my js libraries. My grunt file entry looks like this:
bowerInstall: {
target: {
src: ['wwwroot/index.html'],
cwd: '',
dependencies: true,
devDependencies: true,
exclude: [],
fileTypes: {},
ignorePath: '',
overrides: {}
}
}
My index.html gets correctly updated from my index.html.tpl as seen here:
<head>
<!-- bower:js -->
<script src="../bower_components/jquery/dist/jquery.js"></script>
<script src="../bower_components/angular/angular.js"></script>
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="../bower_components/underscore/underscore.js"></script>
<!-- endbower -->
<!-- bower:css -->
<link rel="stylesheet" href="../bower_components/bootstrap/dist/css/bootstrap.css" />
<!-- endbower -->
<link rel="stylesheet" type="text/css" href="wwwroot/app/styles/style.css" />
What I want to happen is to copy all js library files to a specific lib directory, and then link them from there. Can this be accomplished with bower install or is there another grunt plug-in I should be using? The bower-install plugin seems popular but I can't find much documentation for it.
You should try to use grunt-bower along with grunt-bower-install. You can configure bower to install copy files to specific folders. It will look like this:
bower: {
dev: {
dest: 'lib/',
js_dest: 'lib/js',
css_dest: 'lib/styles'
}
}
Then if you run the task:
grunt bower
You will have something like this in your lib folder:
/js
/package1
package1_file1.js
package1_file2.js
/package2
package2.js
/styles
/package1
package1.css
/package2
package2.css
Add a .bowerrc file next to your bower.json. If the file is already in there change its content from:
{
"directory": "bower_components"
}
to
{
"directory": "you/new/lib/path"
}
Re-install your Bower components:
bower install
Then call the Grunt task:
grunt bowerInstall

How do I compile all my .js files into one minified file using grunt?

I'm new to grunt and I need a little help setting it up. I want to use SASS, Compass and compile all my .js files into one minified file.
The site I'm working on is not currently using grunt and I want to set it up to use it. All my .js files are included at the bottom of the page. What do I need to do to change it so that only one minified .js file contains all of the .js files?
At the bottom of my index page I have .js files included like so:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-route.min.js"></script>
<script src="//code.angularjs.org/1.3.4/angular-sanitize.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap.min.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script src="bower_components/angular-loading-bar/src/loading-bar.js"></script>
<script src="bower_components/angular-promise-tracker/promise-tracker.js"></script>
<script src="bower_components/angular-promise-tracker/promise-tracker-http-interceptor.js"></script>
<script src="js/config.json" type="application/json"></script>
<script src="js/infinite-scroll.js"></script>
<script src="js/hotels.js"></script>
<script src="js/weather.js"></script>
<script src="js/main.js"></script>
My Gruntfile.js looks like this:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
minified : {
files: {
src: [
'/js/src/**/*.js',
'/js/src/*.js'
],
dest: '/js/min/'
}
},
compass: {
dist: {
options: {
sassDir: 'sass',
cssDir: 'css'
}
}
},
watch: {
css: {
files: '**/*.scss',
tasks: ['compass']
}
}
});
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-minified');
grunt.registerTask('default',['watch']);
}
My package.json looks like this:
{
"name": "hoteldemo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "test"
},
"author": "",
"license": "ISC",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-compass": "^1.0.3",
"grunt-contrib-sass": "^0.9.2",
"grunt-contrib-watch": "^0.6.1"
}
}
You'll probably want to use something like grunt-usemin. It may even be worth your time to explore some of the generators provided by Yeoman since these generally give you the proper grunt scaffolding depending on the technologies you're using.
Using grunt-usemin alone in your project would look something like this:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular-route.min.js"></script>
<script src="//code.angularjs.org/1.3.4/angular-sanitize.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<!-- build:js js/min/app.min.js -->
<script src="bower_components/angular-bootstrap/ui-bootstrap.min.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script src="bower_components/angular-loading-bar/src/loading-bar.js"></script>
<script src="bower_components/angular-promise-tracker/promise-tracker.js"></script>
<script src="bower_components/angular-promise-tracker/promise-tracker-http-interceptor.js"></script>
<script src="js/config.json" type="application/json"></script>
<script src="js/infinite-scroll.js"></script>
<script src="js/hotels.js"></script>
<script src="js/weather.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->
You'll have to configure a grunt task to do the build for you which will be pretty specific to your setup. Just follow along with the grunt-usemin documentation.

How to concat certain js files

I have the need to just concat certain 'vendor' JS files. My users won't always have access to the internet and I need to concat already minified JS files.
I have this index.html:
<!-- build:js vendor.min.js -->
<script type="text/javascript" src="bower_components/jquery/jquery.min.js"></script>
<script type="text/javascript" src="bower_components/underscore/underscore.min.js"></script>
...
<!-- endbuild -->
<!-- build:js app.min.js -->
<script type="text/javascript" src="app/app.js"></script>
...
<!-- endbuild -->
I just want to concat the first group of files. Reason being is that some are already minified and some are not. The vendor files that are not minified cannot be minified.
Is there a way to run usemin to just concat the first group into a vendor.js file and concat and uglify the second group into an app.min.js file?
You should use flow option to define your custom workflow.
For example, if you need to only concat a group of files, add this to the useminPrepare:
useminPrepare: {
html: 'index.html',
options: {
flow: {
html: {
steps: {
onlyconcat: ['concat']
},
post: {}
}
}
}
}
In your index.html, change this:
<!-- build:onlyconcat vendor.min.js -->
<script type="text/javascript" src="bower_components/jquery/jquery.min.js"></script>
<script type="text/javascript" src="bower_components/underscore/underscore.min.js"></script>
...
<!-- endbuild -->

bower add Jquery UI theme in style

In my project I have included to jQuery UI.I am using Bower, Yeoman and Grunt.
I added jQuery UI: bower install jquery-ui --save .
but the jQuery UI theme was not included in Bower style components.
<!-- build:css(.) styles/vendor.css -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/components-font-awesome/css/font-awesome.css" />
<!-- endbower -->
<!-- endbuild -->
<!-- build:css(.tmp) styles/main.css ->
Help me with this problem .
This is not issue with library . its in Grunt-wiredep which has problem in injecting dependencies which has file name like jquery-ui,socket-io,font-awesome. there is way to override it .
wiredep: {
target: {
src: '<%= jericho.client %>/index.html',
ignorePath: '<%= jericho.client %>/',
exclude: [/es5-shim.js/, /json3.js/ ,/bootstrap.css/, /font-awesome.css/ ],
overrides: {
'socket.io-client': {
main: 'socket.io.js'
},
'jqueryui-touch-punch': {
main: 'jquery.ui.touch-punch.js'
}
}
}
},
so add 'jquery-ui': { main: 'jquery-ui.js' } . in the grunt wiredep configuration.
Link: https://github.com/taptapship/wiredep/issues/86

Resources