实现一个 Code Pen:(六)云函数生成网页缩略图

sxkk20082年前知识分享241

前言

在前面的文章中,我们已经实现了编辑器的功能,并且数据可以保存到云数据库,接下来我们需要生成缩略图的功能,目前掘金的的 code pen 还没有缩略图的功能,这是否是一个挑战呢?

缩略图生成方法

生成缩略图的方法可分为 2 种,一种是客户端生成,还有一种是服务端生成。

dom-to-img

客户端生成我第一个想到的是使用到一个库 dom-to-img

这个库,其主要原理是:

  • 将 html node 转化为 xml,设定命名空间

  • foreignObject 包裹 xml

  • 把内容变为了 svg

  • svg 变为 base64 的图片

    下面代码是最核心的源码中的一个函数 makeSvgDataUri

function makeSvgDataUri(node, width, height) {
  return Promise.resolve(node)
    .then(function (node) {
      node.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
      return new XMLSerializer().serializeToString(node)
    })
    .then(util.escapeXhtml)
    .then(function (xhtml) {
      return '' + xhtml + ''
    })
    .then(function (foreignObject) {
      return (
        '' +
        foreignObject +
        ''
      )
    })
    .then(function (svg) {
      return 'data:image/svg+xml;,' + svg
    })
}

使用这个库的好处是可以通过客户端生成,节省服务端资源。但不足的是用户的浏览器大小不一,所生成的图片大小也不一样, 所以在我们 code pen 缩略图场景中,客户端生成不合适。

Puppeteer

服务端生成缩略图,我想到的是使用 Puppeteer 生成网页截图,来到达生成缩略图的效果。

Puppeteer 可以将 Chrome 或者 Chromium 以无界面的方式运行(当然也可以运行在有界面的服务器上),然后可以通过代码控制浏览器的行为,即使是非界面的模式运行,Chrome 或 Chromium 也可以在内存中正确渲染网页的内容。

vercel

由于我使用的是 vercel 部署的,那么我们是否可以使用 vercel 来生成缩略图吗?

我在一顿搜索之后找一篇文章 《Generate Open Graph images on-demand with Next.js on Vercel》

核心代码如下。

import chromium from 'chrome-aws-lambda'
import playwright from 'playwright-core'

const getAbsoluteURL = (path) => {
  const baseURL = process.env.VERCEL_URL
    ? `https://${process.env.VERCEL_URL}`
    : 'http://localhost:3000'
  return baseURL + path
}

export default async function handler(req, res) {
  // Start the browser with the AWS Lambda wrapper (chrome-aws-lambda)
  const browser = await playwright.chromium.launch({
    args: chromium.args,
    executablePath: await chromium.executablePath,
    headless: chromium.headless,
  })
  // 创建一个页面,并设置视窗大小
  const page = await browser.newPage({
    viewport: {
      width: 1200,
      height: 630,
    },
  })
  // 从url path 拼接成完成路径
  const url = getAbsoluteURL(req.query['path'] || '')
  await page.goto(url, {
    timeout: 15 * 1000,
    waitUntil: 'networkidle',
  })
  await page.waitForTimeout(1000)
  // 生成png 的缩略图
  const data = await page.screenshot({
    type: 'png',
  })
  await browser.close()
  // 设置图片强缓存
  res.setHeader('Cache-Control', 's-maxage=31536000, stale-while-revalidate')
  res.setHeader('Content-Type', 'image/png')
  // 设置返回 Content-Type 图片格式
  res.end(data)
}

chrome-aws-lambda 是为了 serverless 环境定制的 chrome 内核,包大小比较小,我将这段代码部署上去,通过 url 拼接的方式访问,我们就可以生成当前页面的缩略图了;

大家可以通过 https://code.runjs.cool/api/thumbnail?path=/pen/create 这个地址访问体验。 虽然有点慢,但是可以生成缩略图

vercel 生成的缩略图

有个问题就是,右上角的“保存”无法显示,查了下github chrome-aws-lambda 不包含任何字体,所以要支持中文,先要加载中文字体

readme 中有 demo

await chromium.font('/var/task/fonts/NotoColorEmoji.ttf')
// or
await chromium.font('https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf')

字体可以下载阿里巴巴普惠体,由于中文字体比较大,我就没有尝试,既然速度慢,那能否试试国内的云环境呢?

uniapp

由于我使用的云存储是 uniapp,那么我将尝试下 uniapp 的云函数。

本地尝试

于是我建立了一个云函数,然后在本地运行云函数。

首先安装使用 npm 安装 puppeteer npm i puppeteer

输入云函数代码

const puppeteer = require('puppeteer')

exports.main = async (event, context) => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  await page.goto('https://baidu.com')
  const path = `${__dirname}/img.png`
  await page.screenshot({ path })
  await browser.close()
  return 1
}

执行完成后就在本地生成img.png文件,效果如下图

puppeteer 百度首页截图

没错,生成的是一张800*600 大小的浏览器截图,感觉没问题了。

阿里云

于是我就按这个逻辑写完了云函数,当我点击上传部署 的时候,HbuildX 就没有进度,一直处于上传中,查了下资料,应该是 puppeteer 本身依赖了 Chromium,Chromium 又依赖非常多的系统库,无法在云函数上安装完成。

但是我在阿里云官网找到了一篇文章

《Serverless 实战 —— 快速开发一个分布式 Puppeteer 网页截图服务》

按这篇文章讲述的是阿里云是支持 Puppeteer,由于 puppeteer 比较大,云函数会自动开通 NAS 服务(文件存储)

所以 uniapp 中选择服务商选择阿里云,云函数式不支持 puppeteer 的

腾讯云

那么腾讯云支持吗?后来我又查到腾讯云云函数中内置了 puppeteer,可以在文档中找到,注意(nodejs 16)已经不支持 puppeteer

于是我又尝试了腾讯云函数,代码如下

const puppeteer = require('puppeteer')

exports.main = async (event, context) => {
  const browser = await puppeteer.launch({
    headless: true,
    args: ['--no-sandbox', '--disable-setuid-sandbox'],
  })
  const page = await browser.newPage()
  await page.goto('https://baidu.com')
  const res = await page.screenshot()
  await browser.close()

  return {
    isBase64Encoded: true,
    statusCode: 200,
    headers: {
      'content-type': 'image/png',
      'Cache-Control': 's-maxage=31536000, stale-while-revalidate',
    },
    body: res.toString('base64'),
  }
}

此时不需要 package.json,上传后,云函数 URL 化,

体验地址:

https://tcb-mtsm4smjc8dbf7-8dkm6932475ab.service.tcloudbase.com/baidu

效果

腾讯云函数 puppeteer 缩略图

应该是满足了我们的需求。

小结

本文介绍了生成缩略图的方式

  1. dom-to-img 客户端生成,但是用户的浏览器大小不一,缩略图大小不一样。

  2. vercel 可以配合 chrome-aws-lambda 可以生成缩略图,但是必须要先加载字体。

  3. uniapp 免费的阿里云函数不支持 Puppeteer,可以直接使用阿里云的 serverles 服务,但是要开通 NAS。

  4. 腾讯云函数系统内置 Puppeteer,免安装,应该是比较不错的方案。

最后贴一下我项目地址和代码

预览地址:https://code.runjs.cool/pen/create

代码仓库:https://github.com/maqi1520/next-code-pen

以上就是本文全部内容,希望这篇文章对大家有所帮助,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端。

本文首发掘金平台,来源Ai知识分享博客

相关文章

https://retor.hr/

https://sedeblockchain.com/

https://dnaprojecten.nl/

web design trend 2023 example 1 https://nationalstudentshow.com/

https://anakaric.com/

https://yaremenko.design/

https://www.landa.as/es/

web design trend 2023 example https://selectedbase.com/

CSS First

在过去,我们通常依靠 JavaScript 来创造网站的视觉效果。但从那时起,CSS 已经发展到可以做很多复杂的事情,而这些事情是 JavaScript 无法做到的。三维变换、过滤器和新的 CSS 功能,如:选择器(has)、容器查询(@container)和层叠层(@layer),将使许多有趣的网页设计纯粹依靠 CSS 来实现。

因此,从今年开始,我们将看到网站减少对 JavaScript 的依赖来创造视觉效果。

https://redstapler.co/cool-css-text-light-effect-5-minutes-tutorial/

https://redstapler.co/3d-infinity-effect-css-tutorial/

https://codepen.io/seyedi/pen/zYoeLEv

3d transparent video https://redstapler.co/create-3d-effect-on-website-using-transparent-video-background/

2023 web 设计趋势

翻译一篇文章原文链接:https://redstapler.co/web-design-trends-2023/作者:TK在过去的一年里,我们在网页设计领域看到了很多令人兴奋的发展。而在这篇文章中,我...

AI技术控:如何应对人工智能的挑战及未来发展趋势

AI技术控:如何应对人工智能的挑战及未来发展趋势

  人工智能(AI)技术近年来快速发展,对各行各业产生了重大影响。然而,随着AI技术的迅猛发展,人们对其未来的发展趋势、产业革命的规模及对劳动力市场的影响仍存在很多疑虑和担忧...

AI识图:让图像智能化改变我们的生活

AI识图:让图像智能化改变我们的生活

  在当今数字化时代,人工智能(Artificial Intelligence,简称AI)技术正不断演进和应用于各个领域。其中,AI识图技术以其强大的图像分析和识别能力成...

盘点掘金 2021 高赞 Vue 文章

vue 中 Axios 的封装和 API 接口的管理作者: 愣锤点赞 4195收藏 4896阅读 200697分类 前端Vue 开发必须知道的 36 个技巧【近 1W 字】作者: 火狼 1点赞 415...

如果你会 TailwindCSS 我推荐 VSCODE 安装 这个插件tailwind-snippets 可以快速帮我们来发出一个常用的代码片段,大家可以在 https://www.tailwindsnippets.ml/snippets 查看效果,快速实现我们的 html 页面

tailwind-snippets 预览

部署

Vercel

Next.js 开发商 Vercel 获得最近 1.5 亿美元 D 轮融资。Vercel 注册什么的我就不讲了,建议使用GitHub 登录, 点击new project创建一个项目,这个项目可以从自己的 GitHub 库导入或者选择 Vercel 给的模板,Vercel 给的模板(下图)首先也会导入进自己的 GitHub 库,总之要先把内容导入进 GitHub 库才行。

Vercel 支持的框架

Vercel 为个人用户提供了

  1. 自动 HTTPS/SSL
  2. 带宽 100 GB
  3. 并发构建,每天 10 万次调用
  4. Serverless Function

所以 Vercel 不光支持静态网站也支持 nodejs 动态网站,如果想要其他后端语言

可以选择 heroku

heroku

Heroku 是一个支持多种编程语言的云平台,并且提供了 Heroku PostgresHeroku RedisApache Kafka on Heroku

Heroku 支持的语言

Heroku 虽然提供了比较全面的编程语言和数据库支持,免费用户还支持

  1. 使用 Git 和 Docker 部署
  2. 自定义二级域名
  3. 容器编排
  4. 自动操作系统补丁

但 heroku 对国内用户支持不是很友好,第一点访问国内速度比不上 Vercel, 第二点 163 和 QQ 邮箱都不能注册,想要注册得要其他邮箱, 第三没有免费的 ssl。第四项目源代码只能有 500M。

数据库选择

MongoDB

选择 https://cloud.mongodb.com/

mongodb 首页截图

创建 database 的时候选择 free;

选择免费截图 地域可以选择日本或者新加坡。

接着创建一个用户 创建一个用户 密码是自动生成的,要把密码拷贝下来

接着要创建一个允许链接的 IP 地址

在 mongodb.com 设置允许链接的IP

如何白嫖一个动态网站

前言我们知道,想要搭建一个网站往往需要一下几个步骤:域名注册服务器购买数据库购买或部署网站设计网站开发网站备案网站上线在国内上线一个网站,域名还必须得备案,光是域名备案的话还的几个星期,整个流程下来,...

AI生成图片:探索人工智能技术的视觉创意

AI生成图片:探索人工智能技术的视觉创意

  在当今科技发展的浪潮中,人工智能(AI)技术正迅速成为各个领域的重要驱动力。其中,AI生成图片技术凭借其强大的创造力和想象力引起了广泛关注。通过AI生成的图像不仅具有逼真...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。