docsify文档网站部署与配置

前言

为了做好技术资料的文档和积累,自己想搭建一个类似wiki的文档网站,一番搜索之后感觉docsify比较适合目前的需求,然后又根据需要做了一些配置,特意记录下来。

docsify基本用法

简要介绍

一个神奇的文档网站生成器。

docsify 可以快速帮你生成文档网站。不同于 GitBook、Hexo 的地方是它不会生成静态的 .html 文件,所有转换工作都是在运行时。如果你想要开始使用它,只需要创建一个 index.html 就可以开始编写文档并部署。

特性

  • 无需构建,写完文档直接发布
  • 容易使用并且轻量 (压缩后 ~21kB)
  • 智能的全文搜索
  • 提供多套主题
  • 丰富的 API
  • 支持 Emoji
  • 兼容 IE11
  • 支持服务端渲染 SSR

使用步骤

  1. 全局安装 docsify-cli 工具,可以方便地创建及在本地预览生成的文档;

    1
    npm i docsify-cli -g
  2. 初始化项目,如果想在项目的 ./docs 目录里写文档,直接通过 init 初始化项目;

    1
    docsify init ./docs

    初始化成功后,可以看到 ./docs 目录下创建的几个文件

    • index.html 入口文件
    • README.md 会做为主页内容渲染
    • .nojekyll 用于阻止 GitHub Pages 忽略掉下划线开头的文件

    直接编辑 docs/README.md 就能更新文档内容,如果需要创建多个页面,或者需要多级路由的网站,在 docsify 里也能很容易的实现。例如创建一个 guide.md 文件,那么对应的路由就是 /#/guide

    假设你的目录结构如下:

    1
    2
    3
    4
    5
    6
    7
    .
    └── docs
    ├── README.md
    ├── guide.md
    └── zh-cn
    ├── README.md
    └── guide.md

    那么对应的访问页面将是

    1
    2
    3
    4
    docs/README.md        => http://domain.com
    docs/guide.md => http://domain.com/guide
    docs/zh-cn/README.md => http://domain.com/zh-cn/
    docs/zh-cn/guide.md => http://domain.com/zh-cn/guide
  3. 本地预览,通过运行 docsify serve 启动一个本地服务器,。默认访问地址 http://localhost:3000

    1
    docsify serve docs
  4. 修改配置项,在index.html中的 window.$docsify 里可以修改配置项,例如

    1
    2
    3
    4
    5
    6
    7
    <script>
    window.$docsify = {
    repo: 'docsifyjs/docsify',
    maxLevel: 3,
    coverpage: true,
    };
    </script>

更多docsify用法,参考docsify官方文档;更多命令行工具用法,参考 docsify-cli 文档

docsify进阶用法

说是“进阶用法”,其实大部分在docsify的文档中可以找到,这里简单记录几个。

图片缩放浏览

这个在官方文档中有记录,使用medium-zoom插件即可实现Medium风格的图片放大浏览。

index.html中添加代码如下:

1
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>

PDF文件嵌入

使用docsify-pdf-embed:)插件实现PDF的嵌入,只需要在index.html导入docsify.min.js之后,导入所需要以下内容(后面两行二选一即可):

1
2
3
4
5
6
<!-- PDFObject.js is a required dependency of this plugin -->
<script src="//cdnjs.cloudflare.com/ajax/libs/pdfobject/2.1.1/pdfobject.min.js"></script>
<!-- This is the source code of the pdf embed plugin -->
<script src="path-to-file/docsify-pdf-embed.js"></script>
<!-- or use this if you are not hosting the file yourself -->
<script src="//unpkg.com/docsify-pdf-embed-plugin/src/docsify-pdf-embed.js"></script>

这样,如果需要在.md文件中嵌入PDF,只需要用类似插入代码的方式:

1
2
3
4
5
6
### Here are some of your previous markdown contents
blah blah blah

```pdf
path-to-the-pdf-file
```

其他用法参加GitHub上的项目介绍:lazypanda10117/docsify-pdf-embed: A simple plugin for embedding PDF in Docsify. (github.com)

自定义错误页

这里所说的“自定义错误页”是在进入docsify文档之后,如果没有找到目标文档时的404错误页。docsify本身支持通过windows.docsifynotFoundPage配置,在找不到指定页面时加载自定义的404页面:

1
2
3
window.$docsify = {
notFoundPage: 'my404.md',
};

但是,这种自定义方法只能加载.md文件,为了像许多自定义的页面一样美观,需要将自定义的404html页以文件的方式键入到404markdown文件中

根据官方文档介绍,docsify 4.6 开始支持嵌入任何类型的文件到文档里你可以将文件当成 iframevideoaudio 或者 code block,如果是 Markdown 文件,甚至可以直接插入到当前文档里。

显然嵌入的404html页最终会以iframe的形式呈现出来,为了保证展示的效果,还需要添加一些css,最终使用的404md文件如下:

1
2
3
4
5
6
7
8
[filename](_media/404.html ':include :type=iframe style="
width: 125%;
top: -75px;
left: -12.5%;
position: absolute;
height: 100vh;
right: 0;
"')

效果如下图所示:

docsify自定义404错误页

这样,关于docsify的配置就基本完成了。

Nginx配置

docsify解决了文档网站内容生成的问题,还需要一个Web服务器提供服务,因为docsify只是静态页面,使用nginx即可。

基本配置

nginx的基本配置很简单,只要提供最简单的Web服务即可:

1
2
3
4
5
6
7
8
9
10
11
server {
listen your_listening_port;
allow allowed_ip_addresses;
deny all;
root /where_docsify_locates/docs/;
index index.html;

location / {
autoindex on;
}
}

其中的your_listening_port是nginx监听的端口,allowed_ip_address是允许访问的IP地址(比如只允许反向代理的服务器地址),where_docsify_locates是docsify-cli创建项目所在的目录。

Basic auth验证

身份验证框架中最常用的HTTP认证方案是 “HTTP Basic authentication”(RFC 7617)。该方案中规定使用"用户的ID/密码"作为凭证信息,并且使用 base64算法进行编码。由于用户 ID 与密码是是以明文的形式在网络中进行传输的(base64 可逆),所以基本验证方案并不安全,建议配合 HTTPS协议使用。

在nginx中开始Basic auth主要包括以下步骤:

  • 使用 auth_basic 指令,启用 HTTP基本身份验证。
  • 使用 auth_basic_user_file 指令, 指定帐密文件位置。
  • 如果没有 Apache htpasswd 命令,可以使用 openssl 命令代替。

具体如下:

  1. 创建htpasswd账号密码文件

    1
    2
    3
    4
    5
    6
    # 格式每行一个账户
    用户名:密码

    # nginx 可以直接使用 Apache 的 htpasswd命令创建的密码文件。
    # 例如创建一个文件名为 htpasswd、帐号为 username、密码为 password。
    htpasswd -bdc htpasswd username password

    如果没有 htpasswd命令,也可以使用 openssl passwd 命令代替。

    1
    2
    3
    4
    5
    echo  -n 'username:' >> .htpasswd
    openssl passwd -apr1 password >> .htpasswd

    cat -A .htpasswd
    username:$apr1$zUcStfd8$vlKz3z77Z1HToLyQSpVys/
  2. 在nginx中添加auth_basic认证

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    server {
    listen your_listening_port;
    allow allowed_ip_addresses;
    deny all;
    root /where_docsify_locates/docs/;
    index index.html;
    location / {
    auth_basic "Please enter your username and password";
    auth_basic_user_file /where_your_htpassd_locates/htpasswd;
    autoindex on;
    }
    }
  3. 重启 nginx

    1
    nginx -t && nginx reload

nginx反向代理

在此基础上,我又使用另外一台服务器提供反向代理,并且只允许反向代理访问文档网站(就是上面的allowdeny限制的)。增加反向代理主要实现了以下两个作用:

  1. 开启HTTPS访问。在同一端口上处理http和https,并将http自动重定向为https。配置示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    server {
    listen 7000 ssl;

    ssl_certificate /path/to/ssl_certificate.cer;
    ssl_certificate_key /path/to/ssl_certificate_key.key;
    ssl_client_certificate /path/to/ssl_client_certificate.cer;

    error_page 497 301 =307 https://89.89.89.89:7000$request_uri;

    location / {
    proxy_pass http://89.89.89.89:3000/;

    proxy_pass_header Server;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-Protocol $scheme;
    }
    }

    其中 error_page 497 301 =307 https://89.89.89.89:7000$request_uri;实现了对http的重定向,并且避免了对http方法的改变。具体参见:

    https://stackoverflow.com/questions/8768946/dealing-with-nginx-400-the-plain-http-request-was-sent-to-https-port-error

    https://blog.51cto.com/u_10309478/2089060

  2. 自定义错误页。主要涉及到HTTP Basic auth认证失败的401错误或者页面不存在的404错误。与前面docsify页面内的404错误页稍有不同,这里相当于是整个网页的404错误。通过nginx的proxy_intercept_errors on实现自定义错误页。配置示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    server {
    proxy_intercept_errors on;
    error_page 404 /errorPages/404.html;
    error_page 401 /errorPages/401.html;
    location /errorPages/ {
    alias /$errors_dir/;
    }
    }

效果如下所示:

验证失败的401页面

整个页面的404效果

小结

以上就是我用nginx+docsify搭建文档网站的主要配置,主要实现了以下功能:

  1. nginx提供docsify服务;
  2. nginx提供反向代理,https访问并自动重定向http;
  3. 自定义文档不同情况的错误页。

此外,在Windows下基于IIS实现了docsify的Basic auth认证。另外如果用Python的Web框架,例如Fast API,或者Rust的Web框架,例如actix-web,可以实现更丰富的功能。

参考资料

  1. https://docsify.js.org/#/zh-cn/
  2. https://serverfault.com/questions/47876/handling-http-and-https-requests-using-a-single-port-with-nginx
  3. https://www.yisu.com/zixun/18354.html
  4. https://devbeep.com/html-404-page-templates/
  5. https://github.com/tsparticles/404-templates