手把手带逛11ty第一集:介绍、安装与配置

Eleventy

什么是eleventy

这是一个静态站点生成工具,NodeJS实现的。这玩意主要流行于个人博客搭建。

常见的个人博客项目的需求,其实就是把markdown文档归置起来,转成网页。再额外加一些索引页面的工作。eleventy特别适合做这种工作。

当然用它也能做其它类型的静态站点,这玩意只是个工具,怎么用,用在哪个领域,全看你。

HelloWorld 项目搭建

首先你需要安装NodeJS,然后按下面的流程走就差不多了:

# 为新项目创建一个新目录
mkdir HelloWorld
cd HelloWorld

# 把这个新目录初始化成一个新的前端项目
npm init -y

# 养成好习惯:上Git
git init

# 安装核心的npm包
npm install --save-dev --save-exact @11ty/eleventy

接下来我们来做两件事:一是要在package.json中添加一些方便的script定义,另一个是创建一个名为index.md的markdown文档

首先,把我们的package.json写成类似下面这样。注意核心的点在于scripts中的定义,其它内容无关紧要

{
  "name": "HelloWorld",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "build": "eleventy",
    "start": "eleventy --serve"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@11ty/eleventy": "2.0.1"
  }
}

然后我们的名为index.md的markdown文档就简单的写成下面这样:

# 二流程序员的核心品质

复制粘贴一把梭,增删改查小能手。

会写`Hello World`就敢说自己精通某个语言、框架

现在我们的目录结构如下所示:

HelloWorld
├─index.md
└─package.json

接下来就是见证奇迹的时刻:安装依赖,然后执行start脚本!

npm install
npm start

然后你在浏览器访问http://localhost:8080就能看到,我们把一个markdown文档转化成了静态网页。

HelloWorld项目背后都发生了什么?

说起来也简单,我们在执行start脚本的时候,实际调用的是eleventy --serve命令行。这个命令背后做了两件事:

  1. 把目录下的index.md文档转化成了一个静态网页,并把转化后的结果放在了_site目录中
  2. 把整个_site目录托管在了当前主机的8080端口上

这个例子虽然简单,但基本阐明了eleventy的功能:

  1. 把文档转化为静态网页站点,并打包在一个目录中。这个目录名默认是_site
  2. 可以把_site目录视为“打包”成果,并且这个打包成果可以直接托管到诸如nginx或者Apache之类的web server上,这就是所谓的“发布”的过程

如果你只想打包,不想进行本地托管的话,执行build脚本也行,它背后调用的是eleventy命令行:没有带--serve参数。

另外如果想更改托管的端口号,就把start脚本的定义改成诸如eleventy --serve --port 5453这种形式

来说一说配置

eleventy有个优点,就是“约定大于配置”。在上面的HelloWorld项目里,我们没有写任何配置相关的东西,eleventy就知道:

  1. 它搜索扫描出了index.md
  2. 它把打包结果放在了默认的_site目录中

eleventy虽然是个简单的框架,但也是有一些可配置项的,不过我不会现在就把所有的配置项都一股脑的扔在你脸上,因为很多配置项相关的功能和特性我们还没有接触。

但我们至少现在应该知道:如何更改默认的配置。比如现在有一个天然的需求就是,我想把index.md挪到一个叫src的子目录中去,还想把打包的目的地改成dist目录,怎么做?

简单:在项目目录中新建一个名为.eleventy.js的文件,然后以module.exports的形式更改配置就行了。虽然module.exports的内容可以直接是一个JS对象,然后在对象中写上要更改的配置项的新值,但建议大家使用回调函数形式:没麻烦多少。如下所示:

module.exports = function(config) {
    return {
        dir: {
            input: "src",
            output: "dist"
        }
    }
}

再然后把index.md挪到src目录下,再跑一次npm start就能看到效果了

项目目录结构与站点的路径之间的映射关系

现在,我们再在src目录下添加一个名为post1.md的文档,内容随便写,比如下面这样:

# 一篇没有意义的文档

啦啦啦啦啦啦啦

再次运行npm start,有如下效果:

  1. 首页依然是index.md转化成的网页,可以通过三个地址访问到
    1. 网站根目录:http://localhost:8080/
    2. 显式指定html文档路径:http://localhost:8080/index.html
    3. 指定html文档路径,但不带扩展名:http://localhost:8080/index
  2. post1.md转化成的网页,可以通过三个地址访问到
    1. http://localhost:8080/post1/
    2. http://localhost:8080/post1/index
    3. http://localhost:8080/post1/index.html

如果你去看dist目录下的打包结果,会发现目录结构如下所示:

dist
├─post1
|  └─index.html
└─index.html

如果你有过将网页部署到nginx之类的web server上的经验,你就知道,以nginx为例,当用户访问一个路径,比如:http://host/a/b/c的时候,nginx其实返回的是网站目录中的a/b/c/index.html文件。但与eleventy --serve在本地开启的简易web server相比,nginx并不会把http://host/a/b/c/index映射到a/b/c/index.html文件上去。

了解了这个东西,其实就说明了,从项目中的文档文件路径,到最终用户访问到的路径之间,有两层转换

  1. 首先是eleventy以一定的规则,把配置文件中${config.dir.input}目录下的文档会打包到${config.dir.output}目录中去。最终我们会把${config.dir.output}目录部署在某个web server上
  2. web server会有一些约定俗成的规则,把http请求路径映射到目录结构中去

第2步是可以通过web server的配置,比如nginx的配置来控制的,但多数情况下,约定俗称的规则已经足够符合直觉。现在问题是第一步:

  1. 为什么src/index.md映射的是dist/index.html,而不是dist/index/index.html
  2. 为什么src/post1.md映射的是dist/post1/index.html,而不是dist/post1.html

这里就没什么道理可讲了,eleventy在做文档转化的时候,具体的映射规则可以用下面的不严谨语言来描述:

  1. 首先,算出这个文档与{config.dir.input}之间的差值(或者说是相对路径),由于我们在配置中设定了config.dir.input == "src",所以简单来说就是把src去掉。然后再把文档的扩展名去掉
    • src/index.md ==> /index
    • src/post1.md ==> /post1
  2. 这个文档如果以index为名,则把/index去掉
    • src/index.md ==> /index ==> 空串
    • src/post1.md ==> /post1 ==> /post1
  3. 然后再拼接上/index.html,在前面拼接上${config.dir.output}的值,就得到了最终映射出来的HTML文档路径
    • src/index.md ==> /index ==> 空串 ==> dist/index.html
    • src/post1.md ==> /post1 ==> /post1 ==> dist/post1/index.html