Eleventy入门 福州小程序开发

Eleventy入门 福州小程序开发

时间:2020-10-1 作者:gykj

Eleventy(或11ty)是Node.js静态站点生成器(SSG)。SSG在构建时执行大多数渲染工作,以创建一组静态HTML,CSS和JavaScript文件。生成的页面不必具有服务器端依赖项,例如运行时或数据库。

这带来了几个主要好处:

  • 托管很简单:您正在提供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的配置文件。这个简单的示例代码返回一个对象,该对象指定以下内容:

  1. src源文件的源目录
  2. build在其中创建网站文件的目录
// 11ty configuration
module.exports = config => {

  // 11ty defaults
  return {

    dir: {
      input: 'src',
      output: 'build'
    }

  };
};

要构建站点并启动由Browsersync驱动的实时重新加载服务器,请输入以下内容:

npx eleventy --serve

Eleventy呈现在src目录中找到的所有内容,并将结果内容输出到build

Eleventy入门 福州小程序开发

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

通常建议零售价$ 11.95 此致完全免费

$ 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来访问创建的单个文件。

Eleventy入门 福州小程序开发

在创建的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服务器。CmdC

注意:在网站开发过程中几乎不需要停止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.njkNunchucks模板进行布局。默认情况下,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。(它使用safeNunchucks过滤器来输出HTML,而不会转义引号和尖括号。)

这两个{% include %}定义引用了模板中包含的文件。在创建一个HTML头文件src/_includes/partials/htmlhead.njk,该文件还使用页面的titledescription

<!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:必须在菜单中所需的每个页面中定义最重要的部分。本节设置以下内容:

  1. key页面菜单的A。这可能与相同,title但通常更短。
  2. 可选的parent,引用父页面的key
  3. 可选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
‐‐‐

注意:使用order10或更高倍数的值可以稍后在其他页面之间插入页面,而无需任何手动重新编号。

现在可以在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加载任何页面以查看菜单。

Eleventy入门 福州小程序开发

现在,您可以导航到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简码传递三个参数:

  1. 通过该eleventyNavigation()函数过滤的每个页面,该函数返回页面对象的分层列表。每个页面定义一个children子页面数组。
  2. 目前page
  3. 可选的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.mdarticle-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.

每个帖子指定一个日期和一个或多个标签(HTMLCSS在这里使用)。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 /:

Eleventy入门 福州小程序开发

创建文章/博客索引页面

尽管您可以从一个帖子导航到另一个帖子,但在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.

前端物料配置执行以下操作:

  1. 它设置标准page.njk模板。
  2. 它将页面添加为articles菜单项。
  3. 它创建一个名为pagelistfrom的列表collections.post,将其反向(最新的帖子优先),并且每页最多允许三项。Eleventy将撰写六篇文章,生成两页,每页三篇文章。

现在修改其中的contentsrc/_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 /上的三篇最新文章:

Eleventy入门 福州小程序开发

接下来的链接指向的文章在进一步网页的http://本地主机:8080 /用品/ 1 /。

创建自定义过滤器

上面的屏幕截图显示的日期是不友好的JavaScript字符串。Eleventy提供了可以修改数据并返回字符串的过滤器。当Markdown生成的内容通过safe过滤器输出未编码的HTML:时,您已经看到了这种用法{{ content | safe }}

lib/filters/dateformat.js使用以下代码创建一个新文件。它导出两个函数:

  1. ymd()它将日期YYYY-MM-DD转换为HTMLdatetime属性的机器可读格式,并且
  2. 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.jsreturn语句之前的任何位置注册过滤器:

  /* --- 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使用dateymddatefriendly以及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为使用dateymddatefriendly过滤器:

{% if post.data.date %}<p class="time"><time datetime="{{ post.data.date | dateymd }}">{{ post.data.date | datefriendly }}</time></p>{% endif %}

重新启动构建npx eleventy --serve并刷新浏览器。加载任何文章以查看友好的日期,格式化的字数和阅读时间估计:

Eleventy入门 福州小程序开发

产生的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

  1. 一种data()将最重要的设置作为JavaScript对象返回的方法
  2. 一个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"
}

Eleventy入门 福州小程序开发

使用转换处理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.jsreturn.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.jsreturn语句之前的某个位置注册转换:

  // 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.jsreturn语句之前注册转换:

  // 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,您的缩小脚本将加载并运行。现在可以通过其屡获殊荣的荣耀来查看最终站点:

Eleventy入门 福州小程序开发

建立生产现场

对网站感到满意后,您可以在生产模式下构建它,而无需源地图和其他开发选项。

删除build文件夹并在Linux / macOS上设置ELEVENTY_ENVproduction

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错误页面并生成适当的代码来处理它(例如.htaccessApache的文件)。
  • 生成其他根文件,例如favicon.ico或Service Worker。
  • 使用Eleventy的分页功能从data生成页面。
  • 并为将WordPress内容导入静态页面获得加分。福州小程序开发

Eleventy为您服务吗?

静态网站生成器是任何主要提供内容更改频率不高的网站的理想解决方案。可以在Git存储库中对页面进行版本控制,开发更易于控制,测试简单,性能出色并且安全性问题消失了。(我wp-login.php对服务器日志中所有失败的尝试感到无比开心!)

有许多SSG可供选择,但是如果您满足以下条件,Eleventy是一个不错的选择:

  • 是SSG的新手或对您当前的选择不满意
  • 例如Node.js,并希望在开发过程中使用JavaScript
  • 想跳上最新的酷事!

祝好运!

版权所有:https://www.eraycloud.com 转载请注明出处