Self-built blog address: https://www.bytelife.net, welcome to visit! This article was published as a blog post. For a better reading experience, I suggest you visit my blog at 👇

The author:
Jeffrey


Link to this article:
https://www.bytelife.net/articles/47472.html


Copyright Notice: All articles in this blog are used unless otherwise stated
BY-NC-SALicense Agreement. Reprint please indicate the source!


Recently the blog to Tencent cloud, compared with Tencent cloud and Ali cloud, found that Tencent cloud CDN recently made a lot of upgrades, for the CDN cache node configuration is more detailed, after all, Tencent cloud price is lower, more friendly to individual webmaster. This article is mainly about how to use the COS+CDN of Tencent Cloud to deploy static websites, and how to use Tencent Cloud Function Service to perfectly solve the problem of automatic cache refresh of CDN nodes (with some optimization of the official refresh function).

<! –more–>

My deployment plan

  • Operating environment: Site use of domestic and overseas separate parse solution, resolves to tencent cloud CDN node, in overseas parsing to Vercel CDN nodes, while the main access site is due to domestic users, but Google, bing and so on, after all, the search engine is abroad, and the acceleration of CDN for foreign and domestic is more expensive, so will be separate parsing.

    • Domestic: Tencent cloud COS object storage + Tencent cloud CDN acceleration
    • Overseas: Vercel static website hosting
  • Automated Deployment: Since the source code for your site is hosted on GitHub, use GitHub Actions for automated deployment. It’s not too convenient to write articles and push them to automatically deploy to multiple platforms.

GitHub Actions automatically deploys to Tencent Cloud COS

Tencent cloud provides a very easy to use CLI tool, execute some simple commands can quickly upload files to the COS object storage. In the Git project under the root directory of the creation. Making/workflows/XXX. Yml file, you can create a configuration of the Actions. To deploy Hexo to Tencent Cloud COS object store, use the following configuration:

# workflow
name: Blog

on:
  push:
    branches:
      - master

jobs:
  deploy:
    name: Deploy Blog
    runs-on: ubuntu-latest
    env:
      TZ: Asia/Shanghai

    steps:
    # check it to your workflow can access it
    # from: https://github.com/actions/checkout
    - name: Checkout Repository master branch
      uses: actions/checkout@v2
      with: 
        ref: 'master'
        submodules: true

  # from: https://github.com/actions/setup-node
    - name: Setup Node.js
      uses: actions/setup-node@master
      with: 
        node-version: "14.x"

    - name: Yarn Install Cache
      uses: c-hive/gha-yarn-cache@v1

    - name: Install Dependencies
      run: yarn install

    ## generate files
    - name: Generate Hexo Site Public Files & Create Files for Blog Assets
      run: yarn build

    ## deploy to tencent cos
    - name: Deploy to Tencent COS
      env:
        SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }}
        SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }}
        BUCKET: ${{ secrets.TENCENT_COS_BUCKET }}
        REGION: ap-shanghai
      run: |
        sudo pip install coscmd
        coscmd config -a ${SECRET_ID} -s ${SECRET_KEY} -b ${BUCKET} -r ${REGION}
        coscmd upload -rs --delete ./public/ / -f

Among them:

  • ${{ secrets.TENCENT_SECRET_ID }},${{ secrets.TENCENT_SECRET_KEY }},${{ secrets.TENCENT_COS_BUCKET }}This needs to be configured in the Secrets Settings of the GitHub repository.
  • The commandcoscmd upload -rs --delete ./public/ / -fCompare the files in the current COS bucket, update them if they change, delete the corresponding files if they exist in the bucket but not in the public directory, delete the corresponding files if they exist in the bucket but not in the public directory.coscmdThe specific use method can refer toTencent cloud official document.

Enable COS static website function

It is not enough to upload the website files to COS, you need to turn on the static website function of COS, open the bucket -> basic configuration -> static website, and configure as shown in the following figure:

At this time, you can access the website through the domain name provided by the access node in the figure. Of course, you can also bind the custom domain name, provided that the domain name has been filed.

Tencent cloud CDN acceleration

Create a domain name

If your domain name is recorded, you can also use Tencent Cloud CDN to accelerate COS static website. The configuration is very simple. Create a domain name in the CDN page and configure it as shown in the following figure:

Configure the cache

Cache configuration is very important. Since the site is a static site, the content of the site changes less. In order to reduce the return request of the CDN, it is necessary to configure the node cache policy.

Note: there is no need to worry about configuring the node cache time too long to cause the page to be unable to update. I will explain how to configure the cache auto-refresh later.

More details about the configuration of the CDN will not be described, they are very simple and easy to understand.

CDN node cache is automatically refreshed

The official plan

Since the cache policy of CDN node was configured in the previous step, as long as the request could hit the cache, the return request would not be made, which would lead to our page update not being shown to the user in time. Therefore, we need to consider how to automatically refresh the cache of CDN node.

Tencent cloud official provides us with a solution, we can configure a function in the function calculation of COS bucket ->CDN cache refresh function, as shown in the following figure:

But this scheme, there is a problem because of our static web sites have default index page index. The HTML, and this function is provided by the official URL will only refresh the corresponding files, and do not refresh the index URL, for example http://www.bytelife.net/index.html this file, Usually our request is http://www.bytelife.net/, so the official solution is not perfect for static sites.

Optimization scheme

You can solve this problem by simply modifying the official function. Click the function name in the CDN cache refresh function list just created to jump to the edit page of the function:

Replace the contents of the index.js file with the following code, and finally click the “Deploy” button in the upper right corner:

'use strict' const CosSdk = require('cos-nodejs-sdk-v5') const CdnSdk = require('./common/CdnSdk') const CdnRefreshTask = require('./common/CdnRefreshTask') const { getParams, getObjectUrl, logger, getLogSummary } = require('./common/utils') exports.main_handler = async (event, context, callback) => { /** * parse param from event and process.env */ const { objects, cdnHosts, secretId, secretKey, token } = getParams(event) logger({ title: 'param is parsed success, param as follow: ', data: { objects, cdnHosts, event } }) /** * init cos instance */ if (! secretId || ! secretKey || ! token) { throw new Error(`secretId, secretKey or token is missing`) } const cdnSdkInstance = new CdnSdk({ secretId, secretKey, token }) const cosInstance = new CosSdk({ SecretId: secretId, SecretKey: secretKey, XCosSecurityToken: token }) const taskList = objects.map(({ bucket, region, key }) => { const purgeUrls = []; Cdnhosts.foreach (host => {const tempUrl = getObjectTurl ({cosInstance, bucket, region, key, origin: `${/^(http\:\/\/|https\:\/\/)/.test(host) ? '' : 'https://'}${host}` }); purgeUrls.push(tempUrl); // If you end with /index.html, Add directory page / / / such as https://www.xxxx.com/index.html, https://www.xxxx.com/ if(tempUrl. LastIndexOf ('/index.html') == (tempUrl. Length - 11)){ purgeUrls.push(tempUrl.substr(0, tempUrl.length - 10)) } }); return new CdnRefreshTask({ cdnSdkInstance, urls: purgeUrls }) }) const taskResults = [] for (const task of taskList) { const results = await task.runPurgeTasks() taskResults.push(... results) } logger({ title: 'cdn refresh full logs:', data: taskResults }) const { status, messages } = getLogSummary(taskResults) logger({ messages: messages.map(item => item.replace(/\,\ /g, '\n')) }) if (status === 'fail') { throw messages.join('; ') } else { return messages.join('; ')}}