I am new to grunt and I am struggling with this problem. So I am working on a project where we use separate grunt configs for dev and prod.
The problem is that when I work on the dev server I have access to all css files. On prod server all css files are minifed and put into one css file
https://xxx/styles.a1a34405694a04f0edd0.css
The gruntfile-dist.js
file looks like this
'use strict';
// Grunt file for distribution only
// Removed tasks for dev
module.exports = function (grunt) {
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Configurable paths for the application
var appConfig = {
app: require('./bower.json').appPath || 'webapp',
// Web Application Sources should be defined on a /src/main/webapp folder
sources: '${basedir}/src/main/webapp',
// Test sources should be defined on /src/test
testSources: '${basedir}/src/test',
// Target folder where all generated files are placed
target: '${project.build.directory}',
// Documentation folder defined on target/docs folder
docs: '${project.build.directory}/docs',
// Distribution folder defined on target/dist folder
dist: '${project.build.directory}/dist'
};
grunt.loadNpmTasks('grunt-appcache', 'grunt-polyfill-builder');
// Define the configuration for all the tasks
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Project settings
yeoman: appConfig,
appcache: {
options: {
basePath: '<%= yeoman.dist %>'
},
all: {
dest: '<%= yeoman.dist %>/offline.manifest',
cache: '<%= yeoman.dist %>/**/*',
network: '*',
fallback: ['404.html']
}
},
// Replace url of image in dist/main.css file.
replace: {
manifest: {
src: ['<%= yeoman.dist %>/offline.manifest'],
dest: '<%= yeoman.dist %>/offline.manifest',
replacements: [
{
from: 'dist/',
to: ''
}
]
}
},
// Empties folders to start fresh
clean: {
target: {
files: [{
dot: true,
src: [
'<%= yeoman.target %>/*.{ico,png,txt}',
'<%= yeoman.target %>/.htaccess',
'<%= yeoman.target %>/*.html',
'<%= yeoman.target %>/views',
'<%= yeoman.target %>/images',
'<%= yeoman.target %>/styles',
'<%= yeoman.target %>/fonts',
'<%= yeoman.target %>/components',
'<%= yeoman.target %>/scripts'
]
}]
},
dist: {
files: [
{
dot: true,
src: '<%= yeoman.dist %>'
}
]
},
docs: {
files: [
{
dot: true,
src: '<%= yeoman.docs %>'
}
]
},
server: {
files: [
{
dot: true,
src: '<%= yeoman.target %>/.tmp'
}
]
}
},
// Automatically inject Bower components into the app
wiredep: {
app: {
src: ['<%= yeoman.target %>/index.html'],
ignorePath: /\.\.\//
},
sass: {
src: ['<%= yeoman.target %>/styles/{,*/}*.{scss,sass}'],
ignorePath: /(\.\.\/){1,2}bower_components\//
}
},
// Compiles Sass to CSS and generates necessary files if requested
compass: {
options: {
sassDir: '<%= yeoman.sources %>',
cssDir: '<%= yeoman.target %>/css',
generatedImagesDir: '<%= yeoman.target %>/images',
imagesDir: '<%= yeoman.sources %>/components/assets',
javascriptsDir: '<%= yeoman.sources %>/scripts',
fontsDir: '<%= yeoman.target %>/fonts',
importPath: '<%= yeoman.target %>/bower_components',
httpImagesPath: '/images',
httpGeneratedImagesPath: '/images',
httpFontsPath: '/styles/fonts',
relativeAssets: false,
assetCacheBuster: false,
sourcemap: true,
raw: 'Sass::Script::Number.precision = 10\n'
},
dist: {
options: {
environment: 'production'
}
}
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['last 1 version']
},
target: {
files: [{
expand: true,
cwd: '<%= yeoman.target %>/css',
src: '**/*.css',
dest: '<%= yeoman.target %>/css'
}]
}
},
// Renames files for browser caching purposes
filerev: {
dist: {
src: [
'<%= yeoman.target %>/scripts/{,*/}*.js',
'<%= yeoman.target %>/styles/{,*/}*.css',
'<%= yeoman.target %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
'<%= yeoman.target %>/styles/fonts/*'
]
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
html: ['<%= yeoman.target %>/index.html', '<%= yeoman.target %>/owa-mail.html', '<%= yeoman.target %>/owa-doc-setting.html', '<%= yeoman.target %>/owa-doc-upload-2016.html', '<%= yeoman.target %>/owa-doc-upload-2013.html', '<%= yeoman.target %>/owa-doc-upload-failed.html'],
options: {
dest: '<%= yeoman.target %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['concat', 'cssmin'],
copy: ['concat']
},
post: {}
}
}
}
},
// Performs rewrites based on filerev and the useminPrepare configuration
usemin: {
html: ['<%= yeoman.target %>/{,*/}*.html'],
css: ['<%= yeoman.target %>/css/{,*/}*.css'],
options: {
dirs: ['<%= yeoman.target %>'],
assetsDirs: [
'<%= yeoman.target %>',
'<%= yeoman.target %>/images',
'<%= yeoman.target %>/styles'
]
}
},
// The following *-min tasks will produce minified files in the dist folder
// By default, your `index.html`'s <!-- Usemin block --> will take care of
// minification. These next options are pre-configured if you do not wish
// to use the Usemin blocks.
cssmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.target %>/styles',
src: ['*.css', '!*.min.css'],
dest: '<%= yeoman.target %>/styles',
ext: '.min.css'
}]
}
},
//refer: https://babeljs.io/docs/en/options
babel: {
options: {
sourceMap: true,
presets: ['@babel/preset-env'],
sourceType: 'module', //no strict mode 3 option: "script" | "module" | "unambiguous
exclude: ['<%= yeoman.sources %>/scripts/lib']
},
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.sources %>',
dest: '<%= yeoman.target %>',
src: [
'**/*.js'
]
}]
}
},
//append features if necessary : https://github.com/zloirock/core-js#features, or: target\node_modules\core-js\modules\
polyfill: {
options: {
uglify: true,
features: ['es5', 'es6.object.assign', 'es7.array.includes', 'es6.array.of', 'es6.array.find'],
output: '<%= yeoman.target %>/scripts/lib/polyfill.js'
}
},
uglify: {
options: {
mangle: true
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true,
removeOptionalTags: true
},
files: [{
expand: true,
cwd: '<%= yeoman.target %>',
src: ['*.html', 'views/{,*/}*.html'],
dest: '<%= yeoman.target %>'
}]
}
},
// ng-annotate tries to make the code safe for minification automatically
// by using the Angular long form for dependency injection.
ngAnnotate: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.target %>/.tmp/concat/scripts/',
src: '*.js',
dest: '<%= yeoman.target %>/.tmp/concat/scripts/'
}]
}
},
// Copies remaining files to places other tasks can use
copy: {
target: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.sources %>',
dest: '<%= yeoman.target %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'views/{,*/}*.html',
'images/{,*/}*.{webp}',
'styles/fonts/{,*/}*.*'
]
},
{
expand: true,
cwd: '<%= yeoman.sources %>/office-web-addin',
dest: '<%= yeoman.target %>',
src: ['**/*.html']
},
// {
// expand: true,
// cwd: '<%= yeoman.sources %>',
// dest: '<%= yeoman.target %>',
// src: ['**/*.js']
// },
{
expand: true,
cwd: '<%= yeoman.sources %>/components/themes',
dest: '<%= yeoman.target %>/components/themes',
src: ['**']
},
{
expand: true,
cwd: '<%= yeoman.sources %>/images',
dest: '<%= yeoman.target %>/images',
src: ['**']
},
{
expand: true,
cwd: '<%= yeoman.sources %>/resources',
dest: '<%= yeoman.target %>/resources',
src: ['**/*.json', '**/*.jpg']
}]
},
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.target %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'.htaccess',
'*.html',
'views/{,*/}*.html',
'images/{,*/}*.{webp}',
'styles/fonts/{,*/}*.*',
'scripts/**/*.js',
'styles/*.css',
]
},
{
expand: true,
cwd: '<%= yeoman.target %>/images',
dest: '<%= yeoman.dist %>/images',
src: ['**']
},
{
expand: true,
cwd: '<%= yeoman.target %>/bower_components/xcomponent-widgets/pdfViewer/',
dest: '<%= yeoman.dist %>/bower_components/xcomponent-widgets/pdfViewer/',
src: ['**/*.*']
},
{
expand: true,
cwd: '<%= yeoman.target %>/bower_components/xcomponent-widgets/components/object-display-storyline/TimelineJS/build/css',
dest: '<%= yeoman.dist %>/styles',
src: ['**']
},
{
expand: true,
cwd: '<%= yeoman.target %>/bower_components/xcomponent-widgets/TimelineJS/',
dest: '<%= yeoman.dist %>/bower_components/xcomponent-widgets/TimelineJS/',
src: ['**/*.*']
},
{
expand: true,
cwd: '<%= yeoman.target %>/bower_components/pdf-tron-webviewer/',
dest: '<%= yeoman.dist %>/bower_components/pdf-tron-webviewer/',
src: ['**/*.*']
},
{
expand: true,
cwd: '<%= yeoman.target %>/resources',
dest: '<%= yeoman.dist %>/resources',
src: ['**/*.json', '**/*.jpg']
}
// We can add more resources to dist here, like the environments folder (refer to xgov)
]
}
},
//create template.js file. Contain all template files.
ngtemplates: {
target: {
cwd: '<%= yeoman.sources %>/components/',
src: ['**/*-template.html', '**/*-tpl.html', '**/template/*.html', '**/templates/*.html'],
dest: '<%= yeoman.target %>/xecm-webapp/template.js',
options: {
module: "xecm-webapp",
url: function (url) {
var urlSp = url.split("/");
var p1 = urlSp.pop();
var p2 = urlSp.pop();
if (p2 == 'template' || p2 == 'templates')
return p2 + '/' + p1;
else
return p1;
},
htmlmin: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true, // Only if you don't use comment directives!
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
}
}
},
target3: {
cwd: '<%= yeoman.sources %>/components/',
src: ['**/office-auth-tpl.html'],
dest: '<%= yeoman.target %>/xecm-webapp/template3.js',
options: {
module: "owa-doc-setting",
url: function (url) {
var urlSp = url.split("/");
var p1 = urlSp.pop();
var p2 = urlSp.pop();
if (p2 == 'template' || p2 == 'templates')
return p2 + '/' + p1;
else
return p1;
},
htmlmin: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
removeComments: true, // Only if you don't use comment directives!
removeEmptyAttributes: true,
removeRedundantAttributes: true,
removeScriptTypeAttributes: true,
removeStyleLinkTypeAttributes: true
}
}
}
}
});
// Task to build dev and dist folders
grunt.registerTask('build', [
'clean', // Clean all folders
'copy:target',
'ngtemplates', //Generate templateCache
'compass',
'autoprefixer',
'wiredep',
'babel',
'polyfill',
'useminPrepare', //Reads HTML for usemin blocks to enable smart builds that automatically concat, minify and revision files.
'concat',
'cssmin',
'ngAnnotate',
'uglify',
'filerev',
'usemin',
'htmlmin',
'copy:dist',
'appcache:all',
'replace:manifest'
]);
};
in the index.html file I have this part for building of the css
<!-- build:css styles/xxx-styles.css -->
<link rel="stylesheet" href="css/components/document-basket-display-list/basket-document-display/basket-document-display.css" />
<link rel="stylesheet" href="css/components/pdf-tron-web-viewer/pdf-tron-web-viewer.css" />
<!-- endbuild -->
So when I am on my dev server I can see that this css files are existing but on the prod server whole css code is put into one file. But I need also to have this <link rel="stylesheet" href="css/components/pdf-tron-web-viewer/pdf-tron-web-viewer.css" />
css file to exist on it's own also on my prod server and I am not able to do that.
I tried putting the linking of the css file outside of start and endbuild comments for the css part.
build:css styles/xxx.css
and endbuild