Ignore package target path when using grunt-bower - gruntjs

I'm experimenting with grunt/bower for a project and I have the following content structure:
content
css
js
I've got grunt/bower working on my own files, but I'm trying to incorporate jquery now and the bower task keeps putting jquery in content/js/dist/jquery.js where I'd rather have content/js/jquery.js. In other words, I want to strip / ignore the dist folder when copying the file. So far, my task looks like this:
bower: {
install: {},
dev: {
dest: 'Content',
js_dest: 'Content/js',
less_dest: 'Content/css',
css_dest: 'Content/css',
options: {
packageSpecific: {
"jquery": {
dest: 'Content/js'
}
}
}
}
},
How can I tell the bower task to copy the dist/jquery.js from the jquery package file to the specific path content/js/jquery.js in my app?

You can use the keepExpandedHierarchy option (flattened output structure) in order to achieve this behavior. You can set is specifically on for jquery:
bower: {
install: {},
dev: {
dest: 'Content',
js_dest: 'Content/js',
less_dest: 'Content/css',
css_dest: 'Content/css',
options: {
packageSpecific: {
'jquery': {
keepExpandedHierarchy: false
}
}
}
}
}
When running grunt bower the jquery.js file is copied to Content\js\jquery.js:
>grunt bower
Running "bower:install" (bower) task
Running "bower:dev" (bower) task
Content\js\jquery.js copied.
Done, without errors.

Related

How do I generate sourcemaps for Uglified files using Grunt?

I have a Grunt project that uses both Browserify and Uglify. Here are the core bits of it:
browserify: {
myapp: {
options: {
transform: ['babelify'],
browserifyOptions: {
debug: true
},
},
src: 'src/index.js',
dest: 'build/myapp.js'
}
},
uglify: {
options: {
sourceMap: true,
banner: bannerContent
},
target: {
src: 'build/myapp.js',
dest: 'build/myapp.min.js'
}
},
It seems to generate a myapp.min.js.map file but it no longer has the raw sources in the source-map that existed prior to the Browserification.
Here's what the resultant source-map file contains:
{
"version":3,
"sources":[
"myapp.js"
],
"names":[
...
...
...
],
"mappings":".........",
"file":"myapp.min.js"
}
I've tried using the uglifyify transform for Browserify but that does not seem to generate as small files as the Uglify task.
I've also bumped all my dependencies to the latest but I haven't been able to resolve this issue.
grunt-contrib-uglify has a sourceMapIn option that allows you to specify the location of an input source map file from an earlier compilation - which in your scenario is the browserify task.
However, whilst setting browserifyOptions: { debug: true } in your browserify task does generate an inline source map in the resultant .js file (i.e. in build/myapp.js), the crux of the problem is twofold:
We don't have an external source map file that we can configure the sourceMapIn option of the subsequent grunt-contrib-uglify task to utilize.
grunt-browserify doesn't provide a feature to create an external .map file, it only creates them inline (see here)
To address the aforementioned issue consider utilizing grunt-extract-sourcemap to extract the inline source map from build/myapp.js (i.e. from the output file generated by your browserify task) after it has been produced.
Gruntfile.js
The following gist shows how your Gruntfile.js should be configured:
module.exports = function (grunt) {
grunt.initConfig({
browserify: {
myapp: {
options: {
transform: ['babelify'],
browserifyOptions: {
debug: true
},
},
src: 'src/index.js',
dest: 'build/myapp.js'
}
},
extract_sourcemap: {
myapp: {
files: {
'build': ['build/myapp.js']
}
}
},
uglify: {
options: {
sourceMap: true,
sourceMapIn: 'build/myapp.js.map'
},
target: {
src: 'build/myapp.js',
dest: 'build/myapp.min.js'
}
}
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-extract-sourcemap');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Note the order of the tasks in your task list is important.
grunt.registerTask('default', ['browserify', 'extract_sourcemap', 'uglify']);
};
Explanation
First the browserify task is invoked which outputs a new file (i.e. build/myapp.js) containing your bundled JavaScript and an "inlined" source map info. If you were to inspect the content of build/myapp.js at this stage it includes something like the following at the end:
//# sourceMappingURL=data:application/json;charset=utf-8;base64, ...
Next the extract_sourcemap task is invoked. This essentially extracts the "inlined" source map info from build/myapp.js and writes it to a new file named myapp.js.map which is saved in your build directory.
The original "inlined" source map info in build/myapp.js is replaced with a link to the newly generated source map file, i.e. myapp.js.map. If you inspect the content of build/myapp.js you'll now notice the following at the end of the file instead:
//# sourceMappingURL=myapp.js.map
Lastly the uglify task is invoked. Notice how its sourceMapIn option is configured to read build/myapp.js.map, i.e the source map file we generated at step 2.
This task creates your desired build/myapp.min.js file containing; your minified JS, and a link to a newly generated source map file build/myapp.min.js.map.
Note The final resultant file (i.e. build/myapp.min.js) now correctly maps back to the original src/index.js file and any file(s) that index.js itself may have import'ed or require()'d

Grunt CSS import and paths

I have the following setup in Grunt for the concat and minification of my projects css
cssmin: {
options: {
},
concat: {
files: {
'dist/app.css': [
'tmp/*.css',
'app/theme/css/vendors/fontello.css',
'app/theme/js/vendors/revolution/css/settings.css',
'app/theme/css/styles.css',
'app/theme/css/media-queries.css',
'app/app.css'
]
}
},
min: {
files: [{
src: 'dist/app.css',
dest: 'dist/app.css'
}]
}
},
It works fine with the exception that, as far as I can tell its removed the following import statement
#import url("http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic");
And all 3rd party css files have relative image paths which are not resolved. I can see cssmin uses clean css which should be able to help handle these issues but after hours of searching and reading the docs I can't any clear examples or doucmentation on how to configure the above to solve this?
I used Ze Rubeus suggestion of moving my font import statement into the HTML instead (a little annoying as it means modifying a 3rd party css file). But I found the option for fixing the css paths which is
rebase: true,
relativeTo: './'
My cssmin configuration now looks like
cssmin: {
options: {
rebase: true,
relativeTo: './'
},
concat: {
files: {
'dist/app.css': [
'tmp/*.css',
'app/theme/css/vendors/fontello.css',
'app/theme/js/vendors/revolution/css/settings.css',
'app/theme/css/styles.css',
'app/theme/css/media-queries.css',
'app/app.css'
]
}
},
min: {
files: [{
src: 'dist/app.css',
dest: 'dist/app.css'
}]
}
}
And everything is working :)
You have to change all you import PATH depend on this directory 'dist/app.css'
And instead of css font import I advice you to use the HTML link like the following
<link href='http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic' type='text/css'>
make sure to change all url Path's on these directory's :
'tmp/*.css',
'app/theme/css/vendors/fontello.css',
'app/theme/js/vendors/revolution/css/settings.css',
'app/theme/css/styles.css',
'app/theme/css/media-queries.css',
'app/app.css'
depend on this output 'dist/app.css': because there is no task in gruntjs who correct the import Path in css files for you !
regarding your code the watch task need's to be something like so :
watch: {
css: {
files: ['tmp/*.css',
'app/theme/css/vendors/fontello.css',
'app/theme/js/vendors/revolution/css/settings.css',
'app/theme/css/styles.css',
'app/theme/css/media-queries.css',
'app/app.css'],
tasks: ['concat','cssmin'],
options: { spawn: false }
}
},
And execute this command grunt watch in your terminal to keep automatically tracking for changes in these files and apply these tasks .

Grunt + Sass, how do I include subfolder scss when I compile?

I'm trying to change my sass workflow by including it in grunt and compiling from there. I can compile successfully if all my scss files are in one folder:
sass: {
dist: {
options: {
style: 'compact'
},
files: {
'style.css': 'css/*.scss'
}
}
}
however my usual file structure includes a subfolder for components exclusive to certain pages. Grunt is recognising the top level .scss files but nothing below it. I also tried this:
sass: {
dist: {
options: {
style: 'compact'
},
files: {
'style.css': 'css/main.scss',
'style.css': 'css/pages/*.scss'
}
}
}
but no joy there either. How do I compile to a single css file from multiple scss locations?
You must add /**/ after your folder, like so:
'style.css': 'css/**/*.scss'
You can see the documentation here: http://gruntjs.com/configuring-tasks#globbing-patterns

Installing 'modular-scale' using Grunt require without compass config.rb

I'm trying to install 'modular-scale' (https://github.com/Team-Sass/modular-scale) via my Gruntfile but I can't get it to work.
Note that I don't use a config.rb, I want to require the plugin using Grunt via grunt-contrib-compass.
I thought it was as simple as adding this to my Gruntfile (after the grunt.initConfig({ etc):
compass: {
dist: {
options: {
require: ['modular-scale'], // This line here
sassDir: 'setup',
cssDir: 'css'
}
}
},
watch: {
css: {
files: '**/*.scss',
tasks: ['compass']
}
}
The watch task is absolutely fine. The problem is that if I use one of the SASS variables that are part of the 'modular-scale' plugin, I'll get an error thrown up, suggesting that the 'modular-scale' isn't actually being required.
Am I missing something here?
You no longer need Compass or a config.rb file to use modular-scale.

Grunt - livereload only uglified script.js?

GruntJS newbie here. I currently have my gruntfile.js using the watch task to look for changes to any .js files in my js/components/ folder and uglify those scripts into a single script.js file.
The issue that I'm having is that these changes cause a full page reload.
Is it possible to only reload the script.js file without also reloading the HTML/CSS? The effect I'm after is the same effect I'm currently getting with SASS/CSS files like so:
watch : {
options: { livereload: true },
sass: {
options: {
livereload: false
},
files: ['css/sass/*.scss'],
tasks: ['compass:dev']
},
css: {
files: ['css/*.css']
}
}
This reloads only my CSS without reloading the entire page, which makes for a much smoother workflow. Is it possible to do the same for JS? If not, why not? My current JS workflow configuration looks like this:
grunt.initConfig({
uglify: {
my_target: {
files: {
'js/script.js' : ['js/components/*.js']
}
}
},
watch : {
options: { livereload: true },
scripts: {
files: ['js/components/*.js'],
tasks: ['uglify']
}
}
});
After reading around I finally wound up on the livereload.js Github page. Under the developer's rundown of the project's current status, "Live JS reloading" is the one remaining to-do item. So it's a planned feature, but not yet implemented. The last commit on the project was 7 months back, so I'm not sure when/if we can anticipate this update.

Resources