Where is Next.js cool?
I used Next.js + strapi to make a simple blog site and wrote a concise tutorial on Next.js by the way. After that, Next itself has been developing rapidly. Using the ability of generation js to do:
- Excellent development experience
- Excellent website, the best "dynamic" and "static" balance
In terms of features, it supports:
- SSR(Server Side Rendering)
Provides the getServerSideProps method to request data when the user accesses it, which is suitable for real-time data pages. - SSG(Static Site Generation)
Provide getStaticProps and getStaticPaths methods to produce static pages in advance;
And the cooler point is: use fallback, revalidate to support a certain degree of dynamics.
This kind of "movable" SSG is naturally what I need, to maintain static access, and the site can be automatically updated when I add or modify articles. Excellent! !
Why do we still need to come to Webify to "toss" it?
Now that the above is pretty cool, why is there today's article, and why do I need to toss it?
The reason is also very simple: the cost is slightly higher, for a good access speed, you need a virtual machine with good performance and a certain amount of bandwidth. For general personal blogs, the investment is not cost-effective.
Here are our solutions: Tencent Cloud develops Webify , in simple terms it is a serverless hosting service similar to vercel, but supports more frameworks, and is a domestic service provider, cheap and first-class access speed .
There are pictures as proof:
And now hosting, you can get a 300 yuan no-threshold voucher for free, and you can click on the link below to find out if you are interested: https://cloud.tencent.com/developer/article/1871549
CloudBase Webify Actual Combat
For general articles, it is simple to use github management. Webify supports Github, Gitlab, and Gitee service providers. I heard that Coding will be supported soon:
- Vue.js (vue-cli)
- React.js (create-react-app)
- Hexo
- Gatsby.js
- Angular
- Next.js SSG
- Nuxt.js SSG
- And automatic adaptation framework
Take this blog next as an example. Webify actually uses the next export capability. After building, it directly deploys static files to the server.
If your blog post is directly managed by md and git, it will be OK if you see it here. Submit git and Webify will automatically redeploy your site. cool~~
The question is, what if your site data comes from serverless cms like strapi? Next export does not support the "moving" feature (fallback, revalidate) in the next SSG.
Webify Advanced-Automate Webify
In fact, the method is very simple, just add a bridge service and let your serverless cms update change to git.
Take strapi as an example:
- strapi data release
- Web hook to custom bridge service.
- The bridge service update site git.
- Weify triggers redeployment.
Of course, if subsequent webify supports more redeployment methods, it will be simpler here.
At first glance, it seems to be back to the original point. We still need a server. Here we will introduce another guest of this article, the tcb cloud function. The above-mentioned on-demand invocation service is most suitable to use cloud functions. You don't need a virtual machine that is always on. You only need to call up the cloud functions when you update the article. It will stop when you use it, and the cost is low.
According to the scenario of this blog, we let the bridging service automatically generate the sitemap of the site to github when the bridge service is running to do two things with one stone.
- Used for sitemap to generate sitemap xml;
- Use @octokit/rest, @octokit/plugin-create-or-update-text-file to update the files in github.
Here is the simplified code:
Generate sitemap sitemap.xml
const {
SitemapStream,
streamToPromise
} = require('sitemap')
const {
Readable,
Transform,
pipeline
} = require('stream')
const {
apiRequest,
getPostsWithGraphql
} = require('./request')
const PaginationLimit = 30
module.exports = ({
hostname,
cmsUrl
}) => {
async function getPostSitemap() {
const smStream = new SitemapStream({
hostname,
});
let page = 0;
const postStream = new Readable({
objectMode: true,
async read(size) {
const result = await getPostsWithGraphql(`${cmsUrl}/graphql`, page++, PaginationLimit);
if (result.error || !Array.isArray(result.data.posts)) {
this.push(null);
} else {
result.data.posts.forEach((item) => {
this.push(item);
});
if (result.data.posts.length < PaginationLimit) {
this.push(null);
}
}
},
});
const trans = new Transform({
objectMode: true,
transform(data, encoding, callback) {
callback(null, {
url: `/p/${data.book.slug || data.book.uuid}/${
data.slug || data.uuid
}`,
changefreq: 'daily',
priority: 1,
lastmod: new Date(data.updated_at),
});
},
});
const buffer = await streamToPromise(pipeline(postStream, trans, smStream, (e) => {
// throw e;
}))
return {
path: 'public/sitemap.xml',
content: buffer.toString()
}
}
return Promise.all([
// getHomeSitemap(),
// getBookSitemap(),
getPostSitemap()
])
}
Update files in Github
'use strict';
const {
Octokit
} = require("@octokit/rest");
const {
createOrUpdateTextFile,
} = require("@octokit/plugin-create-or-update-text-file");
const {
throttling
} = require("@octokit/plugin-throttling");
const getSitemaps = require('./sitemap')
const MyOctokit = Octokit.plugin(createOrUpdateTextFile, throttling);
exports.main = async (event, context) => {
const {
headers: {
authorization,
'x-strapi-event': strapiEvent
},
body
} = event;
const {
model,
entry
} = JSON.parse(body)
const {
CMS_TOKEN,
GITHUB_ACCESS_TOKEN,
BLOG_URL = 'https://hicc.pro',
CMS_URL = 'https://cms.hicc.pro'
} = process.env;
// strapi 上添加密钥来确保安全
if (CMS_TOKEN !== authorization) {
return {
doTrigger: false
}
}
let doTrigger = false // TODO: 识别真正的发布
const siteMaps = await getSitemaps({
hostname: BLOG_URL,
cmsUrl: CMS_URL
})
const octokit = new MyOctokit({
auth: GITHUB_ACCESS_TOKEN,
throttle: {
onRateLimit: (retryAfter, options) => {
console.warn(
`Request quota exhausted for request ${options.method} ${options.url}`
);
// Retry twice after hitting a rate limit error, then give up
if (options.request.retryCount <= 2) {
console.log(`Retrying after ${retryAfter} seconds!`);
return true;
}
},
onAbuseLimit: (retryAfter, options) => {
// does not retry, only logs a warning
console.warn(
`Abuse detected for request ${options.method} ${options.url}`
);
},
},
});
await Promise.all(siteMaps.map(({
path,
content
}) => {
return octokit.createOrUpdateTextFile({
// replace the owner and email with your own details
owner: "xxx",
repo: "xxx",
path,
message: `feat: update ${path} programatically`,
content: content,
branch: 'master',
sha: '',
committer: {
name: "xxx",
email: "xxxx@outlook.com",
},
author: {
name: "xxx",
email: "xxxx@outlook.com",
},
})
}))
return {
doTrigger
}
};
Author: hicc, Tencent senior front-end development engineer.
Welcome to the official website of Webify: https://webify.cloudbase.net/
Personal site support plan, free 300 yuan voucher without threshold: https://webify.cloudbase.net/blog/personal-site-plan
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。