受数百万不喜欢使用代码的互联网用户的启发,Webflow迅速发展到一些行业内部人士开始质疑WordPress的未来,将其作为非技术性网站所有者的主要选择。
Webflow是否真的是WordPress宝座的竞争者?还是这是永远不会损害WordPress统治地位的临时威胁?在本文中,我们将探讨使每个公司受欢迎的原因以及对其各自职位的主要威胁。
WordPress:网站标准
WordPress最初只是Matt Mattlenlenweg和Mike Little的宠物项目,这两个年轻的开发人员希望在他们使用的b2 / cafelog平台停止更新其代码之后创建一个开源博客平台。
从这个无辜的开始,WordPress发展到今天,诸如Zoom,Walt Disney Company和Zillow之类的公司每天都在使用它来推动博客工作。Vogue,Techcrunch和Rolling Stone等媒体巨头将WordPress视为一个CMS,而不仅仅是整个CMS的核心。得益于WordPress的流行,可以肯定地说,如果没有WordPress,我们今天所知的大部分Web都无法像它那样起作用。
但是,如果您不只是知名品牌和庞大的统计数据,WordPress仍然不过是一个荣耀的博客平台。到目前为止,WordPress的CMS功能是其被广泛采用的理由。使用WordPress创建网站已成为行业标准。阅读有关启动网站的任何指南,您将一遍又一遍地看到相同的步骤:
- 获得便宜的博客托管服务提供商
- 一键安装WordPress
- 安装WordPress主题
- 自定义它
- 添加内容
- 启动您的网站
作为一个非技术人员,我记得在2010年左右创建我的第一个网站时,它令人生畏,甚至有些吓人。没有一键式WordPress安装无济于事。但是,在按照我的托管服务提供商共享的每个步骤进行操作之后,我启动并运行了第一个由WordPress驱动的网站。对我来说,那是与WordPress建立长期合作关系的开端-我一直坚持到今天。
这并不是说为像我这样的非技术人员安装和使用WordPress很容易。与PHP紧密合作的感觉就像是在潜入水下的同时清洗潜水艇的引擎。您认为如果触摸错误的螺丝,整艘船都会沉没。
WordPress背后的公司Automattic非常了解这些担忧,这就是为什么它建立了庞大的专家和业余爱好者社区的原因,他们会在遇到任何问题时引导像我这样的非技术人员朝着正确的方向发展。这个紧密联系的社区是为什么WordPress尽管具有技术性,但仍继续在非技术人员中流行的原因之一。
如果我们不仅仅关注品牌名称和不计其数的统计数据,WordPress的功能将非常有限。它被创建为博客平台,并且一直如此。但这并没有阻止它允许其他人在需要时开发独特的即席功能。
通过超过57,000个插件,开发人员已将WordPress从单纯的博客平台转变为一种功能强大的平台,能够满足几乎每个网站所有者的需求。例如,如果您需要联系表格,则可以单击几下安装免费的插件,例如WPForms。无需打开引擎并使用HTML和PHP编写表单代码。
我问了uSERP的首席执行官,为WordPress构建的SaaS工具的所有者Jeremy Moser,为什么他认为WordPress如此成功,他说:
WordPress代表网站,Apple代表手机。他们成功的原因有几个基本原因。1)市场占有率。它们在当前市场中占主导地位,并且口碑相传。2)它们即插即用!您可以在一个小时内启动一个简单的WordPress网站,下载10个免费插件,并对网站进行转化和其他操作进行优化。大多数功能几乎都不存在学习曲线,从而提供了极低的入门门槛。
当您需要在前端或后端进行深入的自定义更改时,WordPress的局限性显而易见。改变主题的美感或增加现有插件无法提供的独特功能,就需要雇用开发人员-他们的高价值服务价格高昂。
WordPress企业家和行业专家Matt Medeiros观察到,由于建立基于WordPress的网站的技术障碍,WordPress不再是企业家的最佳选择。
关于WordPress即将推出的REST API,以及是否使其很快成为核心的争论一直在进行着激烈而激烈的辩论。
这些讨论仅针对1%的1%,但它们会在我们心爱的软件的未来时间表中传递连锁反应。实际上,我认为这是一段时间以来最具定义性的讨论,它将决定WordPress在未来十年的发展方向。如果您不像我那样生活和呼吸WordPress,那您为什么还要在乎呢?坦率地说,您可能没有,为什么要承担这种认知负担?
如您所见,WordPress及其非技术社区之间的脱节是解释Webflow崛起的原因之一。
除了管理WordPress网站的精神压力外,严重的漏洞问题还改变了WordPress的公众认知。一项研究发现,在所分析的42,106个WordPress网站中,至少有30,823个存在安全漏洞,这使它们受到了黑客的怜悯。考虑到数据泄露的成本,与WordPress安全挑战保持一致的努力可能不值得。
在将近15年的时间里,WordPress经历了从CMS领域的Drupal和Joomla到页面构建器行业的Squarespace和Wix到ThemeForest中的传统HTML模板网站的激烈竞争。但是,在Webflow出现之前,这些竞争者都没有阻止WordPress成为网站所有者和开发人员的主要选择。
Webflow:无代码运动的领导者
WordPress的卓越性隐含地回答了一个明显的问题,即如果开发网站很容易,那么每个人都将使用具有内置后端功能的定制HTML模板或CSS框架(如Bootstrap)。
但是事实证明,对网站开发的需求高于大多数人自己完成的能力,这就是为什么人们使用WordPress来启动其网站的原因。尽管WordPress确实可以帮助人们有效地启动网站,但效率却不高。对于那些想要定制网站而不必依赖昂贵的网站开发或任何其他技术问题的叛军,WordPress远远不够。
正是出于这种需要,无代码运动诞生了。不仅消费者的需求增加了,而且WordPress也导致了公司内部不同部门的孤立。
正如Kate Kendall解释的那样:
优先考虑功能开发以及错误修复和调整是一个挑战。进展缓慢。我们尝试了许多A / B测试工具,并将某些页面移至流行的CMS,但是用户体验开始受到影响。
通过使用无代码工具和平台,非技术人员可以创建Web应用程序和网站,而无需编写任何代码。Webflow是无代码领域中最受欢迎的工具之一,但它并不是唯一的工具:Zapier,Sharetribe和Glide也已成为行业标准。
首先,Webflow是一个多功能的Web设计工具,CMS和电子商务平台。该公司的目标客户是网页设计师,内容经理和营销人员,他们的共同点是缺乏技术技能。
Webflow还提供托管和内置动画等功能,与WordPress不同,Webflow的用户无需处理任何PHP,数据库或自动更新。换句话说,Webflow为其用户提供了开发人员的能力,而无需处理其中的技术问题。它吸引了想要打破各自的孤岛并在一个屋顶下进行协作的非技术创始人和技术开发人员,这导致许多WordPress用户切换到Webflow。
B2B营销机构Limehub的创始人兼首席执行官Raine Gaisford是一个前WordPress用户的例子,该用户由于其低维护,低复杂性和WordPress较低的成本而转向Webflow。
我们想要一个无代码的网站平台,该平台应具有先进的设计能力,并包括托管功能,但它也可以与我们使用的其他应用程序灵活集成,并且可以随着我们的变化和发展而适应和扩展。我们还希望降低维护成本,因此我们可以将精力集中在创建和发布许多新内容上,而不是花时间确保网站是最新的并且可以正常工作。
Webflow的拖放功能使您可以使用不同的元素,“符号”(可重复使用的组件,如导航菜单)和导航器,与使用的一种网页设计工具几乎相同。
Webflow与WordPress的主要区别在于,它提供了一个内置的托管解决方案,与所有托管公司一样,它根据网站访问者和所需的功能提供了不同的计划。
他们的网站计划起价为每月12美元,非常适合想要没有CMS的网站的任何人。如果您要使用Webflow的CMS,则每月费用为$ 16。他们的电子商务功能每月起价为29美元。
许多开发人员会争辩说,使WordPress与众不同的是其开源精神。同时,Webflow是一个封闭的,基于云的平台,非常类似于分别用于CRM和电子商务行业的Hubspot或Shopify。
对于非技术人员来说,这是有利的。例如,您可以直接从公司获得客户支持,而不必依赖WordPress的论坛和博客来寻求解决方案。有些人可能会担心与使用封闭源软件相关的安全性或道德问题,但这是很少有人了解或关心的问题(包括我在内)。
尽管大张旗鼓,Webflow并非没有缺陷。首先,Webflow带有陡峭的学习曲线,在开发网站时需要深入关注细节。与预先制作的WordPress主题不同,Webflow是设计人员用来创建其工作版本的专业工具。尽管该公司通过Webflow University提供了广泛的教育计划,但仍然是任何企业家在切换到平台之前都必须考虑的一项耗时的任务。
而且,Webflow为用户提供了几乎无限量的选择,其中许多需要奉献和知识才能正确使用。使用Webflow的前WordPress用户Nat Eliason使用以下类比总结了这一点:“ Webflow更像是没有训练轮的自行车。如果您会骑自行车,那太好了,但是如果您不知道,那将是一段糟糕的时光。”
但是,通过正确的方法和时间投入,Webflow允许人们以一种使许多开发人员嫉妒的方式创建网站。
那是什么?WordPress还是Webflow?
在提出赞成和反对WordPress和Webflow的论据之后,开始的问题仍然存在:您应该使用WordPress还是Webflow?没有明确的答案,但是为了更接近定义,我的想法是:
- 如果您想走阻力最小的道路,那么WordPress将继续是大多数非技术人员的首选。它是免费的,易于使用,并且每个主题都有成千上万的教程。
- 如果您想完全控制您的网站而不处理固有技术,那么Webflow是您的选择。如您所知,Webflow允许进行高级自定义,这使非技术人员可以轻松地从头开始开发网站。而且,它允许技术和非技术团队(例如网页设计师和营销人员)之间进行开放式协作。
随着CMS领域新战的发展,WordPress与Webflow的困境将持续数年,并不断受到媒体的关注。
你要做什么?卡片在桌子上;是时候做出选择了。
伊凡·克雷默(Ivan Kreimer)
伊万·克雷默(Ivan Kreimer)是一位自由内容撰稿人,他为SaaS业务创建教育内容。在他的消遣中,他喜欢帮助人们成为自由作家。除了为那些阅读SitePoint等网站的聪明人撰写文章外,Ivan还为Entrepreneur,MarketingProfs等网站撰写文章。
Eleventy入门
- 托管很简单:您正在提供HTML文件
- 系统很安全:没有什么可破解的
- 性能可能很棒。
Eleventy已变得越来越受欢迎,并在Web开发中引起了知名人士的关注。它是内容站点和博客的理想选择,但已适用于在线商店和报告系统。
在大多数情况下,您将使用Eleventy从Markdown文档生成HTML页面,这些页面会将内容插入由诸如Nunchucks之类的引擎提供动力的模板中。但是,本教程还演示了如何将Eleventy用作所有资产的完整构建系统。您不一定需要单独的系统,例如npm脚本,webpack或Gulp.js,但是您仍然可以享受自动构建和实时重新加载的乐趣。
您需要一个JavaScript框架吗?
一些SSG采用客户端JavaScript框架,例如React或Vue.js。您可以将框架与Eleventy一起使用,但未强制执行。
我认为,除非您要创建复杂的应用程序,否则可能不需要JavaScript框架。而且,如果您要创建应用程序,那么SSG不是正确的工具!盖茨比球迷可能会不同意,所以请在Twitter上挑战/嘲笑我!
给我看代码
Eleventy声称很简单,但是在超越基础知识时可能会令人生畏。本教程演示了如何使用页面和博客/文章来构建一个简单的网站-这项任务通常由WordPress处理。
完整代码可在https://github.com/craigbuckler/11ty-starter上获得。您可以通过在终端中输入以下命令,在Windows,macOS或Linux上下载,安装并启动它:
git clone https://github.com/craigbuckler/11ty-starter
cd 11ty-starter
npm i
npx eleventy --serve
然后在浏览器中导航到主页http:// localhost:8080。
以下步骤描述了如何从头开始构建站点。
安装Eleventy
像任何Node.js项目一样,从创建目录并初始化package.json
文件开始:
mkdir mysite
cd mysite
npm init
然后将Eleventy安装为开发依赖项:
npm i @11ty/eleventy --save-dev
注意:此项目将模块安装为开发依赖项,因为它们仅需要在开发计算机上运行。某些具有自动构建过程的主机可能会要求您使用标准的运行时依赖项。
呈现您的第一页
创建一个src
目录,所有源文件都将驻留在该目录中,然后在其中创建一个index.md
文件。添加主页内容,例如:
‐‐‐
title: 11ty starter site
‐‐‐
This is a demonstration website using the [11ty static site generator](https://www.11ty.dev/). It shows pages, blog posts, lists, and tags.
The whole build process is managed through 11ty.
‐‐‐
破折号之间的内容称为前题。它定义了有关页面的名称-值元数据,可用于设置Eleventy和模板的参数。title
此处仅设置了a,但是您很快就会添加说明,日期,标签和其他数据。
.eleventy.js
必须在项目的根文件夹中创建一个名为Eleventy的配置文件。这个简单的示例代码返回一个对象,该对象指定以下内容:
src
源文件的源目录- 将
build
在其中创建网站文件的目录
// 11ty configuration
module.exports = config => {
// 11ty defaults
return {
dir: {
input: 'src',
output: 'build'
}
};
};
要构建站点并启动由Browsersync驱动的实时重新加载服务器,请输入以下内容:
npx eleventy --serve
Eleventy呈现在src
目录中找到的所有内容,并将结果内容输出到build
:
$ npx eleventy --serve
Writing build/index.html from ./src/index.md.
Wrote 1 file in 0.12 seconds (v0.11.0)
Watching...
[Browsersync] Access URLs:
---------------------------------------
Local: http://localhost:8080
External: http://172.27.204.106:8080
---------------------------------------
UI: http://localhost:3001
UI External: http://localhost:3001
---------------------------------------
[Browsersync] Serving files from: build
在这种情况下,build/index.html
可以通过在浏览器中加载URL http:// localhost:8080来访问创建的单个文件。
在创建的HTML文件build/index.html
包含从markdown文件呈现的内容src/index.md
:
<p>This is a demonstration website using the <a href="https://www.11ty.dev/">11ty static site generator</a>. It shows pages, blog posts, lists, and tags.</p>
<p>The whole build process is managed through 11ty.</p>
可以使用Ctrl|停止Eleventy服务器。Cmd+ C。
注意:在网站开发过程中几乎不需要停止Eleventy,因为新文件会自动呈现。但是,以下部分添加了更多配置选项,因此需要重新启动。
创建模板
Eleventy几乎可以使用任何JavaScript模板引擎。Nunchucks是一个很好的选择,因为它是全面的,并在11ty.dev的整个文档中使用。
将前面的内容更改src/index.md
为此:
‐‐‐
title: 11ty starter site
description: This is a demonstration website generated using the 11ty static site generator.
layout: page.njk
‐‐‐
这指示Eleventy使用page.njk
Nunchucks模板进行布局。默认情况下,Eleventy_includes
在源目录(src/
)的子目录中查找模板。那里的任何文件都不会自己渲染,而是在构建过程中使用。
在以下位置创建此新模板src/_includes/page.njk
:
{% include "partials/htmlhead.njk" %}
<main>
{% block content %}
<h1>{{ title }}</h1>
{{ content | safe }}
{% endblock %}
</main>
{% include "partials/htmlfoot.njk" %}
该模板将title
定义的内容放在页面<h1>
标题的标题中,并替换{{ content }}
为Markdown生成的HTML。(它使用safe
Nunchucks过滤器来输出HTML,而不会转义引号和尖括号。)
这两个{% include %}
定义引用了模板中包含的文件。在创建一个HTML头文件src/_includes/partials/htmlhead.njk
,该文件还使用页面的title
和description
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ title }}</title>
<meta name="description" content="{{ description }}">
</head>
<body>
然后在以下位置创建HTML页脚src/_includes/partials/htmlfoot.njk
:
</body>
</html>
停止并重新启动Eleventy npx eleventy --serve
。
build\index.html
现在,呈现的文件包含一个完整的HTML页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>11ty starter site</title>
<meta name="description" content="This is a demonstration website generated using the 11ty static site generator.">
</head>
<body>
<h1>11ty starter site</h1>
<p>This is a demonstration website using the <a href="https://www.11ty.dev/">11ty static site generator</a>. It shows pages, blog posts, lists, and tags.</p>
<p>The whole build process is managed through 11ty.</p>
</body>
</html>
注意:当您在浏览器中查看源代码时,还将看到BrowserSync在元素之后<script>
添加了。这用于触发实时重新加载,并且不会出现在最终版本中(请参见下面的“构建生产站点”部分)。<body>
创建更多页面
现在,您可以创建更多内容,例如强制性的“关于我们”部分。
src/about/index.md
:
‐‐‐
title: About us
description: What we do.
‐‐‐
Some information about us.
src/about/team.md
:
‐‐‐
title: Our team
description: Information about us.
‐‐‐
Who are we and what we do.
src/about/privacy.md
:
‐‐‐
title: Privacy policy
description: We keep your details private.
‐‐‐
Our privacy policy.
这些文件都没有在其前面引用模板。Eleventy允许您通过创建目录来定义目录中所有文件的默认值<directory-name>.json file
。在这种情况下,它名为src/about/about.json
。它将JSON值设置为在页面的前端未明确定义时使用的JSON值:
{
"layout": "page.njk"
}
重新运行npx eleventy --serve
并检查build
文件夹,以查看网站如何开始成形:
index.html
:主页about/index.html
:关于我们页面about/team/index.html
:团队页面about/privacy/index.html
:隐私政策页面
因此,您可以在浏览器中使用类似slug的URL。例如,http:// localhost:8080 / about / team /显示团队页面index.html
文件。
不幸的是,不可能在页面之间导航!您需要菜单…
创建导航菜单
Eleventy提供了一个标准的导航插件,可通过输入以下内容进行安装:
npm i @11ty/eleventy-navigation --save-dev
.eleventy.js
在最后return
声明之前,必须在配置文件中引用插件:
// 11ty configuration
module.exports = config => {
/* --- PLUGINS --- */
// navigation
config.addPlugin( require('@11ty/eleventy-navigation') );
// 11ty defaults
return {
dir: {
input: 'src',
output: 'build'
}
};
};
eleventyNavigation:
必须在菜单中所需的每个页面中定义最重要的部分。本节设置以下内容:
key
页面菜单的A。这可能与相同,title
但通常更短。- 可选的
parent
,引用父页面的key
。 - 可选
order
号码;较低的值首先出现在菜单中。
首页中的内容src/index.md
可以相应地更新:
‐‐‐
title: 11ty starter site
description: This is a demonstration website generated using the 11ty static site generator.
layout: page.njk
eleventyNavigation:
key: home
order: 100
‐‐‐
关于页面src/about/index.md
:
‐‐‐
title: About us
description: What we do.
eleventyNavigation:
key: about
order: 200
‐‐‐
团队页面位于src/about/team.md
:
‐‐‐
title: Our team
description: Information about us.
eleventyNavigation:
key: team
parent: about
order: 210
‐‐‐
隐私政策页面位于src/about/privacy.md
:
‐‐‐
title: Privacy policy
description: We keep your details private.
eleventyNavigation:
key: privacy
parent: about
order: 220
‐‐‐
注意:使用order
10或更高倍数的值可以稍后在其他页面之间插入页面,而无需任何手动重新编号。
现在可以在src/_includes/page.njk
以下位置将导航菜单添加到页面模板:
{% include "partials/htmlhead.njk" %}
<header>
<nav>
{{ collections.all | eleventyNavigation | eleventyNavigationToHtml | safe }}
</nav>
</header>
<main>
...
这是一些神奇的Eleventy插件代码,它检查所有页面并使用eleventyNavigation()
功能过滤它们以创建层次结构列表。使用eleventyNavigationToHtml()
功能将该列表呈现器呈现为HTML 。
重新npx eleventy --serve
加载任何页面以查看菜单。
现在,您可以导航到eleventyNavigation
前件中定义的任何页面。
改善导航
导航插件返回基本的HTML列表:
<ul>
<li><a href="/">home</a></li>
<li>
<a href="/about/">about</a>
<ul>
<li><a href="/about/team/">team</a></li>
<li><a href="/about/privacy/">privacy</a></li>
</ul>
</li>
</ul>
这对于大多数站点已经足够,但是您可以对其进行改进。例如:
- 提供将菜单显示到特定级别的选项,例如仅在页眉中显示顶层,在页脚中显示所有页面
- 高亮显示活动页面,同时使其不可单击
- 为活动菜单项和打开菜单项设置样式类。
实现此目的的一种方法是创建一个可重用的简码,使用过WordPress的任何人都会熟悉它。简码和任何可选参数运行一个函数,该函数返回放置在模板中的HTML字符串。
停止Eleventy服务器并更新src/_includes/page.njk
模板以{% navlist %}
在<header>
和<footer>
部分中使用简码:
{% include "partials/htmlhead.njk" %}
<header>
<nav>
{% navlist collections.all | eleventyNavigation, page, 1 %}
</nav>
</header>
<main>
{% block content %}
<h1>{{ title }}</h1>
{{ content | safe }}
{% endblock %}
</main>
<footer>
<nav>
{% navlist collections.all | eleventyNavigation, page, 2 %}
</nav>
</footer>
{% include "partials/htmlfoot.njk" %}
该navlist
简码传递三个参数:
- 通过该
eleventyNavigation()
函数过滤的每个页面,该函数返回页面对象的分层列表。每个页面定义一个children
子页面数组。 - 目前
page
。 - 可选的
level
。的value值1
仅返回顶级HTML。2
返回顶层和所有直接子页面。
该navlist
简码必须使用注册.addShortcode()
的功能.eleventy.js
在之前return
的语句。它传递了一个短代码名称和要调用的函数:
/* --- SHORTCODES --- */
// page navigation
config.addShortcode('navlist', require('./lib/shortcodes/navlist.js'));
您现在可以在中导出函数lib/shortcodes/navlist.js
。下面的代码递归地检查所有页面以生成适当的HTML(如果很难遵循,请不要担心)。
注意:简码文件src
不是文件夹的一部分,因此已在文件夹外部创建,但是您也可以在中定义它src/_includes
。
// generates a page navigation list
const
listType = 'ul',
elementActive = 'strong',
classActive = 'active',
classOpen = 'open';
// pass in collections.all | eleventyNavigation, (current) page, and maximum depth level
module.exports = (pageNav, page, maxLevel = 999) => {
function navRecurse(entry, level = 1) {
let childPages = '';
if (level < maxLevel) {
for (let child of entry.children) {
childPages += navRecurse(child, level++);
}
}
let
active = (entry.url === page.url),
classList = [];
if ((active && childPages) || childPages.includes(`<${ elementActive }>`)) classList.push(classOpen);
if (active) classList.push(classActive);
return (
'<li' +
(classList.length ? ` class="${ classList.join(' ') }"` : '') +
'>' +
(active ? `<${ elementActive }>` : `<a href="${ entry.url }">`) +
entry.title +
(active ? `</${ elementActive }>` : '</a>') +
(childPages ? `<${ listType }>${ childPages }</${ listType }>` : '') +
'</li>'
);
}
let nav = '';
for (let entry of pageNav) {
nav += navRecurse(entry);
}
return `<${ listType }>${ nav }</${ listType }>`;
};
重新运行npx eleventy --serve
并导航到“关于”页面。标头<nav>
HTML现在包含以下内容:
<ul>
<li><a href="/">home</a></li>
<li class="active"><strong>about</strong></li>
</ul>
页脚<nav>
HTML包含以下内容:
<ul>
<li><a href="/">home</a></li>
<li class="open active">
<strong>about</strong>
<ul>
<li><a href="/about/team/">team</a></li>
<li><a href="/about/privacy/">privacy</a></li>
</ul>
</li>
</ul>
添加文章/博客文章
文章或博客文章与标准页面不同。它们通常标有日期,并以相反的时间顺序显示在索引页上。
创建一个新src/articles
目录并添加一些Markdown文件。在这个例子中,命名为六个文件artice-01.md
到article-06.md
已经建立,但你通常用更好的名字来创建更具有可读性SEO友好的URL。
内容示例article/article-01.md
:
‐‐‐
title: The first article
description: This is the first article.
date: 2020-09-01
tags:
- HTML
- CSS
‐‐‐
This is an article post.
## Subheading
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
每个帖子指定一个日期和一个或多个标签(HTML
与CSS
在这里使用)。Eleventy自动为每个标签创建一个集合。例如,一个HTML
集合是所有带有标记的帖子的数组HTML
。您可以使用该集合以有趣的方式编制索引或显示这些页面。
最近的article-06.md
文件draft
设置了一个值,并标明了远期的日期:
‐‐‐
title: The sixth article
description: This is the sixth article.
draft: true
date: 2029-09-06
tags:
- HTML
- CSS
- JavaScript
‐‐‐
这表示该帖子在该日期过去并且draft
已被删除之前,不应发布(在实时站点上)。Eleventy没有实现此功能,因此您必须创建自己的自定义集合,该集合忽略草稿。
在的顶部添加几行以.eleventy.js
检测开发模式并返回当前日期时间:
// 11ty configuration
const
dev = global.dev = (process.env.ELEVENTY_ENV === 'development'),
now = new Date();
module.exports = config => {
...
}
然后定义一个post
通过.addCollection()
在return
语句之前调用而命名的集合。以下代码提取md
目录中的所有文件,src/articles
但删除设置位置draft
或将来的发布日期(除非您使用的是开发模式):
// post collection (in src/articles)
config.addCollection('post', collection =>
collection
.getFilteredByGlob('./src/articles/*.md')
.filter(p => dev || (!p.data.draft && p.date <= now))
);
src/_includes/post.njk
为帖子创建一个新模板。这是基于page.njk
模板的,但是该content
块还显示了从该post
集合中提取的文章日期,字数和下一个/上一个链接:
{% extends "page.njk" %}
{% block content %}
<h1>{{ title }}</h1>
{% if date %}<p class="time"><time datetime="{{ date }}">{{ date }}</time></p>{% endif %}
<p class="words">{{ content | wordcount }} words</p>
{{ content | safe }}
{% set nextPost = collections.post | getNextCollectionItem(page) %}
{% if nextPost %}<p>Next article: <a href="{{ nextPost.url }}">{{ nextPost.data.title }}</a></p>{% endif %}
{% set previousPost = collections.post | getPreviousCollectionItem(page) %}
{% if previousPost %}<p>Previous article: <a href="{{ previousPost.url }}">{{ previousPost.data.title }}</a></p>{% endif %}
{% endblock %}
最后,定义一个src/articles/article.json
文件设置post.njk
为默认模板:
{
"layout": "post.njk"
}
运行npx eleventy --serve
,然后浏览至http:// localhost:8080 / articles / article-01 /:
创建文章/博客索引页面
尽管您可以从一个帖子导航到另一个帖子,但在http:// localhost:8080 / articles /上创建索引页面以按相反的时间顺序显示所有帖子(从最新到最新)将很有用。
Eleventy提供了一个分页功能,该功能可以通过遍历一组数据(例如posts
上面创建的集合)来创建任意数量的页面。
src/articles/index.md
使用以下内容创建一个新文件:
‐‐‐
title: Article index
description: A list of articles published on this site.
layout: page.njk
eleventyNavigation:
key: articles
order: 900
pagination:
data: collections.post
alias: pagelist
reverse: true
size: 3
‐‐‐
The following articles are available.
前端物料配置执行以下操作:
- 它设置标准
page.njk
模板。 - 它将页面添加为
articles
菜单项。 - 它创建一个名为
pagelist
from的列表collections.post
,将其反向(最新的帖子优先),并且每页最多允许三项。Eleventy将撰写六篇文章,生成两页,每页三篇文章。
现在修改其中的content
块src/_includes/page.njk
以包括一个新的pagelist.njk
部分:
{% block content %}
<h1>{{ title }}</h1>
{{ content | safe }}
{% include "partials/pagelist.njk" %}
{% endblock %}
src/_includes/partials/pagelist.njk
使用代码创建该部分,以遍历pagelist
分页对象并输出每个帖子的链接,标题,日期和描述:
{% if pagelist %}
<aside class="pagelist">
{%- for post in pagelist -%}
<article>
<h2><a href="{{ post.url }}">{{ post.data.title }}</a></h2>
{% if post.data.date %}<p class="time"><time datetime="{{ post.data.date }}">{{ post.data.date }}</time></p>{% endif %}
<p>{{ post.data.description }}</p>
</article>
{%- endfor -%}
</aside>
{% endif %}
在此代码下,您可以添加下一个和上一个链接以浏览分页索引:
{% if pagination.href.previous or pagination.href.next %}
<nav class="pagenav">
{% if pagination.href.previous %}
<p><a href="{{ pagination.href.previous }}">previous</a></p>
{% endif %}
{% if pagination.href.next %}
<p><a href="{{ pagination.href.next }}">next</a></p>
{% endif %}
</nav>
{% endif %}
在重新开始构建过程之前,请设置ELEVENTY_ENV
环境变量development
以确保草稿和以后的帖子包含在构建中。在Linux / macOS上,输入:
ELEVENTY_ENV=development
或在Windowscmd
提示符下:
set ELEVENTY_ENV=development
或Windows Powershell:
$env:ELEVENTY_ENV="development"
重新运行npx eleventy --serve
并刷新浏览器。菜单中将出现一个新的文章链接,该链接显示了http:// localhost:8080 / articles /上的三篇最新文章:
在接下来的链接指向的文章在进一步网页的http://本地主机:8080 /用品/ 1 /。
创建自定义过滤器
上面的屏幕截图显示的日期是不友好的JavaScript字符串。Eleventy提供了可以修改数据并返回字符串的过滤器。当Markdown生成的内容通过safe
过滤器输出未编码的HTML:时,您已经看到了这种用法{{ content | safe }}
。
lib/filters/dateformat.js
使用以下代码创建一个新文件。它导出两个函数:
ymd()
它将日期YYYY-MM-DD
转换为HTMLdatetime
属性的机器可读格式,并且friendly()
它将日期转换为人类可读的格式,例如1 January, 2020
。
// date formatting functions
const toMonth = new Intl.DateTimeFormat('en', { month: 'long' });
// format a date to YYYY-MM-DD
module.exports.ymd = date => (
date instanceof Date ?
`${ date.getUTCFullYear() }-${ String(date.getUTCMonth() + 1).padStart(2, '0') }-${ String(date.getUTCDate()).padStart(2, '0') }` : ''
);
// format a date to DD MMMM, YYYY
module.exports.friendly = date => (
date instanceof Date ?
date.getUTCDate() + ' ' + toMonth.format(date) + ', ' + date.getUTCFullYear() : ''
);
您还可以创建一个过滤器,以显示帖子中的单词数量,该数量将四舍五入到最接近的十位并用逗号分隔符设置格式,并估算读取时间。lib/filters/readtime.js
使用以下代码创建:
// format number of words and reading time
const
roundTo = 10,
readPerMin = 200,
numFormat = new Intl.NumberFormat('en');
module.exports = count => {
const
words = Math.ceil(count / roundTo) * roundTo,
mins = Math.ceil(count / readPerMin);
return `${ numFormat.format(words) } words, ${ numFormat.format(mins) }-minute read`;
};
.eleventy.js
在return
语句之前的任何位置注册过滤器:
/* --- FILTERS --- */
// format dates
const dateformat = require('./lib/filters/dateformat');
config.addFilter('datefriendly', dateformat.friendly);
config.addFilter('dateymd', dateformat.ymd);
// format word count and reading time
config.addFilter('readtime', require('./lib/filters/readtime'));
然后更新src/_includes/post.njk
使用dateymd
,datefriendly
以及readtime
过滤器:
{% if date %}<p class="time"><time datetime="{{ date | dateymd }}">{{ date | datefriendly }}</time></p>{% endif %}
<p class="words">{{ content | wordcount | readtime }}</p>
然后将文章索引的部分更改src/_includes/partials/pagelist.njk
为使用dateymd
和datefriendly
过滤器:
{% if post.data.date %}<p class="time"><time datetime="{{ post.data.date | dateymd }}">{{ post.data.date | datefriendly }}</time></p>{% endif %}
重新启动构建npx eleventy --serve
并刷新浏览器。加载任何文章以查看友好的日期,格式化的字数和阅读时间估计:
产生的HTML:
<p class="time"><time datetime="2020-09-05">5 September, 2020</time></p>
<p class="words">80 words, 1-minute read</p>
使用JavaScript模板处理图像
Eleventy可以使用中的.addPassthroughCopy()
功能从任何文件夹复制文件.eleventy.js
。例如,要将所有文件复制src/images/
到中build/images/
,您可以添加:
config.addPassthroughCopy('src/images');
如果您的图像已经过优化,那可能就足够了,但是自动的构建时优化可以减少文件数量。在这一点上,开发人员经常转向另一个系统,例如npm
脚本,webpack或Gulp.js,但这可能不是必需的。
JavaScript是Eleventy中的一流模板选项。任何结尾的文件.11ty.js
都将在构建过程中处理。该文件必须使用以下内容导出JavaScript class
:
- 一种
data()
将最重要的设置作为JavaScript对象返回的方法 - 一个
render()
方法—通常返回一个字符串,但它也可以运行同步或异步过程并返回true
。
要减小图像尺寸,请安装imagemin以及JPEG,PNG和SVG文件的插件:
npm i imagemin imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev
在中创建images
目录src
,添加一些图像,然后src/images/images.11ty.js
使用以下代码创建一个新文件:
// image minification
const
dest = './build/images',
fsp = require('fs').promises,
imagemin = require('imagemin'),
plugins = [
require('imagemin-mozjpeg')(),
require('imagemin-pngquant')({ strip: true }),
require('imagemin-svgo')()
];
module.exports = class {
data() {
return {
permalink: false,
eleventyExcludeFromCollections: true
};
}
// process all files
async render() {
// destination already exists?
try {
let dir = await fsp.stat(dest);
if (dir.isDirectory()) return true;
}
catch(e){}
// process images
console.log('optimizing images');
await imagemin(['src/images/*', '!src/images/*.js'], {
destination: dest,
plugins
});
return true;
}
};
重新运行npx eleventy --serve
图像的优化版本将复制到该build/images/
文件夹中。
注意:如果build/images
找到目录,以上代码将结束。这是在每次构建过程中放弃对相同图像进行重新处理的简单解决方案,可确保Eleventy保持快速运行。如果添加其他图像,请build/images
首先删除文件夹以确保它们均已生成。可以使用更好的选项,但是它们需要更多的代码!
现在可以在Markdown或模板文件中添加图像。例如,中的<header>
定义src/_includes/page.njk
可以具有徽标和英雄图像:
<header>
<p class="logo"><a href="/"><img src="/images/logo.svg" width="50" height="50" alt="11ty starter">11ty starter</a></p>
<nav>
{% navlist collections.all | eleventyNavigation, page, 1 %}
</nav>
<figure><img src="/images/{% if hero %}{{ hero }}{% else %}orb.jpg{% endif %}" width="400" height="300" alt="decoration" /></figure>
</header>
hero
可以根据需要在前面设置一个值,例如,在src/articles/articles.json
:
{
"layout": "post.njk",
"hero": "phone.jpg"
}
使用转换处理CSS
您可以用类似的方式处理CSS或使用任何其他构建系统。但是,在这种情况下,Eleventy变换是一个不错的选择。转换是传递当前呈现的字符串内容和文件路径的函数。然后,他们返回该内容的修改版本。
我考虑过使用Sass进行CSS预处理,但是带有一些插件的PostCSS可以实现一种轻量级的替代方案,该替代方案仍支持局部,变量,混合和嵌套。在项目中安装PostCSS模块:
npm i postcss postcss-advanced-variables postcss-nested postcss-scss cssnano --save-dev
然后lib/transforms/postcss.js
使用以下代码创建文件。.css
当构建在development
模式下运行时,它会在处理,最小化和添加源映射之前验证文件正在传递:
// PostCSS CSS processing
/* global dev */
const
postcss = require('postcss'),
postcssPlugins = [
require('postcss-advanced-variables'),
require('postcss-nested'),
require('cssnano')
],
postcssOptions = {
from: 'src/scss/entry.scss',
syntax: require('postcss-scss'),
map: dev ? { inline: true } : false
};
module.exports = async (content, outputPath) => {
if (!String(outputPath).endsWith('.css')) return content;
return (
await postcss(postcssPlugins).process(content, postcssOptions)
).css;
};
转换必须在语句之前使用.addTransform()
函数in进行注册。的通话将触发一个完整的网站重建时一个文件中,更改目录:.eleventy.js
return
.addWatchTarget()
src/scss/
// CSS processing
config.addTransform('postcss', require('./lib/transforms/postcss'));
config.addWatchTarget('./src/scss/');
创建一个src/scss/main.scss
文件,并包含您需要的任何SCSS或CSS代码。该示例代码将导入其他SCSS文件:
// settings
@import '01-settings/_variables';
@import '01-settings/_mixins';
// reset
@import '02-generic/_reset';
// elements
@import '03-elements/_primary';
// etc...
Eleventy不会直接处理CSS或SCSS文件,因此您必须src/scss/main.njk
使用以下代码在处创建一个新的模板文件:
‐‐‐
permalink: /css/main.css
eleventyExcludeFromCollections: true
‐‐‐
@import 'main.scss';
这将导入您的main.scss
文件并将其呈现到build/css/main.css
转换函数进行相应处理之前。.njk
如果您需要多个CSS文件,则可以创建类似的SCSS / CSS和文件。
重新运行npx eleventy --serve
并检查构建到的CSS文件的内容build/css/main.css
。源映射确保在浏览器的开发人员工具中检查样式时CSS声明的原始源文件位置可用。
使用转换最小化HTML
可以使用类似的转换来使用html-minifier缩小HTML 。像这样安装它:
npm i html-minifier --save-dev
lib/transforms/htmlminify.js
使用以下代码创建一个新文件。它验证.html
文件正在处理中,并返回缩小版本:
// minify HTML
const htmlmin = require('html-minifier');
module.exports = (content, outputPath = '.html') => {
if (!String(outputPath).endsWith('.html')) return content;
return htmlmin.minify(content, {
useShortDoctype: true,
removeComments: true,
collapseWhitespace: true
});
};
和以前一样,.eleventy.js
在return
语句之前的某个位置注册转换:
// minify HTML
config.addTransform('htmlminify', require('./lib/transforms/htmlminify'));
注意:您可以考虑在开发过程中不要缩小甚至美化HTML。也就是说,HTML空格会影响浏览器的呈现,因此通常最好以与生产相同的方式来构建代码。源代码查看将变得更加困难,但是浏览器开发人员工具会显示最终的DOM。
通过转换内联资产
通常需要在HTML中内联其他资源。SVG是主要的候选对象,因为图像成为DOM的一部分并且可以使用CSS进行操作。通过内联<style>
元素中的CSS,元素中的JavaScript<script>
或元素中的base64编码图像来减少HTTP请求也是可行的<img>
。
该直列源模块可以处理所有的情况为您服务。与此安装:
npm i inline-source --save-dev
现在lib/transforms/inline.js
,使用以下代码添加一个新文件,以检查和处理HTML内容:
// inline data
const { inlineSource } = require('inline-source');
module.exports = async (content, outputPath) => {
if (!String(outputPath).endsWith('.html')) return content;
return await inlineSource(content, {
compress: true,
rootpath: './build/'
});
};
.eleventy.js
在return
语句之前注册转换:
// inline assets
config.addTransform('inline', require('./lib/transforms/inline'));
现在,添加inline
属性的任何<img>
,<link>
或<script>
标签。例如:
<img src="/images/logo.svg" width="50" height="50" alt="11ty starter" inline>
在构建过程中,转换将<img>
使用导入的<svg>
代码替换标记。
使用JavaScript模板处理JavaScript
客户端JavaScript可以通过转换来处理,但是命名的JavaScript模板<something>.11ty.js
也是一个选项,因为它们由Eleventy自动处理(请参见上面的“使用JavaScript模板处理图像”部分)。
的示例代码提供ES6脚本实现简单的暗/亮主题切换。Rollup.js用于将所有引用的模块捆绑main.js
到一个文件中,并进行摇树操作以删除所有未使用的功能。然后,terser插件将生成的代码最小化。
使用以下命令安装Rollup.js模块:
npm i rollup rollup-plugin-terser --save-dev
然后在中创建js
目录src
并添加您的ES6脚本。一个单一的src/js/main.js
入口脚本必须定义其进口等。例如:
import * as theme from './lib/theme.js';
src/js/javascript.11ty.js
使用以下代码创建一个新文件,以将其处理src/js/main.js
为一个捆绑包,并在开发模式下构建时添加源映射:
// JavaScript processing
/* global dev */
const
jsMain = 'js/main.js',
rollup = require('rollup'),
terser = require('rollup-plugin-terser').terser,
inputOpts = {
input: './src/' + jsMain
},
outputOpts = {
format: 'es',
sourcemap: dev,
plugins: [
terser({
mangle: {
toplevel: true
},
compress: {
drop_console: !dev,
drop_debugger: !dev
},
output: {
quote_style: 1
}
})
]
}
;
module.exports = class {
data() {
return {
permalink: jsMain,
eleventyExcludeFromCollections: true
};
}
// PostCSS processing
async render() {
const
bundle = await rollup.rollup(inputOpts),
{ output } = await bundle.generate(outputOpts),
out = output.length && output[0];
let code = '';
if (out) {
// JS code
code = out.code;
// inline source map
if (out.map) {
let b64 = new Buffer.from(out.map.toString());
code += '//# sourceMappingURL=data:application/json;base64,' + b64.toString('base64');
}
}
return code;
}
};
对JavaScript文件的任何更改都可以通过在.eleventy.js
之前添加以下行来触发重建return
:
config.addWatchTarget('./src/js/');
然后,生成的脚本可以包含在您的页面中,例如src/_includes/partials/htmlfoot.njk
:
<script type="module" src="/js/main.js"></script>
</body>
</html>
注意:示例代码将构建ES6模块,而不是编译为ES5。该脚本较小,但浏览器兼容性会受到更大的限制。就是说,这是一个逐步的增强,该站点无需JavaScript即可运行。
重新启动npx eleventy --serve
,您的缩小脚本将加载并运行。现在可以通过其屡获殊荣的荣耀来查看最终站点:
建立生产现场
对网站感到满意后,您可以在生产模式下构建它,而无需源地图和其他开发选项。
删除build
文件夹并在Linux / macOS上设置ELEVENTY_ENV
为production
:
ELEVENTY_ENV=production
或Windowscmd
提示:
set ELEVENTY_ENV=production
或Windows Powershell:
$env:ELEVENTY_ENV="production"
然后运行npx eleventy
以构建完整站点。
/build
目录中生成的文件可以上载到任何主机。每当将新代码推送到GitHub或类似的存储库时,一些静态网站专家服务就可以自动构建和发布您的网站。福州网站开发 福州网站建设
Eleventy的下一步
该示例项目演示了Eleventy的基础知识,并提供了一些用于构建不同类型的内容的选项。但是,Eleventy非常灵活,您可以自由使用自己喜欢的任何技术。有许多启动项目,每个项目采用的方法略有不同。
有关其他网站功能的建议:
- 为列出相关文章的每个标签创建索引页面。记住Eleventy会自动为每个标签创建单独的集合。
- 生成
feed.xml
列出所有帖子的RSS文件。 - 创建一个
sitemap.xml
列出所有页面的文件。 - 构建一个404错误页面并生成适当的代码来处理它(例如
.htaccess
Apache的文件)。 - 生成其他根文件,例如
favicon.ico
或Service Worker。 - 使用Eleventy的分页功能从data生成页面。
- 并为将WordPress内容导入静态页面获得加分。