前言
我们知道,官网通常是需要快速的首屏响应,也需要做seo优化,所以建议使用现代ssr框架来实现网站。诸如博客、官网之类的应用,都是以 内容发布 为主要功能的网站。往往需要一个后台系统,所以建议使用cms来作为内容管理系统。因此,在本项目选择了nextjs 来开发官网,选择strapi来作为后台系统,nextjs 与 strapi 都以 js/ts 为开发语言,本项目适合前端程序员单独开发。(本项目的 官网部分 改造自峰华全栈工程师的从零制作响应式网站-html&css课程成品 )
Nextjs
nextjs 是一个开发者广泛使用 react 同构ssr框架。nextjs 进行 ssr 渲染,也能 进行 Static Site Generation(SSG) 优化,这使得Nextjs开发的应用具有极强首屏渲染能力。
Strapi
strapi 是一个基于koa的 headless(无头) cms。headless 意味它仅有后台系统,并暴露接口给前端使用。strapi 拥有极强的可定制性,和扩展性。本项目将深入strapi开发,使用 redis 作为后端缓存使用,采用strapi社区开发的插件实现redis 与 strapi连接,这极大提高了本项目的后端性能。
官网开发
响应式网站开发

这里采用tailwindCSS,来方便的实现响应式网站开发。在tailwindCSS只需要加上前缀,如xl- lg-等,即可实现css中媒体查询一样的效果。注意:tailwindCSS 有小屏优先原则,默认即为小屏样式。
举例:
html
<div className="grid w-4/5 xl:w-3/5 mx-auto mt-7 mb-[60px]">
</div>
Nextjs的SSG优化
在nextjs中,当page文件中导出名为 getStaticProps (静态站点生成)的函数,nextjs将在构建时使用 getStaticProps 返回的props预渲染此页面。
本项目用到SSG的部分代码:
tsx
export const getStaticProps = async () => {
const { data = {} } = await request.get("/api/articles/newest", {
params: {
count: 3,
},
});
return { props: { newestArticles: data }, revalidate: 60 // 过期时间60s };
};
export default function Home({ newestArticles }) {
return (
// ...someting
);
}
这里首页进行了SSG优化,同时因为首页内容是需要动态更新的,设置了60s的过期时间,每隔60s重新预渲染。
注意:nextjs 有两种模式 page Router 与 app Router,这里使用的是page Router模式,
后台开发
strapi后台支持中文
strapi 后台应用是支持中文的,需要修改src/admin/app.js配置文件
js
const config = {
locales: ["zh-Hans"],
};
const bootstrap = (app) => {
console.log(app);
};
export default {
config,
bootstrap,
};
然后,在个人配置中选择中文即可

strapi 自定义控制器方法与路由
在strapi中创建的每一个内容类型(Content Type),strapi都会生成默认crud接口供开发者使用。但这些往往不足以满足实际开发需求。这就要求我们拥有自定义strapi 控制器(controller)方法和 路由(route)的能力。
以本项目为例,在 src/api/article/routes 目录下新建文件 01-custom-article.js(这是strapi官方推荐的命名,使其能在默认路由文件article.js之前读取),配置自定义路由。
js
module.exports = {
routes: [
{
// Path defined with a regular expression
method: "GET",
path: "/articles/newest", // Only match when the URL parameter is composed of lowercase letters
handler: "article.newest", // 对应controller下的newest方法
},
{
method: "GET",
path: "/articles/view/:id",
handler: "article.view",
},
],
};
在 src/api/article/controllers/article.js中添加自定义newst和view方法。
js
module.exports = createCoreController("api::article.article", ({ strapi }) => ({
async newest(ctx) {
// ...
},
async view(ctx) {
// ...
}
},
}));
strapi 使用redis缓存
大多数时候,网站的内容是不变的。这使得我们可以通过缓存来获得性能提升。
这里主要使用strapi社区的开源插件来实现。使用strapi-plugin-redis插件来连接redis(项目中的文章访问量的实现,就使用了redis来缓存访客ip),使用strapi-plugin-rest-cache和strapi-plugin-rest-cache-redis插件实现strapi api缓存。
安装插件:
bash
yarn add \
strapi-plugin-rest-cache \
strapi-plugin-redis \
strapi-provider-rest-cache-redis
配置插件(config/plugins.js):
js
module.exports = () => {
return {
// @see https://github.com/strapi-community/strapi-plugin-redis
redis: {
config: {
connections: {
default: {
connection: {
host: process.env.RedisHost || "redis",
port: 6379,
db: 0,
},
settings: {
debug: false,
},
},
},
},
},
"rest-cache": {
config: {
provider: {
name: "redis",
options: {
max: 32767, // 过期时间
connection: "default",
},
},
strategy: {
enableEtagSupport: true,
logs: true,
clearRelatedCache: true,
maxAge: 60000,
contentTypes: [
// list of Content-Types UID to cache
"api::head.head",
"api::footer.footer",
"api::article.article",
{// 自定义路由需要这样配置
contentType: "api::article.article",
routes: /* @type {CacheRouteConfig[]} */ [
{
path: "/api/articles/newest", // note that we set the /api prefix here
method: "GET", // can be omitted, defaults to GET
},
],
},
],
},
},
},
};
};
总结
本文分享了一个官网js全栈项目,并介绍了其中的部分重点。以本项目为例,证明了前端程序员可以在类似项目进行独立开发,并且拥有不错的性能。本项目中仍有其他难点没有介绍到,譬如nextjs的ssr渲染写法、strapi的controller方法,以及最后的nextjs和strapidocker部署等等。篇幅所限,有心人就自行阅读源码吧O(∩_∩)O