使用 Nunjucks 使用组件构建静态站点
已发表: 2022-03-10这几天很流行,我敢说一个该死的好主意,用组件构建网站。 我们不是一个一个地构建整个页面,而是构建一个组件系统(想想:搜索表单、文章卡片、菜单、页脚),然后将站点与这些组件拼凑在一起。
像 React 和 Vue 这样的 JavaScript 框架非常强调这个想法。 但是,即使您根本不使用任何客户端 JavaScript 来构建站点,也不意味着您必须放弃使用组件构建的想法! 通过使用 HTML 预处理器,我们可以构建一个静态站点,并且仍然可以获得将站点及其内容抽象为可重用组件的所有好处。
静态网站如今风靡一时,这是理所当然的,因为它们快速、安全且托管成本低廉。 甚至 Smashing Magazine 也是一个静态网站,信不信由你!
让我们来看看我最近使用这种技术建立的一个网站。 我使用 CodePen Projects 来构建它,它提供 Nunjucks 作为预处理器,非常适合这项工作。
具有一致页眉、导航和页脚的四页网站
这是一个微型网站。 它不需要一个成熟的 CMS 来处理数百个页面。 它不需要 JavaScript 来处理交互性。 但它确实需要一些共享相同布局的页面。
单独的 HTML 并没有很好的解决方案。 我们需要的是进口。 像 PHP 这样的语言使用<?php include "header.php"; ?>
这样的东西使这变得简单。 <?php include "header.php"; ?>
,但静态文件主机不会(故意)运行 PHP,单独的 HTML 也无济于事。 幸运的是,我们可以使用 Nunjucks 预处理包含。
在这里创建一个布局非常有意义,包括表示页眉、导航和页脚的 HTML 块。 Nunjucks 模板具有块的概念,它允许我们在使用布局时将内容插入该位置。
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>The Power of Serverless</title> <link rel="stylesheet" href="/styles/style.processed.css"> </head> <body> {% include "./template-parts/_header.njk" %} {% include "./template-parts/_nav.njk" %} {% block content %} {% endblock %} {% include "./template-parts/_footer.njk" %} </body>
请注意,包含的文件的名称类似于_file.njk
。 这不是完全必要的。 它可能是header.html
或icons.svg
,但它们的名称是这样的,因为 1) 以下划线开头的文件有点标准的方式来表示它们是部分的。 在 CodePen 项目中,这意味着它们不会尝试单独编译。 2)通过命名它.njk
,如果我们愿意,我们可以在那里使用更多的 Nunjucks 东西。
这些位都没有任何特别之处。 它们只是用于我们四个页面中的每个页面的一小部分 HTML。
<footer> <p>Just a no-surprises footer, people. Nothing to see here.<p> </footer>
通过这种方式,我们可以进行一次更改,并将更改反映在所有四个页面上。
使用四个页面的布局
现在我们的四个页面中的每一个都可以是一个文件。 不过,让我们从index.njk
开始,在 CodePen 项目中,它会在您每次保存时自动处理并创建一个index.html
文件。
这是我们可以放入index.njk
以使用布局并在该块中删除一些内容的内容:
{% extends "_layout.njk" %} {% block content %} <h1>Hello, World!</h1> {% endblock %}
这将为我们购买一个功能齐全的主页! 好的! 四个页面中的每一个都可以做同样的事情,但在块中放置不同的内容,我们有一个易于管理的小四页站点。
作为记录,我不确定我是否会将这些小块称为我们重用组件。 我们只是提高效率并将布局分解成块。 我认为一个组件更像是一个可重用的块,它接受数据并使用该数据输出其自身的唯一版本。 我们会解决的。
进行主动导航
既然我们已经在四个页面上重复了相同的 HTML 块,是否可以将唯一的 CSS 应用于各个导航项以识别当前页面? 我们可以使用 JavaScript 并查看window.location
等,但我们可以在没有 JavaScript 的情况下做到这一点。 诀窍是在每个页面的<body>
上放置一个class
,并在 CSS 中使用它。
在我们的_layout.njk
中,我们让主体输出一个类名作为变量:
<body class="{{ body_class }}">
然后在我们在单个页面上调用该布局之前,我们设置该变量:
{% set body_class = "home" %} {% extends "_layout.njk" %}
假设我们的导航结构如下
<nav class="site-nav"> <ul> <li class="nav-home"> <a href="/"> Home </a> ...
现在我们可以针对该链接并根据需要应用特殊样式:
body.home .nav-home a, body.services .nav-services a { /* continue matching classes for all pages... */ /* unique active state styling */ }
哦,那些图标? 这些只是我放在文件夹中并包含的单个.svg
文件
{% include "../icons/cloud.svg" %}
这使我可以将它们设置为:
svg { fill: white; }
假设里面的 SVG 元素已经没有fill
属性。
在 Markdown 中创作内容
我的微型网站的主页上有大量内容。 我当然可以用 HTML 本身编写和维护它,但有时将这种类型的东西留给 Markdown 会很好。 Markdown 感觉写起来更干净,当它有很多副本时可能更容易看。
这在 CodePen 项目中非常容易。 我创建了一个以.md
结尾的文件,该文件将自动处理为 HTML,然后将其包含在index.njk
文件中。
{% block content %} <main class="centered-text-column"> {% include "content/about.html" %} </main> {% endblock %}
构建实际组件
让我们将组件视为可重复的模块,它们通过传入数据来创建自己。 在像 Vue 这样的框架中,您将使用单个文件组件,这些组件是模板化 HTML、作用域 CSS 和特定于组件的 JavaScript 的隔离位。 这太酷了,但我们的微型网站不需要任何花哨的东西。
我们需要基于一个简单的模板创建一些“卡片”,所以我们可以构建这样的东西:
在 Nunjucks 中构建类似的可重复组件涉及使用他们所谓的宏。 宏非常简单。 它们就像HTML 有功能一样!
{% macro card(title, content) %} <div class="card"> <h2>{{ title }}</h2> <p>{{ content }}</p> </div> {% endmacro %}
然后根据需要调用它:
{{ card('My Module', 'Lorem ipsum whatever.') }}
这里的整个想法是分离 data 和 markup 。 这给了我们一些非常明确和切实的好处:
- 如果我们需要对 HTML 进行更改,我们可以在宏中进行更改,并且在使用该宏的任何地方都会更改。
- 数据没有与标记纠缠在一起
- 数据可能来自任何地方! 就像我们在上面所做的那样,我们将数据直接编码到对宏的调用中。 或者我们可以引用一些 JSON 数据并对其进行循环。 我敢肯定,您甚至可以想象这样一种设置,其中 JSON 数据来自某种无头 CMS、构建过程、无服务器功能、cron 作业或其他任何东西。
现在我们有了这些结合了数据和标记的可重复卡片,正是我们所需要的:
制作尽可能多的组件
你可以接受这个想法并坚持下去。 例如,想象一下 Bootstrap 本质上是一堆你遵循 HTML 模式使用的 CSS。 您可以将这些模式中的每一个都设为宏,并根据需要调用它们,本质上是对框架进行组件化。
如果您愿意,您可以嵌套组件,采用一种原子设计理念。 Nunjucks 也提供逻辑,这意味着您可以通过传入不同的数据来创建条件组件和变体。
在我制作的简单网站中,我为网站的想法部分制作了不同的宏,因为它涉及略有不同的数据和略有不同的卡片设计。
针对静态站点的快速案例
我可能会争辩说,大多数网站都受益于基于组件的架构,但只有一些网站适合静态。 我在很多网站上工作,在这些网站上使用后端语言是合适且有用的。
我的一个网站,CSS-Tricks,有一些东西,比如用户登录,权限系统有点复杂:论坛、评论、电子商务。 虽然这些事情都没有完全阻止静态工作的想法,但我经常很高兴我有一个数据库和后端语言可以使用。 它可以帮助我构建我需要的东西,并将东西放在一个屋檐下。
前进,拥抱静态生活!
请记住,以我们在本文中所做的方式进行构建的好处之一是最终结果只是一堆静态文件。 易于托管、快速且安全。 然而,我们不必放弃以对开发人员友好的方式工作。 该站点将来易于更新和添加。
- 最后一个项目是一个名为 The Power of Serverless for Front-End Developers 的微型网站 (https://thepowerofserverless.info/)。
- 如果您问我,静态文件托管是无服务器运动的一部分。
- 您可以直接在 CodePen 上查看所有代码(甚至为自己复制一份)。 它使用 CodePen 项目完全在 CodePen 上构建、维护和托管。
- CodePen Projects 处理我们在这里谈到的所有 Nunjucks 的东西,以及 Sass 处理和图像托管之类的东西,我在网站上利用了这些东西。 您可以在本地复制相同的内容,例如,基于 Gulp 或 Grunt 的构建过程。 这是一个样板项目,您可以启动它。