分享一个适合前端初学者练手的小项目,strapi+nextjs全栈官网项目

1,219 阅读4分钟

前言

我们知道,官网通常是需要快速的首屏响应,也需要做seo优化,所以建议使用现代ssr框架来实现网站。诸如博客、官网之类的应用,都是以 内容发布 为主要功能的网站。往往需要一个后台系统,所以建议使用cms来作为内容管理系统。因此,在本项目选择了nextjs 来开发官网,选择strapi来作为后台系统,nextjsstrapi 都以 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社区开发的插件实现redisstrapi连接,这极大提高了本项目的后端性能。

官网开发

响应式网站开发

Screenshot1.png Screenshot2.png

这里采用tailwindCSS,来方便的实现响应式网站开发。在tailwindCSS只需要加上前缀,如xl- lg-等,即可实现css中媒体查询一样的效果。注意:tailwindCSS小屏优先原则,默认即为小屏样式。

举例:

    <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的部分代码:

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 Routerapp Router,这里使用的是page Router模式,

后台开发

strapi后台支持中文

strapi 后台应用是支持中文的,需要修改src/admin/app.js配置文件

const config = {

  locales: ["zh-Hans"],

};


const bootstrap = (app) => {

  console.log(app);

};


export default {

  config,

  bootstrap,

};

然后,在个人配置中选择中文即可

Screenshot3.png

strapi 自定义控制器方法与路由

strapi中创建的每一个内容类型(Content Type),strapi都会生成默认crud接口供开发者使用。但这些往往不足以满足实际开发需求。这就要求我们拥有自定义strapi 控制器(controller)方法和 路由(route)的能力。

以本项目为例,在 src/api/article/routes 目录下新建文件 01-custom-article.js(这是strapi官方推荐的命名,使其能在默认路由文件article.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中添加自定义newstview方法。

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-cachestrapi-plugin-rest-cache-redis插件实现strapi api缓存。

安装插件:

yarn add \
  strapi-plugin-rest-cache \
  strapi-plugin-redis \
  strapi-provider-rest-cache-redis

配置插件(config/plugins.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方法,以及最后的nextjsstrapidocker部署等等。篇幅所限,有心人就自行阅读源码吧O(∩_∩)O

源码地址

官网全栈项目(前端) 官网全栈项目(后端)