我使用了一堆静态站点生成器,但 gulp 是一种更好的方法,因为它是如此模块化。我想知道是否有一个插件可以执行静态站点生成器的某些功能。在我看来,所缺少的只是将目录中的文件转换为 json 数据结构,以便在网站上的菜单中使用。
3 回答
如果您只想生成一个 .json 结构并使用 Gulp 将其添加到文件中,您可以通过以下几种方式之一执行此操作。前两个使用纯 Gulp 技术:
through
您可以使用or编写一个流插件through2
,它基本上必须一次构建一个文件的数据结构,然后在第二个操作中,将在最后创建(即push()
orqueue()
)一个文件您可以使用Highland管道
.reduce()
将文件传输到数据结构,然后.map()
将结果传输到文件,也许.merge()
使用原始流
在这两种情况下,您都需要生成的新vinyl
文件具有适当的.base
and .path
,而您的插件实际上并不知道,因为您正在创建的文件尚不存在。因此,您的代码必须构成一个虚假的绝对路径,以便gulp.dest()
将其放在正确的位置。
第三种技术是编写一个Metalsmith插件,它看起来像这样:
function generate_json(files, smith, done) {
var menu = {};
Object.keys(files).forEach(function(path) {
var file = files[path];
if (path.slice(-5)===".html") {
menu[path] = ... // whatever you want to store about `file`
}
});
files["path/to/menu.json"] = { contents: new Buffer(JSON.stringify(menu)) };
done();
}
虽然不比其他方法所需的代码短多少,但您需要了解的内容少得多才能正确执行。只要确保如果你有错误,你打电话done(err)
是为了传递错误。
如果您想将此插件与 Gulp 管道结合使用,可以使用Gulpsmith像这样包装它:
gulp.src(...)
.pipe( things() )
.pipe( gulpsmith().use(generate_json) )
.pipe( other_stuff() )
.pipe( gulp.dest(...);
Gulp 确实比 Metalsmith 有一定的优势。遗憾的是,易于编写插件并不是其中之一。从 Gulp 插件创建新文件比它应该的更难,正确的错误处理也是如此。流式传输方法与需要跨文件操作的静态站点的性质之间也存在强烈的阻抗不匹配。
例如,如果您想在创建后将菜单嵌入到每个 .html 页面中,您将需要一个更复杂的 Gulp 插件,因为当您的插件“看到”所有文件时,它们会“进入下游”,否则,您必须坚持使用它们,然后在完成后再次将它们流出来。在 Metalsmith 插件中,您只需在生成菜单后添加第二个循环,以再次返回文件以就地插入数据。你不需要做任何事情来传递你没有做任何事情的文件。
对于这类任务,Metalsmith 插件 API 明显优于 Gulp。但是对于可以单独处理流文件的任务,请使用现有的 Gulp 插件。
基本上,Metalsmith 确实是静态站点生成器的 Gulp,而 Gulp 是流式构建系统的 Gulp。您可以使用 Gulpsmith 结合两者的优势。
(顺便说一下,根据您的实际任务,您可能会发现一些现有的 Metalsmith 插件可以完成全部或部分工作。例如,metalsmith-collections
插件为匹配某些模式的文件创建索引,有一个metalsmith-title
将 HTML 标题提取到标题属性, ETC。)
是的,您可以在 gulp 中进行静态生成。
您可能需要的插件比您想象的要少。计数可能会向下舍入为零。
考虑一下你可以用 gulp 做些什么而不用插件:
var gulp = require('gulp'),
browserify = require('browserify');
gulp.task('browserify', function(callback) {
browserify('app.js').bundle()
.pipe(fs.createWriteStream('dist/app.js')
.on('close', callback); // why? read on...
});
不需要存在太多的 gulp 插件。他们将一些原始模块改编为gulp.src
和之间使用的乙烯基对象流gulp.dest
,但乙烯基对象流不是强制性的。
需要模块 X 为您做一些静态生成吗?将其callback
作为您的任务函数的参数,并将其与您的参数一起传递给 X。通常情况下,它是一个单行:require
-ing 一个插件只会让你的代码更长。
即使对于最好描述为“读取所有内容,在内存中处理并写入一次”的工作流程的那些部分,您也可以使用through2.obj来转换乙烯基对象或使用 gulp -filter将它们剔除。Gulp 插件(或者更糟糕的是,通过gulpsmith的metalsmith插件)是最后的手段。
var gulp = require('gulp'),
filter = require('gulp-filter'),
through2 = require('through2');
gulp.task('generate-assets', function() {
return gulp.src('path/to/your/content/and/templates/**')
.pipe(filter(shouldFileSurvive))
.pipe(through2.obj(makeFileDifferent))
.pipe(gulp.dest('dist/'));
});
注意:如果您不回调,则必须返回 final 的结果pipe
。否则,gulp 会认为你的任务是同步的,而不是在启动依赖任务之前等待。
如果最终管道返回正常流而不是gulp.dest
,请进行回调(参见第一个示例),直到b59182c7着陆。
一直在写这样的插件,就在这里gulp-static-site
。看看其他两个答案,我会说它的功能介于vanilla gulp和gulpsmith
.
Gulp-filetree
主要功能确实是树状数据结构的计算,由gulp-filetree
. 它逐渐建立一棵树,直到流结束。然后每个文件(乙烯基对象)都使用一个.tree
属性重新发送。
查看tree.js
以获取有关该数据结构的更多信息。
Gulp-static-site
该插件采用 HTML 文件流,将它们发送gulp-filetree
到一个玉模板,该模板添加了一个带有目录树菜单和文件内容的基本布局。
Lookie lookie 这里是主要管道。 https://github.com/0x01/gulp-static-site/blob/master/index.js#L146 (如您所见,它不是最漂亮的,但还可以。必须删除 Markdown 转换,因为它可以在外面的 gulp 中完成插件。可能同样的论点适用于其他东西......)
问:这有什么关系gulpsmith
?
Gulpsmith 绝对看起来功能强大且完整,如果我在最初编写此代码时就知道它,我可能会使用它。
话虽如此; 这个插件简单、轻量并且有一个小的代码库。我认为很容易理解它的作用并根据您的喜好进行更改,当然欢迎拉取请求:-)
如果还有什么不清楚的,请提出问题或在这里告诉我,谢谢