1. 程式人生 > >使用gulp實時編譯sass/sass

使用gulp實時編譯sass/sass

背景

在我們新開始的專案中,我們打算使用scss來作為我們的樣式書寫語言。同時,所有的sass/scss檔案經過編譯轉化成css檔案後要存放到跟scss/sass檔案相同的目錄下。整個前端團隊已經有實時的程式碼編譯構建工具,那麼我們只需要書寫自己的實時scss/sass構建工具,生成對應的css檔案後,團隊的實時構建工具也會觸發編譯,做打包構建處理。

第三方包選型

基於gulp的sass/scss編譯工具有:基於node-sass的gulp-sass以及基於Ruby的gulp-ruby-sass。但是為了免得再安裝Ruby以及一些特定的原因(gulp-ruby-sass與gulp-sass),我選擇了使用gulp-sass。

執行方式及執行效果

你需要全域性安裝gulp:npm install -g gulp,你需要在你專案的根目錄下新建gulpfile.js檔案。執行方式就是直接在命令列專案根目錄下執行:gulp即可。編譯成功後會給出編譯成功的提示(當然也可以配置關閉該提示),編譯失敗則會給出編譯失敗的提示,並且會在命令列控制檯打印出詳細的錯誤資訊,同時,錯誤提示的時候會帶有音效。在編譯之後的css程式碼,我們使用了cssbeautify對其進行了格式化,同時,你還可以針對自己的需求對其進行語法檢查等。

程式碼

最終的程式碼在下面。需要注意的是,你要在第19行自己指定需要編譯的scss/sass檔案所在的目錄以及這些目錄下不需要編譯的子目錄,該目錄下全部需要編譯就不指定陣列第二項。
如果所有目錄下的scss/sass都需要編譯則指定watchFilesPath為:
var watchFilesPath = ‘*.{sass,sass}';

完整的程式碼:
var path = require('path');

var logSymbols = require('log-symbols');
var gulp = require('gulp');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var notify = require('gulp-notify');
var stripCssComments = require('gulp-strip-css-comments');
var plumber = require('gulp-plumber');
var gutil = require('gulp-util');
var cssbeautify = require('cssbeautify');
var mapStream = require('map-stream');
var colors = require('colors');
var minimatch = require('minimatch');

var execSync = require('child_process').execSync;
var projectPath = execSync('git rev-parse --show-toplevel').toString().trim().replace(/\\n/g);

// 指定要編譯的目錄
var watchFilesPath = ['**/{pc,mobile}/**/*.{scss,sass}', '!**/mobile/hotcss/**'];

// 編譯成功通知開關
var successNotify = true;


// 將.scss/.sass檔案實時轉變為.css檔案
gulp.task('styles', function() {
    return gulp.src(watchFilesPath)
        .pipe(plumber({
            errorHandler: reportError
        }))
        .pipe(mapStream(function(file, cb) {
            logPath(file);
            cb(null, file);
        }))
        .pipe(sass())
        // 去掉css註釋
        .pipe(stripCssComments())
        // auto prefix
        .pipe(autoprefixer('last 2 version', 'safari 5', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
        // css格式化、美化(因為有f2ehint,故在此不再做語法等的檢查與修復)
        .pipe(mapStream(function(file, cb) {
            // 新增css程式碼的格式化
            var cssContent = file.contents.toString();

            if (/\.(css|sass|scss)/.test(path.extname(file.path))) {
                file.contents = new Buffer(cssbeautify(cssContent, {
                    indent: '    ',
                    openbrace: 'end-of-line',
                    autosemicolon: true
                }));
            }

            cb(null, file);
        }))
        // 將編譯後的.css檔案存放在.scss檔案所在目錄下
        .pipe(gulp.dest(function(file) {
            return './';
        }))
        // 編譯成功後的提示(頻繁提示會有點煩人,可將successNotify設定為:false關閉掉)
        .pipe(notify(function(file) {
            return successNotify && 'scss/sass編譯成功!';
        }));
});

gulp.task('watch', function() {
    // Watch .scss files
    gulp.watch(watchFilesPath, ['styles']);
});

// 監聽任務時先執行一次編譯
gulp.task('default', function() {
    gulp.start('styles', 'watch');
});

/**
    ########### helpers ###########
*/

function logPath(file) {
    console.log(logSymbols.info + ' 正在編譯:' + file.path.gray);
}

function reportError(error) {
    var lineNumber = (error.lineNumber) ? 'LINE ' + error.lineNumber + ' -- ' : '';

    notify({
        title: '編譯失敗 [' + error.plugin + ']',
        message: lineNumber + '具體錯誤請看控制檯!',
        sound: 'Sosumi' // See: https://github.com/mikaelbr/node-notifier#all-notification-options-with-their-defaults
    }).write(error);

    gutil.beep();

    // Pretty error reporting
    var report = '';
    var chalk = gutil.colors.white.bgRed;

    report += chalk('TASK:') + ' [' + error.plugin + ']\n';
    report += chalk('PROB:') + ' ' + error.message + '\n';
    if (error.lineNumber) {
        report += chalk('LINE:') + ' ' + error.lineNumber + '\n';
    }
    if (error.fileName) {
        report += chalk('FILE:') + ' ' + error.fileName + '\n';
    }
    console.error(report);

    // Prevent the 'watch' task from stopping
    this.emit('end');
}
這樣你就可以愉快的書寫scc/sass程式碼了。