I'm currently setting up grunt-usemin for our project but I'm running in a small issue with the cssmin task.
Our project depends on a few external libraries, some which bring a long some extra assets (like images or fonts). The problem is these libraries do not have the same folder structure.
This is an example of the different folder structures
lib
|--lib1
| |--style1.css
| +--image1.png
+--lib2
|--styles
| +--style2.css
+--images
+--image2.png
In the index.html all the stylesheets are referenced and put inside a build block. As such, when the usemin task executes, the stylesheets of the libraries are concatenated in one minified file and put inside the output folder. The corresponding assets (images) are copied over to this output folder as well and flatened in the img folder. The output folder structure looks like
out
|--allstyles.min.css
|--image1.png
+--image2.png
As you can guess, the concatenated stylesheets has (in this example) two different relative URIs:
image1.png
..\images\image2.png
This is causing an issue where some of the images cannot be found. I need a solution to rebase all relative URIs to the out folder. I tried using the target and root options of the cssmin task but to no avail. Could someone point me to a correct configuration of this task or to another Grunt task that could achieve what I'm looking for?
Thanks in advance!
I have a grunt file in C:\web\project and CSS files in C:\web\project\www\css. The following snippet is from my grunt file and it rebases URLs correctly for me.
var cssFiles = [
'www/css/layout/Header.css',
'www/css/layout/Footer.css',
'www/css/vendor/chosen/chosen.css'
// ...
];
cssmin: {
concat: {
options: {
keepBreaks: true, // whether to keep line breaks (default is false)
debug: true, // set to true to get minification statistics under 'stats' property (see test/custom-test.js for examples)
noAdvanced: true, // set to true to disable advanced optimizations - selector & property merging, reduction, etc.
//relativeTo: 'http://online-domain-tools.com/'
noRebase: false, // whether to skip URLs rebasing
root: 'www'
},
nonull: true,
src: cssFiles,
dest: 'www/temp/application.css'
},
minify: {
options: {},
nonull: true,
src: ['www/temp/application.css'],
dest: 'www/temp/application.min.css'
}
},
// ...
grunt.registerTask('default', ['cssmin:concat', 'cssmin:minify']);
Can you post your gruntfile to compare it?
Related reading: https://stackoverflow.com/a/21415649/99256
look in the cssmin documentation/options:
rebase: set to false to skip URL rebasing
That solves the issue.
Related
I'm trying to uglify ( mangle + remove comments ) a SapUI5 app by using grunt together with the grunt-sapui5-bestpractice-build plugin.
According to this link, there should not be an uglify task by using this plugin so I've combine it together with the grunt-contrib-uglify plugin.
The problem that I have is; when performing the application build, it seems that my uglify task is being ignored because the grunt-sapui5-bestpractice-build has an implicit uglify task that overwrites the one I'm defining.
For a better understanding, this is the code:
package.json
{
"name": "grunt-build",
"version": "0.0.1",
"description": "Grunt build",
"private": true,
"devDependencies": {
"#sap/grunt-sapui5-bestpractice-build": "1.3.33",
"grunt-contrib-uglify": "3.3.0"
}
}
Gruntfile.js
module.exports = function(grunt) {
'use strict';
// Project configuration.
grunt.initConfig({
uglify: {
options: {
mangle: true,
compress: {
drop_console: true,
dead_code: false,
unused: false
}
},
files: {
expand: true,
cwd: "<%= ref.staging%>",
src: ["**/*.js", '!test/**', '!test_local.html'],
dest: "<%= ref.process%>"
}
}
});
grunt.loadNpmTasks('#sap/grunt-sapui5-bestpractice-build');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', [
'lint',
'clean',
'build',
'uglify'
]);
};
The result is that the application is correctly built & minified, Component-preload.js is created ad used to load the app but the mangle is not done and the comments are still there.
Could you kindly provide any advice here? Do you have any way to input the grunt-sapui5-bestpractice-build with the mangle option in order to do it just using one plugin?
Thanks in advance.
This is more of an extended comment, and not a fully functional answer. I just ran out of space.
The advantage of having the Component-preload.js not mangled is that you can debug it normally, because it contains the spaces, comments etc. Debugging mangled code is more difficult.
You'll have to look at the things you need to do to accomplish this mangling. After '#sap/grunt-sapui5-bestpractice-build' is done, you have minified but not mangled Component.js, a minified but not mangled Comonponent-preload.js and a normal development version in Component-dbg.js, correct?
You might want to abandon the best practice package and go for something else entirely like this: https://www.npmjs.com/package/grunt-openui5. I can't see what happens in the steps in '#sap/grunt-sapui5-bestpractice-build', I can't even find that package anywhere.
Grunt is only executing a series of tasks in a row. I haven't tried the webIDE versions of this but here's the list of tasks I'm executing as part of an offline openui5 app:
'clean:build', // remove `build` folder
'clean:dist', // remove `dist` folder
'copy:build', // copy all my code to the `build` folder
'preload', // mangle all my code in the `build` folder and create a preload
'copy:dist:minified', // copy the mangled code to `dist`
'copy:dist:dbg', // copy and rename my original code as `-dbg.js` versions to `dist`
'clean:build' // remove the `build` folder
This was done with gulp, using packages gulp-openui5-preload and gulp-uglify and some others. Not sure if gulp works on the web ide, but I think you can recreate this in Grunt.
You can either use something like this to mangle the results of the default process and create a new preload file, or you can scrap the default and try to roll your own entirely.
I have a project which has multiple directories in which css is stored (slightly different css for different languages)
Example Directory Structure:
/sass
- /latin
- /hindi
- /chinese
Inside each of those directories is an index.scss file.
I then have a mustache template which pulls in css from the correct directory based on the language set.
I have tried using purify css and unCSS they both work great with a single .css file but do not seem to work when you have multiple directories and files.
I would like each file in each directory to have the unused css removed and a new file created in each directory.
Now grunt supports this sort of recursive task using this format for a task:
files: [
{
expand: true, // Enable dynamic expansion.
cwd: 'lib/', // Src matches are relative to this path.
src: ['**/*.js'], // Actual pattern(s) to match.
dest: 'build/', // Destination path prefix.
ext: '.min.js', // Dest filepaths will have this extension.
extDot: 'first' // Extensions in filenames begin after the first dot
},
But it seems that the two unused css tasks I have tried do not support this.
Does anyone have any suggestions?
Thanks.
I'm looking for a plugin chain to use with Gulp that provides:
source map support
less
minification
concatenation
URL replacement (rebase) to address relocation/concat
I currently have the first four, but I can't find a combination of existing plugins that will give me the last (URL rebasing) also. I've not found any URL rebasing plugins that emit sourcemaps.
Just to be clear, my issue is that when I compile multiple small CSS files from my project development folders, and output them into a common folder, the move resulting from concatenation breaks relative URLs, such as those for background images.
EDITS:
It sounds like the tool chain I currently use is already intended to solve this problem. So, that's ostensibly the answer. However, that raises another question, how the required syntax is supposed to work.
That question theoretically has lots of duplicates out there:
clean-css #152: Rebasing functionality very frustrating
clean-css #195: root option on Windows
clean-css #263: How to get relativeTo option working with CSS files in different paths
http://adilapapaya.com/docs/clean-css/#howtorebaserelativeimageurls
Grunt cssmin rebasing a relative URI?
Unfortunately no answers actually explain the syntax, they just demonstrate voodoo; so I don't know why the following isn't working. If I can get it resolved I'll come back here and flag this accepted to indicate this tool chain does actually do what I need.
The source files:
/assets
/site
styleInput1.less "url(../site/logo.png)"
logo.png
background.png
/application
styleInput2.less "url(../site/background.png)"
The gulp task:
gulp.task(filename, function () {
return gulp.src(files)
.pipe(sourcemaps.init())
.pipe(less())
.pipe(minifyCss({ relativeTo: './compiled' }))
.pipe(concat(filename))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./compiled'));
});
The output, with broken URLs. Note the multiple defects. Although the CSS is raised a directory level relative to the required assets, an additional parent directory has been added (!). Also, one of the URLs has had a hard asset folder name changed (!). Very strange:
/compiled
styleOutput1.css "url(../../compiled/logo.png)"
styleOutput2.css "url(../../site/background.png)"
My apologies for continuing the voodoo, but here is my working gulp pipe:
.pipe(minifyCss({ relativeTo: './compiled', target: './compiled' }))
And the correct output:
/compiled
styleOutput1.css "url(../assets/site/logo.png)"
styleOutput2.css "url(../assets/site/background.png)"
I personally use gulp-minify-css and specify the relativeTo attribute.
gulp.task('css', function() {
gulp.src('./assets/css/main.css')
// Here I specify the relative path to my files
.pipe(minifyCSS({keepSpecialComments: 0, relativeTo: './assets/css/', processImport: true}))
.pipe(autoprefixer({
browsers: ['last 2 versions'],
cascade: false
}))
.pipe(gulp.dest('./assets/css/dist/'))
.pipe(notify({
"title": "Should I Go?",
"subtitle": "Gulp Process",
"message": '<%= file.relative %> was successfully minified!',
"sound": "Pop",
"onLast": true
}));
});
If that doesn't work for you, they have a lot of other parameters to rebase URLs : https://github.com/jakubpawlowicz/clean-css#how-to-use-clean-css-programmatically
Notably:
rebase - set to false to skip URL rebasing
relativeTo - path to resolve relative #import rules and URLs
restructuring - set to false to disable restructuring in advanced
optimizations
root - path to resolve absolute #import rules and rebase relative
URLs
I have a number of backbone apps all hosted on the same site. I am attempting to use grunt-manifest to generate appcache manifests for them. It generates the manifest file, but the links are wrong. I want each app to have a separate manifest file.
For example say I have an app called 'hello', it would be accessed via this url:
mydomain.com/apps/hello
so the main js and css files would be at:
mydomain.com/apps/hello/app.js
mydomain.com/apps/hello/style.css
etc.
There are also some shared components, found at say:
mydomain.com/shared/shared.js
(I dynamically load these with require.js so don't want to concat into the main app.js)
I specify the manifest in grunt like this:
manifest: {
generate: {
options: {
basePath: '<%= gconf.dist_dir %>/',
timestamp: true,
network: ['*'],
},
files: [
{
cwd: 'public/',
src: [
'apps/hello/*',
'shared/*',
// etc
],
dest: '<%= gconf.dist_dir %>/public/apps/hello/manifest.appcache' },
]
}
},
I believe the issue is I am trying to get grunt-manifest to generate an appcache manifest for a portion of a site not the root site. The manifest i get looks like this:
CACHE
apps/hello/app.js
apps/hello/style.css
shared/shared.js
When I load the page - the manifest retrieval fails because it is trying to access links like this:
mydomain.com/apps/hello/apps/hello/app.js
If I manually edit the manifest files and add a '/' in front of everything so it looks like this:
CACHE
/apps/hello/app.js
/apps/hello/style.css
/shared/shared.js
...then it all works.
The issue obviously being the manifest creating relative links, when I want them from the root.
I cannot for the life of me figure out how to get grunt-manifest to create these for me with a '/' in front.
I've tried experimenting with 'basePath' on its own, 'cwd' on its own, a combination of the two. If I leave the '/' off the end of say basePath or cwd and try adding it in the 'src' it doesn't work and I get an empty CACHE section.
I'm sure there must be an easy way of doing this with the grunt globing patterns, but I just can't work it out.
Any ideas?
(also - not enough rep to create a new tag, but a 'grunt-manifest' tag might be useful for others in the future)
I just ecnountered the same issue.
I've forked the module here: https://github.com/killfish/grunt-manifest
If you pass in the option absolutePath : true, it will prepend a '/'
options: {
**absolutePath: true,**
network: ['http://*', 'https://*'],
preferOnline: true,
verbose: true,
timestamp: true
},
So in my config file, I'm statically defining the css files to watch, along with some html partials. (eventually I will minimatch with exclusions .. I'm just going with first pass right now)
Originally I was storing these in the grunt config object, but struggled to get the output I wanted, so I moved them out of the initConfig method and into the wrapping function:
Original pass:
grunt.initConfig({
cssFiles: [ ... list of files ... ],
htmlFiles: [ ... list of files ...],
watch: {
reload: {
files: ['<%= cssFiles.concat(htmlFiles).join(",") %>']
}
}
});
I tried several variations of this (with and without join), as an example.
Current "Working" version:
module.exports = function(grunt) {
var cssFiles = ['someFile.css',...'lastFile.css'],
htmlFiles = [ ... ];
grunt.initConfig({
watch: {
reload: {
files: cssFiles.concat(cshtmlFiles)
}
}
});
};
I feel like I should be able to do this without having to move my array's out of the grunt config (although I don't know WHY I feel they should stay there ... I guess I just haven't seen many Gruntfile's with code outside of initconfig)
I'm using a system that stores all the paths I need in a single config object, like so:
grunt.initConfig({
pathTo: {
distcss : './dist/css/master.css',
srcstyles : './lib/styles/**/*.scss',
vendor : './lib/vendor'
},
// tasks...
});
Then, I load those in via underscore templates like in your first example. If your project is structured in a good way then usually just having one minimatch pattern is enough. All my CSS ends up in lib/styles, and any misc. third party stuff is usually in lib/vendor as that is managed through Bower.
With the right directory structure and pattern you shouldn't need a large array of paths. A sample JavaScript project could look like this:
lib
└── src
├── app
└── tests
Then your minimatch pattern to lint your application and test code would just be lib/src/**/*.js, for example.
But what works for you works for you; if you've written a system that you're happy with, regardless of whether you've seen it elsewhere or not, there's no reason to change it. :-)