vivipure / blog

Funkun's blog.
https://funkun.hashnode.dev/
2 stars 0 forks source link

如何进行网站优化 #26

Open vivipure opened 2 years ago

vivipure commented 2 years ago

最近官网迭代,需要更新官网的布局。在开发的过程中,我就顺便就优化了下官网的性能。 官网之前由于SEO的问题,从 SPA 中单独抽离了出来,用 Nuxt 重构为了一个 SSG 的应用。但是在我的日常使用中还是觉得官网访问慢,虽然Google和bing有进行收录,但是百度一直没有收录,这次也顺便解决这个问题。

性能问题

在开始之前,现对旧版官网跑个分,用 Chrome Devtools 的 lighthouse即可。 image

性能表现的确拉了胯。如何去解决呢?还好 lighthouse 有给出低分的原因。我总结了下,主要有几点。

  1. 图片大小问题,几M的图片很多
  2. 图片格式的问题,没有使用webp
  3. 静态资源的访问速度问题

关于 图片大小和格式,这个问题很好解决。之前官网打包后都是直接放在服务器的。并没有放到OSS。利用OSS提供的功能,我们可以将图片进行转化。在使用固定尺寸和webp格式后,大小大概缩小了20倍,性能提升十分明显。

而资源的访问速度存在问题也是同样的原因。把加载的静态资源统一放到OSS上,利用OSS提供的CDN加速即可。

在进行 CI/CD 打包部署时,网站是直接部署到服务器的,那么如何把静态资源(主要是图片)构建到OSS呢?

第一个办法: 打包后将所有的构建产物直接放到OSS,然后利用nginx代理,官网域名直接访问OSS的文件。

这个办法存在个问题,由于放置的目录不是根目录。而 Nuxt 生成的 SSG 模式产物,是需要指定route 的base,使用相对路径是无法正常引用资源的,配置固定的public path 可以解决访问的问题。

由于平台的其他服务也是放在域名下不同path的,如果只是官网放在OSS的话,Nignx 需要做的兼容比较多,一部分路有要定向到服务器,一部分要定向到OSS。总的来说还是比较麻烦的,手动配置后续也比较难维护。

所以有了第二个方案,只将图片上传到OSS即可,打包时将图片的publicPath单独设置接口。那么如何实现呢?

Nuxt 2 是使用webpack作为构建工具的,因此写个插件,改动下图片的解析即可。

首先是图片解析

// nuxt.config.js
...
   extend(config) {
        // 图片
        const pngLoader = config.module.rules.find(rule => rule.test.test('.png'))

        const options = pngLoader.use[0].options
        // 增加OSS 参数
        options.name = 'img/[name].[contenthash:7].[ext]?x-oss-process=image/format,webp'
       // 增加publicPath
        options.publicPath = '...'

        return config
    },
...

wepback的插件也不复杂,我们只需要在构建结束后将图片的目录上传到OSS即可

const path = require('path')
const fs = require('fs')
const compressing = require('compressing')
const rimraf = require('rimraf')
const FormData = require('form-data')
const { default: axios } = require('axios')
// OSSPlugin.js
module.exports = class OSSPlugin {
    apply(compiler) {
        compiler.hooks.afterEmit.tapAsync('done', (compilation, callback) => {
             uploadAssetsImages()
            callback()
        })
    }
}

function uploadAssetsImages(UPLOADPATH) {
    const fullpath = path.resolve(__dirname, '../dist/_nuxt/img')
    const targetPath = path.resolve(__dirname, './prod.zip')
    const tempPath = path.resolve(__dirname, './prod')

    function clearFile() {
        rimraf.sync(tempPath)
        fs.unlinkSync(targetPath)
    }
    if (!fs.existsSync(fullpath)) return

    if (!fs.existsSync(tempPath)) {
        fs.mkdirSync(tempPath)
    }

    fs.readdir(fullpath, (_err, files) => {
        files.forEach(f => {
            const filePath = fullpath + '/' + f
            fs.copyFileSync(filePath, tempPath + '/' + f)
        })
        compressing.zip.compressDir(tempPath, targetPath).then(() => {
            const formData = new FormData()
            formData.append('file', fs.createReadStream(targetPath))

            axios.post(UPLOADPATH, formData).then(res => {
                clearFile()
            })
        })
    })
}

通过对图片的处理,还有OSS提供的参数,在性能这块,基本上就没啥问题了。

SEO

上面的截图中,SEO 的得分有90分。离满分还是有点距离。看了下主要原因,一是图片没有都加上 alt属性,二是有些a标签没有加上href属性。将这两个问题解决后,得分有了变化。

image

Amazing! 开发时能够有前后的明显对比,还是挺让开发人员开心的!

之前有提到官网一直没有被百度收录到,这里我也做了优化。

  1. 使用sitemap 插件在网站根目录生成站点的sitemap.xml
  2. 增加robots.txt文件,声明网站可爬取规则。一般默认全部,测试环境记得屏蔽。
  3. 之前官网是有重定向到官网这个服务的,现在取消这个重定向,直接构建到根目录,当然要对之前的一些老链接做访问兼容处理。 在技术上,我们只能做这些了。想被百度收录,还得主动去提交网站。

https://ziyuan.baidu.com/ 这个网站用来提交自己的网站给百度.

首先需要给百度账号绑定域名,然后通过验证方式证明网站的所有权。

然后到 普通收录 提交即可。其实还有个快速提交的,但是需要兼容手机端,由于官网没有做相关的兼容,就只能使用普通收录了。

同时,我们的网站也要标识网站相关的内容。 meta 中的 keywords 和 description ,需要精简和准确。保证搜索引擎可以通过这些属性匹配到网站。

搞完这些,就等百度的爬虫来干事了。当然最后如果还是收录不了,那么就用钞能力吧!