薅羊毛!!!用腾讯云的免费资源来优化网站

553 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

先说结论

开局一张表

标题FinishDOMContentLoadedLoad
优化前1.66s720ms925ms
优化后795ms523ms544ms

面向人群

  • 没有实操过图片优化的前端同学
  • 想体验一下云资源的同学

背景

nginx + docker + ghost 搭建个人博客,奈何选购的服务器水管小配置低,想尽一切办法,要提高博客的渲染效率,看到腾讯云上有很多免费的资源,决定试一试

准备

这里建议小伙伴们,最好所有的云资源都用同一家供应商了,例如我这里的所有云资源都是用的腾讯云的,这样会带来很多方便的操作,一般同一供应商的各种资源之间会有合作,会产出一些最佳实践和快捷操作,可以方便开发者快速接入

对于没有服务器使用经验的前端来说,可以使用宝塔面板来完成服务器的操作

腾讯云上轻量服务器(Lighthouse)还是很便宜的,可以是新手优惠

CVM/Lighthouse、COS、CDN、域名、宝塔

分析

就以往的经验而言,优化页面渲染性能,主要从两个方面入手

  1. 网络
  • 请求并发
  • 网络延时
  1. 资源包
  • 压缩

总而言之,想尽一切办法,加快网络响应

基于上面的经验,我们打开newwork看看目前网页的请求情况

不需要优化的点

  • gzip压缩

可优化点

  • 开启http2
  • 开启cdn
  • 图片压缩
  • 域名分片,将资源放到不同的域名下

方向制定

处理图片

首先想到是通过cos存储图片,这样既可以实现域名分片,又可以降低服务器的压力,还方便后续接入cdn。可以通过Nginx转发接口的方式,将上传的请求转发到我们自己写的服务中

大概的流程:网页 -上传图片-> Nginx -转发-> nest.js -上传-> COS

先本地验证一下可行性,这里利用whistlejs,把线上的接口代理到本地调试

通过查看浏览器,可以得到真实的上传请求是ghost/api/admin/images/upload,响应数据格式是{ images: [{url, ref}] }

image.png

image.png

配置whistle

image.png

搭建nest.js服务

image.png

最终发现请求成功走到了本地,且页面上显示了本地返回的图片。至此,我们可以分析出可行的方案:

  1. 图片上传cos,通过不同域名暴露给ghost使用 - 域名分片
  2. 接入cdn,降低网络延时,并开启webp压缩
  3. Nginx开启HTTP2协议

方案实施

  1. 利用nest.js生成基础的后台项目。当然,你也可以搭建自己熟悉的后台服务。腾讯云COS使用
// app.controller.ts

import { Controller, Post, UseInterceptors, UploadedFile, UploadedFiles } from '@nestjs/common';
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';

@Post() // 图片上传
@UseInterceptors(FilesInterceptor('file'))
async uploadImages(@UploadedFiles() file) {
    const url = await this.appService.uploadAssets(file);

    return {
      images: [
        {
          "url": url,
          "ref": null
        }
      ]
    }
}
// app.service.ts

@Injectable()
export class AppService {
  async uploadAssets(files): Promise<any> {
    console.log('资源', files);
    
    if (!files.length) {
      return null
    }

    const { key, buffer } = this.handleParams(files)
    
    const res = await this.handleImage({ key, buffer })

    return res;
  }

  handleParams(files) {
    const file = files[0]
    // @ts-ignore
    const { originalname, buffer } = file

    // 图片格式默认值
    let suffix = 'jpg'
    
    const names = originalname.split('.')
    if (names.length) {
      suffix = names[names.length - 1]
    }
    const time = new Date().getTime()
    const fileName = `${time}.${suffix}`

    // 以时间为目录
    const catalog = moment(Date.now()).format('YYYY-MM')
    // 拼装图片目录
    const key = `ghost/${catalog}/${fileName}`

    return { buffer, key }
  }

  handleImage({ buffer, key }) {
    return new Promise((resolve, reject) => {
      cos.putObject({
          Bucket: 'xxx', /* 必须 */
          Region: 'xxx',    /* 必须 */
          Key: key,              /* 必须 */
          StorageClass: 'STANDARD',
          Body: buffer, // 上传文件对象
          onProgress: function(progressData) {
              console.log(JSON.stringify(progressData));
          }
      }, function(err, data) {
        if (!err) {
          const { Location } = data
          // 将存储桶地址换成CDN地址
          // CDN地址是下面第2步中`自定义加速域名`
          const url = Location.replace("存储桶地址", "CDN地址")
          resolve(url) 
        } else {
          reject(err)
        }
      })
    })
  }
}

nest.js部署到服务器上,并通过Nginx完成接口的转发

node服务的部署也很简单,不想折腾ci/cd的话,直接把打包之后的文件拷贝到服务器中,在通过pm2 start main.js来启动

// Nginx配置

server {
      listen 443 ssl;
      ...
  
      location /ghost/api/admin/images/upload/ {
          proxy_pass http://172.18.0.1:3000/;
      }
      location /ghost/api/admin/media/upload/ {
          proxy_pass http://172.18.0.1:3000/video/;
      }
      location /ghost/api/admin/files/upload/ {
         proxy_pass http://172.18.0.1:3000/files/;
      }
      
      ...
}

这样我们就完成将ghost图片上传接口,转发到我们自己写的node服务上,并通过node将图片上传到COS的功能,接下来给COS开启CDN支持

  1. 给COS开启CDN

CDN每月都有免费额度(10GB左右),对于个人博客网站,完全够用

腾讯云CDN加速COS资源

查看加速之后的图片链接,选择自定义加速域名

image.png

  1. CDN开启图片压缩 webp

Webp自适应,每月也有免费额度(10TB),对于个人博客网站,完全够用

CDN控制台,点击域名管理->图片优化,勾选WebP自适应 image.png

  1. Nginx开启http2
server {
    listen 443 ssl http2;
    ...
}

对比

图片(一张图)

未优化前

image.png

优化后

image.png

标题原图大小压缩后大小(webp)网络协议请求时长
优化前158KB--h1756ms
优化后158KB47KBh2161ms

首屏渲染 (3张图+280个字)

优化前

优化后

image.png

标题FinishDOMContentLoadedLoad
优化前1.66s720ms925ms
优化后795ms523ms544ms

结论

经过一波处理之后,对网站的首屏渲染提升不大,主要是提升了图片渲染的效率。哈哈哈哈哈哈~

总结

总结一下图片所用到的优化点:

  • 开启h2网络协议
  • cos存储
  • cdn加速
  • webp压缩

除了以上的优化点,其实我们还可以:

  • 图片懒加载
  • 对不同的屏幕,展示不同尺寸的图片