使用Gulpjs编译客户端Jade模板

4

我试图将所有的.jade模板编译成一个单独的js文件,使用的是Gulpjs和gulp-jade、gulp-concat。

我可以得到单个文件,但问题在于所有函数都具有相同的名称,它们都被称为"template"。

foo.jade:

.fooDiv
    h1 Foo here

foo2.jade:

.foo2Div
    h1 Foo2 here

Gulp文件:

gulp.src("templates/**/*.jade")
    .pipe(jade({client: true}))
    .pipe(concat("templates.js"))
    .pipe(gulp.dest("../website/templates"))

那将会输出这样的一个文件:
function template(locals) {
    var buf = [];
    var jade_mixins = {};

    buf.push("<div class=\"fooDiv\"><h1>Foo here</h1></div>");;return buf.join("");
}
function template(locals) {
    var buf = [];
    var jade_mixins = {};

    buf.push("<div class=\"foo2Div\"><h1>Foo2 here</h1></div>");;return buf.join("");
}

我希望的是类似这样的功能:

function foo(locals) {
    var buf = [];
    var jade_mixins = {};

    buf.push("<div class=\"fooDiv\"><h1>Foo here</h1></div>");;return buf.join("");
}
function foo2(locals) {
    var buf = [];
    var jade_mixins = {};

    buf.push("<div class=\"foo2Div\"><h1>Foo2 here</h1></div>");;return buf.join("");
}

有没有办法可以做到这一点?我已经搜索了相当长的时间,但没有找到任何东西。

干杯。 Caio

编辑:

Jade现在接受jade.compileClient的name选项。 在此处查看:https://github.com/jadejs/jade/blob/master/jade.js


4
将编辑内容作为答案添加,并提到您是否以动态方式更改了name值可能会很有用。 - Sebastian Thomas
1
@SebastianThomas 我发现这个评论很有帮助。我已经将这个解决方案发布为答案。 - coderfin
3个回答

8

看起来 jade.compileClient 硬编码了 function template(locals),并且没有更改函数名称的选项。 https://github.com/visionmedia/jade/blob/master/lib/jade.js

这有点 hacky,但是您可以在 jade 编译之后修改编译脚本的内容。

var through = require('through2');
var path = require('path');

function modify() {
  function transform(file, enc, callback) {
    if (!file.isBuffer()) {
      this.push(file);
      callback();
      return;
    }
    var funcName = path.basename(file.path, '.js');
    var from = 'function template(locals) {';
    var to = 'function ' + funcName + '(locals) {';
    var contents = file.contents.toString().replace(from, to);
    file.contents = new Buffer(contents);
    this.push(file);
    callback();
  }
  return through.obj(transform);
}

gulp.src("templates/**/*.jade")
    .pipe(jade({client: true}))
    .pipe(modify())
    .pipe(concat("templates.js"))
    .pipe(gulp.dest("../website/templates"));

你可以根据file.path更改funcName,以便在多个子目录中使用jade模板。

运行得非常好! - aditya_medhe
如果您使用pugjs,应该使用name选项而不是这个hacky解决方案。https://pugjs.org/api/reference.html - Shuhei Kagawa
感谢@ShuheiKagawa,您有关于如何在客户端模板中使用它的任何指针吗?我正在使用gulp和gulp-pug将模板预编译为js函数,然后从客户端代码中调用它们(通过AJAX传递JSON作为本地变量)以呈现页面。 - aditya_medhe
gulp-pug的选项会传递给pug。所以你可能只需在gulp-pug中添加name选项即可。 - Shuhei Kagawa
啊,但是这样就不能为每个文件设置“名称”了。现在我明白你的意思了... - Shuhei Kagawa

3
下面的代码片段来自我发现非常有帮助的this comment评论。
gulp.task('strings', function() {
    return gulp.src('media/templates/*.jade')
        .pipe(foreach(function(stream,file){
            var filename = path.basename(file.path);
            filename = filename.split('.')[0]
            return stream
                .pipe(jade({
                    client: true,
                    name: filename
                }));
        }))
        .pipe(concat('all.js'))
        .pipe(gulp.dest('media/strings/'))
});

使用gulp-foreach可以获取当前文件的名称,更改它,然后将其传递给jade。之后您可以像往常一样执行其他操作,例如concat


2

我找到了一个对我有效的优雅解决方案。

基本上,在您的主脚本(在您的.html文件中生成的jade脚本之前加载的脚本)中,您有一个数组,将保存模板()函数返回的值,比如var document = [];

然后使用gulp-insert将脚本包装为'(function() {';\n;document.push(template()); })();,然后像您已经做过的那样连接这些脚本。

现在,按需弹出document[]数组,其中包含每个template()调用的计算值!

我使用LiveScript进行构建,但以下是转换为JavaScript版本:

var jade   = require('gulp-jade');
var concat = require('gulp-concat');
var insert = require('gulp-insert');
gulp.task('jade-to-js', function(){
  return gulp.src('src/node/jade/*.jade')
  .pipe(jade({client: true}))
  .pipe(insert.wrap('(function() {', '\n;document.push(template()); })();')
  .pipe(concat('bundle.js'))
  .pipe(gulp.dest('src/js/'))
});

有没有一种方法可以在bundle.js的开头声明数组? - Ian Warburton
@Ian Warburton - 我所做的就是在包含bundle.js之前,简单地将一个带有文档数组的脚本包含进去 - 这样就可以了 :) - qwe123asdA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接