Blog

Blog

PHODAL

Serverless 应用开发指南:使用 Lambda 构建 Hexo 静态网站

在尝试了一系列的 Serverless 相关的 DEMO 之后,终于要写自己的第三个 Lambda 服务。在那之前,最复杂的要数《Serverless 应用开发指南:Serverless + Express 的 React 服务端渲染》了。毕竟,要进行 Babel 打包,结合 Express 进行服务端渲染等等。

在这篇文章里,我们将尝试使用 Lambda 函数来生成 Hexo 静态网站。要在服务端进行这样的构建,需要三个步骤:

  • 获取 Hexo 博客代码
  • 生成 Hexo 静态网站文件
  • 上传静态文件到 S3

在这两天的把玩里,遇到的最大的坑里,Hexo 官方提供的 API 文档不是很详细。对于 Hexo 来说,它实际上只对最终用户提供一个 CLI 即可。与此同时,对于多数的用户来说,它们可以使用 Travis CI 等来自动构建、发布。

因此,这篇文章实质上的意义并没有那么大。

Serverless Hexo 代码原理

整个 Hexo 的打包过程,如上所说。

获取 Hexo 博客代码

起先我用的是 nodegit 来获取代码,但是发现在 Lambda 上不工作。于是我采用了传统的 request 方式来获取:

  request.get(`${repoAddress}/archive/master.zip`)
    .pipe(fs.createWriteStream(blogZipFile))
    .on('close', (repo) => {
  })

将这个文件保存了,随后使用 unzip 解压出文件夹。

fs.createReadStream(blogZipFile)
    .pipe(unzip.Extract({path: tmpPath}))
    .on('close', function () {
    })

接着就是执行 hexo 的脚本了。

生成 Hexo 静态网站文件

最开始的时候,我使用的是官方的示例:

var hexo = new Hexo(repoUnzipPath, {
  config_path: `${repoUnzipPath}/_config.yml`
});


  hexo.init().then(() => {
    console.info("Running Hexo Generate");
    hexo.call("generate", {force: true})
      .then(() => {
        console.info(`Hexo done`);
        hexo.exit();
      });
   });

然后发现生成的内容有问题,找了很久才找到原因。对于这些配置不在路径上的项目来说,需要手动加载插件:

hexo.loadPlugin(require.resolve('hexo-generator-archive'));
hexo.loadPlugin(require.resolve('hexo-generator-category'));
hexo.loadPlugin(require.resolve('hexo-generator-index'));
hexo.loadPlugin(require.resolve('hexo-generator-tag'));
hexo.loadPlugin(require.resolve('hexo-renderer-ejs'));
hexo.loadPlugin(require.resolve('hexo-renderer-marked'));
hexo.loadPlugin(require.resolve('hexo-renderer-stylus'));

并且,又得按顺序执行,而不是异步。因此,这里的函数需要进一步优化。

上传静态文件到 S3

等文件生成完,我们就可以使用 walk 来遍历文件的内容,并上传。

var walker  = walk.walk(`${repoUnzipPath}/public`, { followLinks: false });
walker.on('file', function(root, stat, next) {
  let filePath = root.toString().substring(`${repoUnzipPath}/public`.length + 1);
  let fileName = stat.name;
  fs.readFile(path.join(root, stat.name), (error, fileContent) => {
    if (error) {
      throw error;
    }
    S3.putObject({
      Bucket: bucketName,
      Key: path.join(filePath, fileName),
      Body: fileContent
    }, (res) => {
      console.log(res);
      console.log(`Successfully uploaded '${fileName}'!`);
    });
  });
  next();
});

上传完后,发现了一个问题:文件的 type 没有指定。因此,整个网站处于不能运行的,待优化状态。不过,这里简单的写几个 if 就能解决了。

Serverless Hexo 使用

首先,依旧是安装这个服务。

serverless install -u https://github.com/phodal/serverless-hexo -n serverless hexo

然后执行

yarn install

接着修改 serverless.yml

    environment:
      USER_NAME: phodal
      REPO_NAME: serverless-hexo-blog-static-files
      BUCKET_NAME: static.wdsm.io

将其中的 USER_NAMEREPO_NAMEBUCKET_NAME 将成你的项目的名字。

然后就可以执行部署了:

serverless deploy

相应的部署日志如下:

..............
Serverless: Stack update finished...
Service Information
service: serverless-hexo
stage: dev
region: us-east-1
stack: serverless-hexo-dev
api keys:
  None
endpoints:
  GET - https://jf1audrhvg.execute-api.us-east-1.amazonaws.com/dev/create
functions:
  create: serverless-hexo-dev-create
Serverless: Removing old service versions...

接着访问 API 执行构建:

curl https://jf1audrhvg.execute-api.us-east-1.amazonaws.com/dev/create

再查看相应的日志

serverless logs -f create -t

如下所示:

START RequestId: d9ae1913-bed0-11e7-bdca-19fc04634b74 Version: $LATEST
2017-11-01 14:49:50.048 (+08:00)    d9ae1913-bed0-11e7-bdca-19fc04634b74    undefined
2017-11-01 14:49:50.049 (+08:00)    d9ae1913-bed0-11e7-bdca-19fc04634b74    Download https://github.com/phodal/serverless-hexo-blog-static-files
2017-11-01 14:49:50.264 (+08:00)    d9ae1913-bed0-11e7-bdca-19fc04634b74    Running Hexo Generate
INFO  Start processing
INFO  Files loaded in 618 ms
INFO  Generated: index.html
INFO  Generated: archives/index.html
INFO  Generated: fancybox/blank.gif
INFO  Generated: fancybox/jquery.fancybox.css
INFO  Generated: fancybox/jquery.fancybox.pack.js
INFO  Generated: fancybox/jquery.fancybox.js
INFO  Generated: fancybox/fancybox_loading.gif
INFO  Generated: fancybox/fancybox_loading@2x.gif
INFO  Generated: fancybox/fancybox_overlay.png
INFO  Generated: fancybox/fancybox_sprite.png
INFO  Generated: fancybox/fancybox_sprite@2x.png
INFO  Generated: archives/2017/11/index.html
INFO  Generated: css/style.css
INFO  Generated: css/fonts/FontAwesome.otf
INFO  Generated: fancybox/helpers/fancybox_buttons.png
INFO  Generated: archives/2017/index.html
INFO  Generated: css/fonts/fontawesome-webfont.eot
INFO  Generated: css/fonts/fontawesome-webfont.woff
INFO  Generated: js/script.js
INFO  Generated: fancybox/helpers/jquery.fancybox-buttons.css
INFO  Generated: fancybox/helpers/jquery.fancybox-buttons.js
INFO  Generated: fancybox/helpers/jquery.fancybox-media.js
INFO  Generated: fancybox/helpers/jquery.fancybox-thumbs.css
INFO  Generated: fancybox/helpers/jquery.fancybox-thumbs.js
INFO  Generated: css/images/banner.jpg
INFO  Generated: css/fonts/fontawesome-webfont.svg
INFO  Generated: css/fonts/fontawesome-webfont.ttf
INFO  Generated: 2017/11/01/hello-world/index.html
INFO  28 files generated in 1.9 s
2017-11-01 14:49:52.780 (+08:00)    d9ae1913-bed0-11e7-bdca-19fc04634b74    Hexo done
2017-11-01 14:49:53.154 (+08:00)    d9ae1913-bed0-11e7-bdca-19fc04634b74    Successfully uploaded
END RequestId: d9ae1913-bed0-11e7-bdca-19fc04634b74
REPORT RequestId: d9ae1913-bed0-11e7-bdca-19fc04634b74  Duration: 3886.34 ms    Billed Duration: 3900 ms    Memory Size: 1024 MB    Max Memory Used: 161 MB

就可以看到整个过程了。

完成后,记得执行以下的命令省点钱。

serverless remove

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签