如何连接和缩小多个 CSS 和 JavaScript 文件与 Grunt.js (0.3.x)

注意: 这个问题只与 Grunt 0.3. x 有关,并且留作参考。有关最新的 Grunt 1.x 版本的帮助,请参阅我在这个问题下面的评论。

我目前正在尝试使用 Grunt.js 设置一个自动构建过程,首先连接,然后缩小 CSS 和 JavaScript 文件。

我已经能够成功地连接和缩小我的 JavaScript 文件,虽然每次我运行 grunt,它似乎只是附加到文件,而不是覆盖它们。

至于缩小甚至连接 CSS,我还不能这样做!

在粗重的 CSS 模块方面,我尝试过使用 consolidate-cssgrunt-csscssmin,但没有用。我不知道怎么使用它们!

我的目录结构如下(作为典型的 node.js 应用程序) :

  • 应用程序
  • Grunt.js
  • /public/index.html
  • /public/css/[各种 css 文件]
  • /public/js/[各种 javascript 文件]

下面是我的 grunt.js 文件目前在应用程序的根文件夹中的样子:

module.exports = function(grunt) {


// Project configuration.
grunt.initConfig({
pkg: '<json:package.json>',
concat: {
dist: {
src: 'public/js/*.js',
dest: 'public/js/concat.js'
}
},
min: {
dist: {
src: 'public/js/concat.js',
dest: 'public/js/concat.min.js'
}
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
node: true
},
globals: {
exports: true,
module: false
}
},
uglify: {}
});


// Default task.
grunt.registerTask('default', 'concat min');


};

总结一下,我有两个问题需要帮助:

  1. 如何连接和缩小所有我的 css 文件在文件夹 /public/css/到一个文件,说 main.min.css
  2. 为什么 grunt.js 一直在 /public/js/下附加连接的和缩小的 javascript 文件 concat.jsconcat.min.js,而不是在每次运行命令 grunt时覆盖它们?

2016年7月5日更新-从 Grunt 0.3. x 升级到 Grunt 0.4. x 或1. x

Grunt.js已经移动到 Grunt 0.4.x中的一个新结构(该文件现在称为 Gruntfile.js)。请参阅我的开源项目 Grunt.js 骷髅,以获得为 Grunt 1.x设置构建过程的帮助。

Grunt 0.4.x移动到 Grunt 1.x

111454 次浏览

concat.js is being included in the concat task's source files public/js/*.js. You could have a task that removes concat.js (if the file exists) before concatenating again, pass an array to explicitly define which files you want to concatenate and their order, or change the structure of your project.

If doing the latter, you could put all your sources under ./src and your built files under ./dest

src
├── css
│   ├── 1.css
│   ├── 2.css
│   └── 3.css
└── js
├── 1.js
├── 2.js
└── 3.js

Then set up your concat task

concat: {
js: {
src: 'src/js/*.js',
dest: 'dest/js/concat.js'
},
css: {
src: 'src/css/*.css',
dest: 'dest/css/concat.css'
}
},

Your min task

min: {
js: {
src: 'dest/js/concat.js',
dest: 'dest/js/concat.min.js'
}
},

The build-in min task uses UglifyJS, so you need a replacement. I found grunt-css to be pretty good. After installing it, load it into your grunt file

grunt.loadNpmTasks('grunt-css');

And then set it up

cssmin: {
css:{
src: 'dest/css/concat.css',
dest: 'dest/css/concat.min.css'
}
}

Notice that the usage is similar to the built-in min.

Change your default task to

grunt.registerTask('default', 'concat min cssmin');

Now, running grunt will produce the results you want.

dest
├── css
│   ├── concat.css
│   └── concat.min.css
└── js
├── concat.js
└── concat.min.js

I agree with above answer. But here is another way of CSS compression.

You can concat your CSS by using YUI compressor:

module.exports = function(grunt) {
var exec = require('child_process').exec;
grunt.registerTask('cssmin', function() {
var cmd = 'java -jar -Xss2048k '
+ __dirname + '/../yuicompressor-2.4.7.jar --type css '
+ grunt.template.process('/css/style.css') + ' -o '
+ grunt.template.process('/css/style.min.css')
exec(cmd, function(err, stdout, stderr) {
if(err) throw err;
});
});
};

I want to mention here a very, VERY, interesting technique that is being used in huge projects like jQuery and Modernizr for concatenate things.

Both of this projects are entirely developed with requirejs modules (you can see that in their github repos) and then they use the requirejs optimizer as a very smart concatenator. The interesting thing is that, as you can see, nor jQuery neither Modernizr needs on requirejs to work, and this happen because they erase the requirejs syntatic ritual in order to get rid of requirejs in their code. So they end up with a standalone library that was developed with requirejs modules! Thanks to this they are able to perform cutsom builds of their libraries, among other advantages.

For all those interested in concatenation with the requirejs optimizer, check out this post

Also there is a small tool that abstracts all the boilerplate of the process: AlbanilJS

You don't need to add the concat package, you can do this via cssmin like this:

cssmin : {
options: {
keepSpecialComments: 0
},
minify : {
expand : true,
cwd : '/library/css',
src : ['*.css', '!*.min.css'],
dest : '/library/css',
ext : '.min.css'
},
combine : {
files: {
'/library/css/app.combined.min.css': ['/library/css/main.min.css', '/library/css/font-awesome.min.css']
}
}
}

And for js, use uglify like this:

uglify: {
my_target: {
files: {
'/library/js/app.combined.min.js' : ['/app.js', '/controllers/*.js']
}
}
}

I think may be more automatic, grunt task usemin take care to do all this jobs for you, only need some configuration:

https://stackoverflow.com/a/33481683/1897196