在Polypane,可访问性是我们关注的三个核心领域之一,另外两个是性能和响应设计。如果您不熟悉Polypane,则它是专门用于Web开发人员的Web浏览器。它具有您在常规浏览器中找不到的各种工具,这些工具可以使您更加高效。要了解有关Polypane的更多信息,请查看介绍文章。
在本文中,我们将重点关注一些常见的可访问性问题,并找到在您的站点中对其进行审核和修复的方法,以确保尽可能地可访问性。这是我们要看的:
- 我的文字有足够的对比度吗?如果没有,我该如何解决?
- 我的网站如何寻找有视觉障碍(例如色盲或远视)的人?诸如阳光直射或具有夜间模式的设备等情况受损如何处理?
- 我的页面结构对依赖它的人有意义吗?
- 如何确保我的站点中没有任何代码质量问题,并且我为提高可访问性所做的工作是否真正有帮助?
- 我的网站在较小的屏幕上运作良好吗?
- 如何确保我的网站适合喜欢深色或不善于处理运动的用户?
对比
我的文字有足够的对比度吗?如果没有,我该如何解决?
理想情况下,在设计过程中要处理文本对比度,使用Stark之类的工具可以轻松测试单个文本和背景对。但是不幸的是,情况并非总是如此。尽管有很多地方可以在线检查给定的文本颜色和给定的背景(我们甚至构建了自己的在线颜色对比测试仪),但是您的网页可能具有许多不同的颜色和背景,对于任何相当复杂的网站,您可能都没有事先了解所有组合。
这样一来,就很容易忽略通常在白色背景上显示的一个灰色文本,而在浅灰色或具有不透明性的深色文本颜色中仅此一个位置仅适用于某些背景。
在Polypane中,几乎所有与元素的交互都会对该特定元素进行快速对比检查。我们的算法会考虑颜色,不透明度和所有背景颜色,以确定实际的文本和背景颜色。然后,我们将其合并为实际的感知文本和背景色,然后进行比较。
我们将在元素工具提示中以及元素面板中显示结果,以及诸如字体系列和字体大小之类的其他信息。这样一来,您的文本对比度始终可以一览无余。
但是,那仍然取决于偶然性,因此Polypane也具有色彩对比叠加层。这将遍历整个页面,找到所有唯一的文本和背景组合,选中所有组合,然后为每个元素添加标签。所有通过的对比对都有一个带有对比的标签,而任何失败的对比都会为每个实例获取一个警告标签,因此您不会忽略任何一个。
我们真的很容易找到对比度问题。但是,如何解决它们?
如果幸运的话,您可以使用设计系统中的另一种颜色,但是如果您没有这种颜色,或者如果这是一次性的颜色对,则必须找设计师或使用在线对比度测试仪自己找到另一种颜色-一个繁琐且耗时的过程,以及我想做的一些事情。
对于每个失败的对比度对,Polypane都会计算出一种与背景具有足够对比度的文本颜色,并建议您进行轻松复制。您甚至可以将鼠标悬停在其上进行预览。(我们提到的在线对比度检查器还为您建议了改进的颜色。)
视觉和情境障碍
我的网站如何寻找有视觉障碍(例如色盲或远视)的人?诸如阳光直射或具有夜间模式的设备等情况受损如何处理?
并非所有访问您网站的人都会拥有完美的视野。实际上,您的大量访问者肯定会出现某种形式的视觉障碍。而且,尽管您可以确保遵循有关最小文本大小的准则,并且不仅仅通过使用颜色就传达任何信息,但很容易忽略一个问题。获得同理心的最佳方法是尝试模拟其他人如何体验您的网站。
色盲
世界范围内有8%至10%的男性是色盲(女性的比例为0.5%少得多),他们分为三类:红绿色色盲,蓝黄色色盲和全色盲。使用Polypane,您可以使用我们的辅助功能覆盖图来模拟所有这些。
您应该使用这些模拟器进行测试,以确保您不仅仅依靠颜色来传递消息。例如,如果在发生错误时仅将输入字段的边框设为红色,则在打开任何这些模拟器时,都几乎看不到或看不到它。相反,您应该提供第二个非彩色指示器,例如错误消息,以将问题传达给用户。
红绿色色盲是最常见的,绝大多数色盲人都患有这种情况。在Polypane中,我们提供了四种不同的模拟器:Deuteranopia,Deuteranomaly,Protanopia和Protanomaly。这里的-anomaly变体是较不严重的版本,而-opia变体将被分类为“完全”红绿色色盲。
顾名思义,患有这种色盲的人很难看到红色和绿色之间的差异,但是也很难看到棕色和橙色之间的差异以及某些蓝色和紫色的阴影。例如,您可以看到常见的“绿色是好,红色是坏”如何使元素着色成为问题。
蓝黄色色盲更为罕见,仅占全球男性的0.0002%。它的技术名称是“ Tritanopia”,而Tritanomaly是不太严重的版本。这种色盲使人们对蓝光的敏感性降低,使蓝色成为任何灰色的部分。
最后,全色盲是最罕见的,占全球男性的0.00003%。它的专有名称是“无色症”,“无色症”是较不严重的版本,人们可以看到一些颜色,但是颜色很暗。
值得注意的是,Polypane中的模拟器(以及任何其他模拟器)都是近似值。尤其是不太严重的变体的范围从几乎不明显到接近完整,因此模拟器选择了一个中间位置。
模糊的视野
这就是色盲,但是全世界有更多的人有某种形式的远视(全世界大约10%),这可能导致屏幕看起来模糊。这可能是“常规”远视,也可能是其他视力障碍,使白内障和青光眼等视力模糊。
白内障是失明的主要原因。它逐渐使您的眼睛晶状体模糊。青光眼是失明的第二大最常见原因,会降低您的周边视力,其次是中央视力。有时它被称为隧道视觉,尽管它是许多不同障碍的总称。
使用这些模拟器,您会注意到阅读常规文本有多么困难。视力模糊的人通常可以通过眼镜或放大倍数对其进行补偿,但这仍然有助于确保您的页面仍可扫描。确保标题足够大,以使这些模拟器可读。这将确保您的页面可扫描而不会造成过多负担。
情境障碍
并非所有的视觉障碍都是身体上的。某些情况也是有条件的:它们仅在您处于特定情况下才会发生。使用Polypane,您可以模拟以下两种:明亮的阳光和夜间模式。
在明亮的阳光下很难看清屏幕。它们被冲洗掉了,有眩光,只有最大的对比度仍然可读。也许并非所有站点都应在明亮的阳光下使用,但是如果您拥有移动或响应站点,则最终将在某个位置将其显示在屏幕上。这是一个很好的模拟器,可以检查您的细微对比是否不太细微。
另一方面,在过去的几年中,夜间模式在计算机和移动设备上的大多数操作系统中已逐渐出现。夜间模式将减少夜间屏幕中的蓝色量,使屏幕对您的眼睛更放松,并减少褪黑激素的抑制。褪黑激素使您昏昏欲睡,而当您周围的自然光线变暗时,一天结束时您会得到更多的睡眠。如果您一直在电脑上工作到凌晨2点,甚至根本不感到疲倦,那么抑制褪黑激素就是原因。
大多数操作系统中的夜间模式旨在防止屏幕上显示的内容出现任何问题,但是,如果您依靠黄色来传达含义,那么当一切都变成黄色时,这些内容可能会丢失。
阅读障碍
全球约有5%至10%的人患有阅读障碍,这是一种阅读障碍。尽管这不是情况上的损害,但确实会影响人们的视觉体验。
一些专家建议,甚至有可能超过15%,因为许多有阅读障碍的人没有意识到自己有阅读障碍。由于无法将我们的阅读体验与其他人的阅读体验进行比较,因此很难知道您的阅读体验何时显着不同。
患有阅读障碍的人将其描述为看到屏幕上的字母在跳舞,这就是我们的阅读障碍模拟器所显示的。当您查看它们时,每个单词中的字母会混杂并重新排序。它们仍然大部分可读,但是比平时花费更多的精力。
并非每个患有阅读障碍的人都经历过这样的阅读,并且使用模拟器比获得其他东西更能获得同理心。但是,如果由于单词太长或字母可以形成多个单词而使单词混乱,则可以考虑将其更改为更简单,更清晰的单词。
页面结构
我的页面结构对依赖它的人有意义吗?
你的页面结构,像你的标题和地标(元素喜欢body
,nav
,main
,aside
和section
)比你想象的更重要。许多辅助技术(例如屏幕阅读器)使用户可以拉出所有标题,地标或链接的列表,以便他们快速浏览并查看是否找到所需的部分。
重要的是要使页面具有逻辑顺序,其标题不要跳过级别和正确的地标(例如导航,页眉和页脚)。如果您的网站是由许多组件和模板构成的,那么您可能无法在页面上呈现所有标题及其顺序之前就获得一个很好的概览,并且并非所有地标都可能带有匹配的标题。
“多窗格大纲”面板实现了HTML5大纲算法,以可视化页面和标题结构。这样可以很容易地看到您在哪里跳过标题级别,以及是否有缺少标题的地标。
代码质量
如何确保我的站点中没有任何代码质量问题,并且我为提高可访问性所做的工作是否真正有帮助?
无可否认,可访问性是一个广阔的领域。本文已经提到对比度问题,不同的视觉和情境障碍以及文档结构,但这只是表面问题。有很多事情可能会对某人在您的网站上的体验产生负面影响,例如缺少alt
图像属性,没有文本的链接以及未定义的页面语言,仅举几例。如果您不需要每页都需要一个庞大的清单,而只是将问题浮出水面,那就太好了。在Polypane中,有多种方法可以执行此操作:通过内置的辅助功能面板和两个叠加层-A11y.css和Tota11y。
A11y.css是一个CSS文件,突出显示页面中可能存在的风险和错误-主要用于辅助功能,但也用于可能导致辅助功能问题(例如缺少字符集)的错误。这可能有点面子,因为它在它认为您应该检查的所有内容周围绘制了粗边框,即使是针对故意的内容(例如空alt
属性)也是如此。
另一方面,可汗学院的Tota11y是几个不同工具的集合。有一个工具可以列出标题和地标(并突出显示任何违反顺序的内容),发现对比度问题(尽管不如Polypane内置的颜色对比度检查器那样彻底)并突出显示可能导致问题的任何链接,图像或标签(由于缺少内容) ,以及缺少或为空alt
或for
属性)。
最后,Polypane带有其自己的“辅助功能”面板,该面板可以根据流行的Ax规则集运行辅助功能检查。运行测试时,Polypane会分析整个页面,并在四个单独的类别中列出所有问题:严重,严重,中度和次要。
关键和严重问题是要解决的真正重要问题。关键问题是诸如alt
图像文本丢失和ARIA错误使用之类的问题。
您可以扩展找到的每个问题,以获取有关受该问题影响的元素以及每个元素的特定问题的更多信息。
对我们而言,这些错误是可操作的很重要:它们不仅告诉您出了什么问题,还为您提供有关如何处理它们的建议。例如,对于缺少alt
属性的图像,我们将说明内容图像和演示图像之间的差异,对于颜色对比度问题,我们将建议一种具有足够对比度的颜色。
在辅助功能面板中,您可以单击任何元素并将其显示在元素检查器中,通常可以在其中通过更新属性或样式来解决问题。完成此操作后,将其复制到您的源中,即可解决问题!
有趣的是,在构建辅助功能面板并检查许多不同的网站时,更常见的是将ARIA误用为问题,而不是缺少ARIA。可访问性是一个复杂的话题,很容易以为您在做正确的事,而实际上却使难度增加了一些。个人知识和手动测试非常宝贵,但是自动测试可以提供出色的现场检查。
较小的屏幕
我的网站在较小的屏幕上运作良好吗?
关于响应式设计已经有很多文章了,但这也是一个重要的可访问性问题。首先,根据WCAG规则1.4.10,不允许在320像素宽的屏幕上产生水平滚动条。并且在更宽的屏幕上,虽然不算违规,但看起来却很刺耳且令人困惑。
找到水平溢出的原因可能是一个真正的难题,因为在大多数情况下,并不能立即弄清楚是哪个元素引起了它。您最终会在dev工具中随机删除元素,以期找到该元素。那是很多繁琐的工作。
启用“布局调试”叠加层后,Polypane会检测是否存在水平滚动条,并找到导致它们的元素。然后,将它们涂成红色,以便您可以找到并修复它们,例如,通过确保父元素具有超载:隐藏,或确保您的内容适合可用空间。
即使手机屏幕比桌面小,但随着屏幕尺寸的增加,用一只手握住手机时,很难轻松到达屏幕的所有部分。通过可触及性叠加层,我们可以显示手握手机(右手或左手)时,屏幕的哪些部分更容易或更难到达。
一只手握住手机,屏幕的底部往往比顶部更容易触及,因此取决于您的站点。实际上,将重要项目放在屏幕底部可能更加用户友好。在应用程序中,将项目放置在屏幕底部很常见,而且我们看到越来越多的网站和Web应用程序也正在迁移到这种模式。
暗模式和动态
如何确保我的网站适合喜欢深色或不善于处理运动的用户?
深色模式虽然很流行,但对于发现明亮的计算机屏幕却又痛苦又费力的人来说,也可能是可访问性的帮助。良好的深色模式可以很好地替代反转色(Mac上的一项功能)或强制色(Edge和Windows上的一项功能)的外观,强制将所有颜色强制显示为指定的调色板,通常使用浅色黑色背景)。
要测试和实现暗模式,请使用“ prefers-color-scheme:dark”,将整个操作系统切换为暗模式,深入浏览器开发工具(设置菜单>更多工具>渲染>向下滚动>选择在仿真下拉菜单中为“暗” )或在Polypane中,您可以弹出打开选项下拉菜单,然后单击“暗”以切换到单个窗格的暗模式,因此很容易与灯光设计并排看到。
同样,前庭疾病患者在大型动画和转场等网站上移动时也会感到不适。对于他们来说,“喜欢减少运动:减少”媒体查询可以是一种解决方案。设置好后,重要的是淡化动画和过渡。您不需要禁用所有动画(尽管也可以使用),但要尽量减少它的晃动和更微妙的淡入淡出。同样,如果您启用了平滑滚动,那将是很大的动作,因此请确保将“滚动行为”设置为“自动”,而不是“平滑”。
在Polypane中进行测试也很容易:打开选项菜单,然后将“ preferred-reduced-motion”选项切换为“ reduce”。现在,您可以单独进行测试,也可以与常规网站并排进行测试。
我希望这可以让您了解您可能遇到的可访问性问题的类型,如何处理它们以及Polypane尝试使它们更容易解决的方法。Polypane有一个免费试用版,可让您在注册后五分钟内进行首次可访问性审核。
基利安·沃克霍夫
Kilian是来自荷兰的网络开发人员,致力于开发可帮助设计师和开发人员更好地完成工作的软件。他对现代网络,应用程序开发和新技术很感兴趣,并在其网站上定期撰写诸如响应式网站,设计系统和Electron之类的主题。
核心网络生命:Google的网络性能指标指南
不幸的是,“绩效”是数十个指标的统称。
到第一个字节的时间,开始渲染,CPU使用率,JavaScript堆大小,第一个有内容的绘画,第一个有意义的绘画,第一个CPU空闲,DOM加载,页面完全加载,交互时间,每秒样式重新计算等。
不同的工具返回不同的结果集,可能很难知道从哪里开始。
Google的Web Vitals计划旨在简化绩效评估,并帮助您专注于最重要的改进。核心网络生命力是反映真实用户体验的关键性能指标。其中一些由Chrome DevTools,PageSpeed Insights和Google Search Console中的Lighthouse面板报告。
该网络的命脉JavaScript库,从真实用户访问你的网站可以帮助测量更真实的指标。可以将结果发布到Google Analytics(分析)或其他端点进行进一步分析。
Google建议使用第75个百分位,即记录同一指标的多个结果,将结果按从最佳到最坏的顺序进行排序,然后在四分之三的时间点分析该数字。因此,四分之三的站点访问者将体验到这种性能水平。
当前的核心网络生命力是内容最大的绘画,首次输入延迟和累积布局偏移,它们可以相应地评估负载,交互性和视觉稳定性。
最大含量的涂料(LCP)
LCP衡量加载性能-内容显示的速度。
历史指标(例如页面负载)DOMContentLoaded
在这方面一直很努力,因为它们并不总是指示用户体验。例如,初始屏幕可能几乎立即出现,但进一步的Ajax请求加载的可用内容可能要花更长的时间才能显示出来。
最大内容绘画(LCP)报告视口内可见的最大图像或文本块的渲染时间。小于2.5秒的时间被认为是好的,大于4.0秒的任何东西都被认为是差的。
LCP中考虑的元素类型为:
<img>
元素<image>
里面的元素<svg>
<video>
元素的海报图像- 使用CSS
url()
属性加载背景图片的元素 - 包含文本节点的块级元素。
在内容加载时确定最大的元素,并计算大小为其在浏览器视口中的可见尺寸。
LCP可能受到以下因素的影响:
- 服务器响应时间
- 资源加载时间
- 渲染阻止CSS或JavaScript
- 客户大小的处理时间
LCP的改进可能通过以下方式实现:
- 使用内容分发网络(CDN)将请求路由到更近的服务器
- 通过最小化昂贵的渲染过程数量来优化服务器响应
- 最小化资产的文件大小
- 在本地缓存资产,并可能使用服务工作者首先返回本地版本。
首次输入延迟(FID)
FID衡量响应度-页面响应用户动作的速度。
该度量记录从用户与页面进行交互(单击,轻击,按键等)到浏览器开始处理该事件处理程序的时间。小于100毫秒的延迟被认为是好的,而大于300毫秒的任何延迟都被认为是较差的。
仅当将应用程序提供给真实用户时,才能准确测量FID。此外,它仅衡量事件处理的延迟,而不衡量运行处理程序或更新UI所花费的时间。
因此,Google和各种工具使用总阻止时间(TBT)作为替代指标,无需实际用户输入即可进行计算。TBT衡量以下之间的总时间:
- 第一个内容丰富的绘画(FCP)-页面内容的任何部分都已呈现的时间,以及
- 交互时间(TTI)-页面能够可靠地响应用户输入的时间(不再运行长时间的任务,并且尚未解决两个以上的GET请求)。
FID / TBT的改善可能通过以下方式实现:
- 通常通过延迟非关键代码来减少JavaScript执行时间
- 分解长期运行的任务
- 使用Web Worker在后台线程中运行任务
- 按需加载第三方JavaScript。
累积版式移位(CLS)
CLS衡量视觉稳定性-查看页面时内容的意外移动。
当内容在没有警告的情况下移动时,CLS会评估那些烦人的情况-通常是在当前滚动位置上方的广告或图像完成加载后DOM发生更改时。该问题在移动设备上尤其明显,可能导致您丢失位置或点击错误的链接。
CLS乘以:
- 影响分数:视口中不稳定元素的总面积(将移动的那些元素)。0.5的碰撞分数表示将替换占整个视口一半的元素。
- 距离分数:视口中任何单个元素移动的最大距离。距离分数0.25表示至少一个元素移动了视口的四分之一(水平或垂直)。
考虑以下示例,该示例在呈现徽标,菜单和英雄图像后不久加载广告:
徽标和菜单不会移动-它们是稳定的元素。广告已添加到DOM,并且其起始位置不变,因此也很稳定。但是,英雄形象会移动:
- 英雄在360 x 720视口中的像素为360 x 510像素。因此,其影响分数为(360 x 510)/(360 x 720)= 0.71
- 它在720px视口高度中移动90个垂直像素,所以它的距离分数是90/720 = 0.125
因此,CLS为0.71 x 0.125 = 0.089
低于0.1的CLS分数被认为是好的,高于0.25的任何东西都被认为是差的。在这种情况下,CLS恰好在可接受的范围内,因为尽管受影响的区域很大,但它移动的距离相对较小。不过,较大的广告将需要进一步关注。
在任何可能触发UI更改或视口调整大小的用户交互之后,CLS算法都不会在500ms内记录布局偏移。因此,您的页面不会因操作所需的界面更新,过渡和动画(例如,从汉堡包图标打开全屏菜单)而受到惩罚。
Chrome DevTools中的“渲染”面板(菜单>更多工具>渲染)提供了“布局移位区域”选项。选中该框并刷新页面-布局转换以蓝色突出显示。您还可以在“网络”面板中修改网络速度以减慢加载速度。
FID / TBT的改善可能通过以下方式实现:
- 通过添加带有
width
和height
属性的尺寸,CSSaspect-ratio
属性或适当的旧填充技巧,为图像,视频和iframe元素保留空间 - 加载网络字体时避免使用FOUT(无样式文本的闪烁)和FOIT(无形文本的闪烁)。预加载或使用类似大小的后备字体会有所帮助
- 在初始页面加载期间,不要在现有内容上方插入DOM元素,例如新闻稿注册和类似的通知框
- 使用CSS
transform
和opacity
更便宜的动画。
绩效优先
核心Web Vitals将随着时间的推移而发展,但是评估LCP,FID和CLS指标可以帮助确定最关键的问题。首先解决快速简便的问题-它们通常具有最大的投资回报率:
- 激活服务器压缩以及HTTP / 2或HTTP / 3
- 通过设置HTTP到期标头来确保使用浏览器缓存
- 提前预载资产
- 连接并缩小CSS和JavaScript
- 删除未使用的资产
- 考虑使用CDN或更好的托管
- 使用适当的图像尺寸和格式
- 优化图像和视频文件的大小(专业CDN可以帮助您)
SitePoint一书“快速入门Web性能”提供了许多技巧,可以提高网站速度,降低成本并保持用户满意。
克雷格·巴克勒
Craig是一位自由职业的英国Web顾问,他于1995年为IE2.0建立了他的第一页。自那时以来,他一直倡导标准,可访问性和最佳实践HTML5技术。他为英国议会,欧洲议会,能源与气候变化部,微软等公司和组织创建了企业规范,网站和在线应用程序。他为SitePoint写了1000多篇文章,您可以找到他@craigbuckler。
Webflow与WordPress:直接对比
由 伊万克赖默
网页
分享:
免费的JavaScript书!
编写功能强大,干净且可维护的JavaScript。
建议零售价$ 11.95
但是,在最近几年中,一个新的竞争者开始挑战WordPress的宝座:Webflow。尽管WordPress继续在博客圈中处于领先地位,但Webflow成为了一个新的小型但快速发展的王国的年轻王子,被称为“无代码运动”。
受数百万不喜欢代码的互联网用户的启发,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入门
由 克雷格·巴克勒
网页
分享:
免费的JavaScript书!
编写功能强大,干净且可维护的JavaScript。
建议零售价$ 11.95
这带来了几个主要好处:
- 托管很简单:您正在提供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>
这对于大多数站点已经足够,但是您可以对其进行改进。例如:
- 提供将菜单显示到特定级别的选项,例如仅在页眉中显示顶层,在页脚中显示所有页面
- 突出显示活动页面,同时使其不可单击
- 为活动菜单项和打开菜单项设置样式类。
实现此目的的一种方法是创建一个可重用的shortcode,使用过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
。
要减小图像大小,请为JPEG,PNG和SVG文件安装imagemin和插件:
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声明的原始源文件位置可用。
使用Transforms压缩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内容导入静态页面获得加分。