Build whole angular project using grunt - javascript

I'm using grunt for the first time in order to annotate/minify/uglify my whole angular project. Here is what i have for the moment :
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
ngAnnotate: {
options: {
singleQuotes: true
},
all: { //"app" target
files: [
{
expand: true,
src: ['./app/**/*.js'],
dest: './build',
},
],
}
},
concat: {
js: { //target
files: [
{
expand: true,
src: ['./build/**/*.js'],
dest: '.',
},
],
}
},
uglify: {
js: { //target
files: [
{
expand: true,
src: ['./build/**/*.js'],
dest: '.',
},
],
}
}
//grunt task configuration will go here
});
//load grunt task
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-ng-annotate');
//register grunt default task
grunt.registerTask('default', ['ngAnnotate', 'concat', 'uglify']);
}
This works great, i get all my .js files in a "build" folder, with the correct folder architecture. The problem is : i only have the javascript files.
What am i supposed to add in the gruntfile to have my whole project architecture in the "build" folder ? ( HTML,CSS and media files in the right places, not only the annotated/minified/uglified javascript ?

You'll want to look at the copy task. It lets you copy files from one directory to another (like your html, css, fonts, images, etc):
copy: {
html: {
files: [
{expand: true, cwd: '.app/', src: ['some-dir/index.html'], dest: '.build/'}
]
},
css: {
files: [
{expand: true, cwd: '.app/', src: ['some-dir/styles/**/*.css'], dest: '.build/'}
]
},
// ... more targets for `copy`
}

Let's assume we want the following post-build file structure:
.
├── build
│ ├── css
│ ├── img
│ └── js
└── index.html
grunt-contrib-concat
You can just add a parameter for your CSS to be concatenated in a single file, just like you did with JS files.
concat: {
js: {
src: [
'scripts/config.js',
'app.js',
'controllers/*.js'
],
dest: 'build/js/main.js'
},
css: {
src: [
'css/*.css'
],
dest: 'build/css/main.css'
}
}
grunt-contrib-cssmin
This will minify your CSS (the single file the concat task created.)
cssmin: {
target: {
files: [{
expand: true,
cwd: 'build/css',
src: ['*.css', '!*.min.css'],
dest: 'build/css',
ext: '.min.css'
}]
}
}
grunt-contrib-imagemin
Minifies your images and puts them in build/img.
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'images/',
src: ['**/*.{png,jpg,jpeg}'],
dest: 'build/img/'
}]
}
}
And finally:
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.registerTask('default', ['concat', 'uglify', 'cssmin', 'imagemin']);

Related

Grunt, how to minify different folders (to include node_modules folder)

I am using NPM in a WP project.
I already have a grunt task that compiles my separate SCSS files into CSS files and then minifies them into one default.min.css file when running grunt (that's good.)
My main issue is that I would like to include different npm packages such as fontawesome, bootstrap etc. where they also would be minified into that one minified min.css file, together with my own files.
I would also like to know how to do this for my own *.js files uglify'd with different packages i'm using (jquery-ui, owl-carousel, etc.)
Please find below my Gruntfile.js, this is my first Gruntfile.js so feel free to include any constructive remarks.
Thanks,
Bud
Gruntfile.js
module.exports = function (grunt) {
grunt.initConfig({
sass: {
dist: {
files: [{
expand: true,
cwd: 'resource/scss/',
src: ['*.scss'],
dest: 'resource/builds/css/',
ext: '.css'
}]
}
},
watch: {
css: {
files: '**/*.scss',
tasks: ['sass', 'cssmin']
},
scripts: {
files: 'resource/js/*.js',
tasks: ['uglify']
}
},
cssmin: {
target: {
files: [{
expand: true,
cwd: 'resource/builds/css/',
src: ['*.css', '!*.min.css'],
dest: 'public/css',
ext: '.min.css'
}]
}
},
concat: {
js: {
options: {
separator: ';'
},
src: 'resource/**/*.js',
dest: '<%= paths.dest.js %>'
}
},
uglify: {
build: {
files: [{
expand: true,
cwd: 'resource/js/',
src: '**/*.js',
dest: 'public/js',
ext: '.min.js'
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default',['cssmin', 'uglify', 'watch']);
};

More efficient way of copying dist files in Grunt?

New to gruntjs and currently using it for moving some npm distributions to a public/js folder.
Here is the code:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
copy: {
bootstrapCss: {
src: "./node_modules/bootstrap/dist/css/bootstrap.css",
dest: "./public/css/bootstrap.css"
},
bootstrapTheme: {
src: "./node_modules/bootstrap/dist/css/bootstrap-theme.css",
dest: "./public/css/bootstrap-theme.css"
},
bootstrap: {
src: "./node_modules/bootstrap/dist/js/bootstrap.js",
dest: "./public/js/libs/bootstrap.js"
},
backbone: {
src: "./node_modules/backbone/backbone.js",
dest: "./public/js/libs/backbone.js"
},
backboneLocalstorage: {
src: "./node_modules/backbone.localstorage/backbone.localStorage.js",
dest: "./public/js/libs/backbone.localStorage.js"
},
requireJs: {
src: "./node_modules/requirejs/require.js",
dest: "./public/js/libs/requirejs.js"
},
underscore: {
src: "./node_modules/underscore/underscore.js",
dest: "./public/js/libs/underscore.js"
},
jquery: {
src: "./node_modules/jquery/dist/jquery.js",
dest: "./public/js/libs/jquery.js"
},
requireJsText: {
src: "./node_modules/requirejs-text/text.js",
dest: "./public/js/libs/requirejs-text.js"
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-copy');
// Default task(s).
grunt.registerTask('default', ['copy']);
};
Is there any way to make this code smaller, rather than have lots of individual copy commands?
Thanks
I would go about this by creating two targets in my copy configuration, one for JS and one for CSS. I would use some of the features provided by Grunt for dynamically building the files object to save me from typing and maintaining each destination path. This way, when I want to add files, I need only add their paths to the respective src array.
grunt.initConfig({
copy: {
js: {
expand: true,
cwd: './node_modules',
dest: './public/js/libs/',
flatten: true,
filter: 'isFile',
src: [
'./bootstrap/dist/js/bootstrap.js',
'./backbone/backbone.js',
'./backbone.localstorage/backbone.localStorage.js',
'./requirejs/require.js',
'./underscore/underscore.js',
'./jquery/dist/jquery.js',
'./requirejs-text/text.js'
]
},
css: {
expand: true,
cwd: './node_modules',
dest: './public/css/',
flatten: true,
filter: 'isFile',
src: [
'./bootstrap/dist/css/bootstrap.css',
'./bootstrap/dist/css/bootstrap-theme.css'
]
}
}
});

Uglify with SourceMaps while using grunt usemin and rev

I want to log javascript errors to server but the stacktrace is not useful with minified JS code. So I was thinking of using either Getsentry or Rollbar which shows proper stack trace with the help of sourcemaps. But I'm struggling to create sourcemap in first place.
I'm getting this error
"Destination (_build/js/app.js) not written because src files were empty."
Once it creates source map properly, there will be another problem i.e. rev will rename the file. I also need to leave the unminified concatenated file.
Below is my gruntfile.js (I've removed few bits out of it.)
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: {
jsFolders: {
src: [
'_build/js/ui',
'_build/js/vendor',
'_build/js/app',
'_build/js/*templates.js'
]
},
build: {
src: ['_build/**/*']
}
},
copy: {
build: {
files: [{
expand: true,
src: [
'index.html',
'img/**/*', //includes web.cofig also.
'img/**/*.svg',
'!img/**/*.psd',
'js/**/*', //includes web.cofig also.
'css/**/*', //includes web.cofig also.
'*.png',
'favicon.ico'
],
dest: '_build/'
}]
},
},
rev: {
option: {
algorithm: 'sha1',
length: 4
},
all: {
files: {
src: [
'_build/**/*.{js,css,eot,ttf,woff}'
]
}
}
},
useminPrepare: {
html: ['_build/index.html']
},
usemin: {
html: [
'_build/index.html'
],
css: [
'_build/css/**/*.css'
]
},
uglify: {
options: {
sourceMap: '_build/js/app.js.map',
},
js: {
files: {
'_build/js/app.js': ['_build/js/app.js']
}
}
},
cssmin: {
minify: {
expand: true,
cwd: '_build/css/',
src: '*.css',
dest: '_build/css/'
}
},
});
grunt.registerTask('build', [
'clean:build',
'handlebars',
'compass',
'autoprefixer',
'copy:build',
'useminPrepare',
'concat',
'uglify',
'cssmin',
'clean:jsFolders',
'rev',
'usemin',
]);
};
UPDATE
Tried #Andy's solution, it still shows the same error "Destination (_build/js/app.js) not written because src files were empty." and it also says below while building
uglify:
{ options:
{ sourceMap: true,
sourceMapName: '_build/js/app.js.map' },
js: { files: { '_build/js/app.js': [ '_build/js/app.js' ] } },
generated:
{ files:
[ { dest: 'dist\\js\\app.js',
src: [ '.tmp\\concat\\js\\app.js' ] } ] } }
Don't know where it got dest name from. My output folder is _build.
UPDATE2:
Refer to below links for better solution
https://stackoverflow.com/a/20574196/148271
https://github.com/gruntjs/grunt-contrib-uglify/issues/39#issuecomment-14856100
useminPrepare is merging the existing uglify config with its own, but nested under generated. Therefore this configuration for uglify works for me
grunt.initConfig({
uglify: {
generated: {
options: {
sourceMap: true
}
}
}
});
There is no simple solution to getting sourcemaps to work with the usemin flow.
Its a known problem that hasnt been addressed in a year it seems:
https://github.com/yeoman/grunt-usemin/issues/30
https://github.com/yeoman/grunt-usemin/issues/220
The options for uglify are:
sourceMap: true,
sourceMapName: 'path/to/name.map'
For example, in my GruntFile.js I use the name found in package.json:
sourceMap: true,
sourceMapName: 'dist/<%= pkg.name %>-<%= pkg.version %>.map'

Gruntjs cwd mask

My file structure:
services/
-- service1/
---- service1.png
-- service2/
---- service2.jpg
-- service3/
---- service3.gif
...
I use grunt-contrib-imagemin for minify and move images.
I want get this structure:
logo/
-- service1.png
-- service2.jpg
-- service3.gif
...
In my grunt-config I tried using '**' in cwd param, but it not work:
grunt.initConfig({
imagemin: {
dynamic: {
options: {
optimizationLevel: 3
},
files: [
{
expand: true,
cwd: 'services/**/',
src: ['*.{png,jpg,gif}'],
dest: 'logo/'
}]
}
}
});
Help me please.
Try this instead:
grunt.initConfig({
imagemin: {
dynamic: {
options: {
optimizationLevel: 3
},
expand: true,
flatten: true,
cwd: 'services',
src: ['**/*.{png,jpg,gif}'],
dest: 'logo/'
}
}
});
cwd is just a file path and doesn't do pattern matching. The flatten option will flatten your file output.

how to config grunt.js to minify files separately

there are some js files in static/js/
1. a.js
2. b.js
3. c.js
how to config grunt.js to get below files:
1. a.min.js
2. b.min.js
3. c.min.js
as far, I have to type specific file name:
min: {
dist: {
src: 'js/**/*.js',
dest: 'js/min/xxx.min.js'
}
}
Had the same problem and found a solution that would automatically minify all my scripts separately:
uglify: {
build: {
files: [{
expand: true,
src: '**/*.js',
dest: 'build/scripts',
cwd: 'app/scripts'
}]
}
}
In grunt 0.4 you can specify multiple dest/src pairs like this:
uglify: {
dist: {
files: {
'dist/main.js': 'src/main.js',
'dist/widget.js': 'src/widget.js'
}
}
}
Or you can use expandMapping, like this:
min: {
files: grunt.file.expandMapping(['path/*.js', 'path2/*.js'], 'destination/', {
rename: function(destBase, destPath) {
return destBase+destPath.replace('.js', '.min.js');
}
})
}
And the output:
path/test.js => destination/path/test.min.js
path2/foo.js => destination/path2/foo.min.js
This below gruntjs works for me for creating minified files for all the js files under a dir
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
build: {
files: [{
expand: true,
src: '**/*.js',
dest: 'build/scripts',
cwd: 'public_html/app',
ext: '.min.js'
}]
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task(s).
grunt.registerTask('default', ['uglify']);
};
From the grunt docs for min:
This task is a multi task, meaning that grunt will automatically
iterate over all min targets if a target is not specified.
So you can do this:
min: {
min_a: {
src: 'a.js',
dest: 'a.min.js'
},
min_b: {
src: 'b.js',
dest: 'b.min.js'
},
min_c: {
src: 'c.js',
dest: 'c.min.js'
}
There's nothing special about the name 'dist' for these tasks.
Use the ext option to name the files .min.js instead of .js
uglify: {
build: {
files: [{
expand: true,
src: '**/*.js',
dest: 'build/scripts',
cwd: 'app/scripts',
ext: '.min.js'
}]
}
}
For explicitly export some files into separate output files (in this case all.min.js and all.jquery.js) use:
uglify: {
js: {
files : {
'js/all.min.js' : [
'js/modernizr.js',
'js/vendor/modernizr-2.6.2-respond-1.1.0.min.js',
'js/bootstrap.min.js',
'js/main.js',
'js/ZeroClipboard.min.js',
'js/bootstrap-datepicker/bootstrap-datepicker.js'
],
'js/all.jquery.js' : [
'js/vendor/jquery-1.9.1.js',
'js/vendor/jquery-migrate-1.2.1.js',
'js/vendor/jquery-ui.js'
]
}
},
options: {
banner: '\n/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n',
preserveComments: 'some',
report: 'min'
}
},
I like to keep the original files and also create uglified ones:
uglify: {
dist: {
files: [{
expand: true,
src: '**/*.js',
dest: 'destdir',
cwd: 'srcdir',
rename: function(dest, src) { return dest + '/' + src.replace('.js', '.min.js'); }
}]
}
},
You also can use copy and grunt-mindirect.
copy: {
dist: {
src: 'a.js',
dest: 'a.min.js'
}
},
minidirect: {
all: 'js/min/*.min.js'
}
This should work.
I guess it only matters for watch tasks.
In grunt 0.4 you can do this
var filesA = 'a.js', filesB = 'b.js', filesC = 'c.js';
...
min: {
min_a: {
src: filesA,
dest: 'a.min.js'
},
min_b: {
src: filesB,
dest: 'b.min.js'
},
min_c: {
src: filesC,
dest: 'c.min.js'
}
watch: {
min_a: {
files: filesA,
tasks: ['min:min_a']
},
min_b: {
files: filesB,
tasks: ['min:min_b']
},
min_c: {
files: filesC,
tasks: ['min:min_c']
}
}
After that just start grunt watch and all will be fine automagically.
In an intention to help others who come to this page in future -
I came across a video which explains on how to minify JS files using Grunt JS here: https://www.youtube.com/watch?v=Gkv7pA0PMJQ
The source code is made available here: http://www.techcbt.com/Post/359/Grunt-JS/how-to-minify-uglify-javascript-files-using-grunt-js
Just in case, if the above links are not working:
You can minify all javascript files and combine/concat into one file using the following script:
module.exports = function(grunt){
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify:{
t1:{
files:{
'dest/all.min.js': ['src/app.js', 'src/one.js', 'src/t/two.js']
}
}
}
});
};
If you would like to have source maps also generated, you can enable "sourceMap" option as follows:
module.exports = function(grunt){
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify:{
t1:{
options : {
sourceMap : true,
},
files:{
'dest/all.min.js': ['src/app.js', 'src/one.js', 'src/t/two.js']
}
}
}
});
};
In order to retain entire folder structure while minifying JS files, you can use the following script:
module.exports = function(grunt){
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify:{
t1:{
files: [{
cwd: 'src/',
src: '**/*.js',
dest: 'dest/',
expand: true,
flatten: false,
ext: '.min.js'
}]
}
}
});
};

Categories

Resources