现在稍具规模的项目中已经很少裸写CSS了。
流行的css预处理器有sass、less、stylus。
因为对Ruby比较熟悉,很早就了解了Sass。所以目前我负责的几个项目中均选用了sass。
我建议先了解一下这几个预处理器的异同和各自的优势。根据项目情况进行选择。三者的语法都不是很复杂。有经验的前端开发人员都可以很快上手。
Sass最初是用Ruby编写的。最大的问题就是编译速度比较慢。然后就有了Sass的c++版编译器本和node-sass。虽然速度不再是问题了。但是安装编译有比较麻烦。使用Windows的环境的小伙伴们更是觉得麻烦。因为需要安装Visual Studio用于编译。幸好我的笔记本上常备VS。于是我先在本机编译好。然后写了端Grunt脚本配合编译出来的sassc.exe填上了这个自己挖的坑。
脚本中先判断系统,如果是win32则使用sassc.exe编译,否则使用node-sass。
用grunt.event.on('watch'…)对文件变化监控,当发生sass文件创建和修改事件时,调用sassc进行编译。
module.exports = function(grunt) {
var path = require("path"),
fs = require("fs"),
isWin = /^win/.test(process.platform);
var config = {
watch: {
sass: {
files: ["src/sass/**/*.scss"],
tasks: ["sass:dev", "notify:sass", "cssmin"]
},
css: {
files: ["*.css", "!*.min.css"],
tasks: ["cssmin"]
},
coffee: {
files: ["src/scripts/**/*.coffee"],
tasks: ["coffee:dev", "notify:coffee"]
}
}
};
grunt.log.writeln("Platform:" + process.platform);
var defaultTasks = ["coffee"],
sassOpts = {
sassStyle: "compact"
};
if (isWin) {
/**
* When running under Windows, use sassc.exe
* which is much faster than ruby version
*/
var useSourceMap = false;
config.watch.sass.tasks.shift();
var exec = require("child_process").exec;
grunt.event.on("watch", function(action, filepath, style) {
if (style == "sass") style = "compact"
if (action == "changed" && path.extname(filepath) == ".scss") {
grunt.log.writeln("compiling: " + filepath);
var csspath = "www/resource/css/app/" + path.basename(filepath).replace(/\.scss$/, ".css"),
scssOpt = "-t " + (style || sassOpts.sassStyle) + " " + (useSourceMap ? "-m " : " "),
cmd = "sassc.exe " + scssOpt + " "" + filepath + "" "" + csspath + """;
grunt.log.writeln(cmd);
exec(cmd, function(error, stdout, stderr) {
if (stdout) grunt.log.writeln(" stdout: " + stdout);
if (stderr) grunt.log.writeln(" stderr: " + stderr);
grunt.log.writeln("Done!");
});
}
});
grunt.registerTask("sassc", function() {
fs.readdirSync("src/sass").forEach(function(name) {
if (name.indexOf(".scss") < 0 || name.indexOf("variables") >= 0) return;
var path = "src/sass/" + name;
grunt.event.emit("watch", "changed", path, "compressed");
});
});
defaultTasks.push("sassc");
} else {
/**
* fallback to grunt-contrib-sass
*/
config.sass = {
options: {
sourcemap: "auto",
style: "compact"
},
dev: {
expand: true,
cwd: "src/sass",
src: "**/*.scss",
dest: "www/resource/css/app",
ext: ".css",
}
};
grunt.loadNpmTasks("grunt-contrib-sass");
defaultTasks.push("sass");
}
};