增量减少构建

Phi*_*ler 13 javascript gulp gulp-less

在我的办公室,我们使用gulp来构建我们较少的文件.我想改进构建任务,因为它花了一秒钟来构建我们最近工作的大型项目.想法是缓存文件,只传递更改的文件.所以我从谷歌开始,发现javascript的增量版本,并认为很容易以较少的方式重写它们.这是我开始使用的那个:https://github.com/gulpjs/gulp/blob/master/docs/recipes/incremental-builds-with-concatenate.md

经过几次不成功的尝试后,我最终得到了以下代码(使用最新的bootstrap发行版测试):

var gulp            = require('gulp');
var less            = require('gulp-less');
var concat          = require('gulp-concat');
var remember        = require('gulp-remember');
var cached          = require('gulp-cached');

var fileGlob = [
    './bootstrap/**/*.less',
    '!./bootstrap/bootstrap.less',
    '!./bootstrap/mixins.less'
];

gulp.task('less', function () {
    return gulp.src(fileGlob)
        .pipe(cached('lessFiles'))
        .pipe(remember('lessFiles'))
        .pipe(less())
        .pipe(gulp.dest('output'));
});

gulp.task('watch', function () {
    var watcher = gulp.watch(fileGlob, ['less']);
    watcher.on('change', function (e) {
        if (e.type === 'deleted') {
            delete cached.caches.scripts[e.path];
            remember.forget('lessFiles', e.path);
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

但是这只传递了更改的文件,并且由于缺少变量定义,编译器失败了.如果我在较少的任务之前管道concat插件,gulp卡在一个(看似)无限循环中.

gulp.task('less', function () {
    return gulp.src(fileGlob)
        .pipe(cached('lessFiles'))
        .pipe(remember('lessFiles'))
        .pipe(concat('main.less')
        .pipe(less())
        .pipe(gulp.dest('output'));
});
Run Code Online (Sandbox Code Playgroud)

有没有人使用这些插件或设法以其他方式创建增量较少的构建.这是一个(杂乱的)github存储库,用于测试:https://github.com/tuelsch/perfect-less-build

PS:我打算加入linting,sourcemaps,minification,evtl.缓存清除和autoprefixer稍后.

Str*_*ior 19

像Ashwell一样,我发现使用导入确保所有LESS文件都可以访问他们需要的变量和mixin是很有用的.我还使用带导入的LESS文件进行捆绑.这有一些优点:

  1. 我可以利用LESS的功能来执行复杂的操作,例如覆盖变量值以生成多个主题,或者将类添加到另一个LESS文件中的每个规则.
  2. 不需要concat插件.
  3. 像Web Essentials for Visual Studio这样的工具可以提供语法帮助和输出预览,因为每个LESS文件都完全能够自己呈现.

你想要导入变量,混合等等,但你不想实际输出另一个文件的全部内容,你可以使用:

@import (reference) "_colors.less";
Run Code Online (Sandbox Code Playgroud)

经过几天的努力,我终于能够获得一个增量构建,正确地重建依赖于我更改的LESS文件的所有对象.我在这里记录了结果.这是最终的gulpfile:

/*
 * This file defines how our static resources get built.
 * From the StaticCommon root folder, call "gulp" to compile all generated
 * client-side resources, or call "gulp watch" to keep checking source 
 * files, and rebuild them whenever they are changed. Call "gulp live" to 
 * do both (build and watch).
 */

/* Dependency definitions: in order to avoid forcing everyone to have 
 * node/npm installed on their systems, we are including all of the 
 * necessary dependencies in the node_modules folder. To install new ones,
 * you must install nodejs on your machine, and use the "npm install XXX" 
 * command. */
var gulp = require('gulp');
var less = require('gulp-less');
var LessPluginCleanCss = require('less-plugin-clean-css'),
    cleanCss = new LessPluginCleanCss();
var sourcemaps = require('gulp-sourcemaps');
var rename = require('gulp-rename');
var cache = require('gulp-cached');
var progeny = require('gulp-progeny');
var filter = require('gulp-filter');
var plumber = require('gulp-plumber');
var debug = require('gulp-debug');

gulp.task('less', function() {
    return gulp
        // Even though some of our LESS files are just references, and 
        // aren't built, we need to start by looking at all of them because 
        // if any of them change, we may need to rebuild other less files.
        .src(
        ['Content/@(Theme|Areas|Css)/**/*.less'],
        { base: 'Content' })
        // This makes it so that errors are output to the console rather 
        // than silently crashing the app.
        .pipe(plumber({
            errorHandler: function (err) {
                console.log(err);
                // And this makes it so "watch" can continue after an error.
                this.emit('end');
            }
        }))
        // When running in "watch" mode, the contents of these files will 
        // be kept in an in-memory cache, and after the initial hit, we'll
        // only rebuild when file contents change.
        .pipe(cache('less'))
        // This will build a dependency tree based on any @import 
        // statements found by the given REGEX. If you change one file,
        // we'll rebuild any other files that reference it.
        .pipe(progeny({
            regexp: /^\s*@import\s*(?:\(\w+\)\s*)?['"]([^'"]+)['"]/
        }))
        // Now that we've set up the dependency tree, we can filter out 
        // any files whose
        // file names start with an underscore (_)
        .pipe(filter(['**/*.less', '!**/_*.less']))
        // This will output the name of each LESS file that we're about 
        // to rebuild.
        .pipe(debug({ title: 'LESS' }))
        // This starts capturing the line-numbers as we transform these 
        // files, allowing us to output a source map for each LESS file 
        // in the final stages.
        // Browsers like Chrome can pick up those source maps and show you 
        // the actual LESS source line that a given rule came from, 
        // despite the source file's being transformed and minified.
        .pipe(sourcemaps.init())
        // Run the transformation from LESS to CSS
        .pipe(less({
            // Minify the CSS to get rid of extra space and most CSS
            // comments.
            plugins: [cleanCss]
        }))
        // We need a reliable way to indicate that the file was built
        // with gulp, so we can ignore it in Mercurial commits.
        // Lots of css libraries get distributed as .min.css files, so
        // we don't want to exclude that pattern. Let's try .opt.css 
        // instead.
        .pipe(rename(function(path) {
            path.extname = ".opt.css";
        }))
        // Now that we've captured all of our sourcemap mappings, add
        // the source map comment at the bottom of each minified CSS 
        // file, and output the *.css.map file to the same folder as 
        // the original file.
        .pipe(sourcemaps.write('.'))
        // Write all these generated files back to the Content folder.
        .pipe(gulp.dest('Content'));
});

// Keep an eye on any LESS files, and if they change then invoke the 
// 'less' task.
gulp.task('watch', function() {
    return gulp.watch('Content/@(Theme|Areas|Css)/**/*.less', ['less']);
});

// Build things first, then keep a watch on any changed files.
gulp.task('live', ['less', 'watch']);

// This is the task that's run when you run "gulp" without any arguments.
gulp.task('default', ['less']);
Run Code Online (Sandbox Code Playgroud)

我们现在可以简单地运行gulp live一次构建所有LESS文件,然后允许每个后续更改只构建依赖于已更改文件的那些文件.