使用 Next.js 12 和 Cosmic 构建一个可以上线的餐厅网站
译者 | 吴河东
审校 | 孙淑娟 梁策
使用工具
Next.js- 用于生产的使用 React 框架,可以轻松地启动全栈应用程序。可上
Cosmic - 无头部 CMS工具,餐厅它实现了数据(内容)层的网站独立性,并使我们能够快速管理网站内容。使用
Sass - 一种稳定、可上强大的餐厅专业级 CSS 扩展语言。
相关资源
代码现场演示安装应用模板相关工具介绍
Next.js是网站一个完整的套件,用于构建超快的使用 React 应用程序。它对开发人员友好,可上使用轻松。餐厅随着Next.js 12.1的网站发布,性能优化、使用中间件、可上React 18 支持、餐厅按需 ISR、对 SWC 的扩展支持等新功能只会变得更好。
Cosmic是一款出色的无头 CMS,它使我们能够全面管理和存储网站内容和媒体,并进行快速更新。
探索 Next.js 的 4 个新杀手级功能并将其用于模板
先安装一个新的包含工具和配置的 Next.js应用程序。网站模板本教程中使用Node.js 12.22.0 或更高版本。
打开终端,输入:
npx create-next-app@latest nextjs-restaurant-website-cms
# or
yarn create next-app nextjs-restaurant-website-cms安装依赖cd nextjs-restaurant-website-cms
npm i
# or
cd nextjs-restaurant-website-cms
yarn开始运行npm run dev
# or
yarn dev在浏览器中打开 *http://localhost:3000/*以查看主页。
1. Rust 编译器Next.js 12 的关键特性之一是性能优化。为了提高性能,Next.js 用可扩展的 Rust 编译器替换了 Babel 编译器,并默认使用 Next.js 12 启用它,该编译器构建在SWC(Speedy Web Compiler)之上,它支持SWC。它可以将TypeScript和JavaScript转化为可以在旧浏览器上运行的 JavaScript 代码。
SWC 在单线程上比 Babel 快 20 倍,在四核上快 70 倍。
这是最令人兴奋的功能之一。中间件使我们能够使用代码而不是配置。这意味着你可以在请求完成之前运行代码,并根据请求,你可以通过重写、重定向、添加标头、设置 Cookie 等来修改响应。通过中间件,你可以实现身份验证、机器人保护、重定向、重写、服务器端分析、亿华云日志记录和处理不受支持的浏览器等。
中间件被创建在 /pages/_middleware.ts ,它将在/pages目录中的所有路由上运行。_middleware.js文件长什么样?让我们以我们的模板为例。
// pages/_middleware.js
import { NextResponse } from next/server;
export async function middleware( request ) {
// create an instance of the class to access the public methods.
//This uses next(),
let response = NextResponse.next();
const country = request.geo.country || US;
const city = request.geo.city || San Francisco;
const region = request.geo.region || CA;
// get the cookies from the request
let cookieFromRequest = request.cookies[location-cookie];
if(!cookieFromRequest) {
// set the `cookie`
response.cookie(location-cookie, `${ country|city|region}`);
}
return response;
}3.按需增量静态再生ISRNext.js 公开了一个函数unstable_revalidate(),允许你使用getStaticProps重新授权各个页面。在getStaticProps中,你不需要指定 revalidate 来按需重新验证,只需要在unstable_revalidate()调用时按需重新验证页面。
// pages/api/revalidate.js
export default async function handler(req, res) {
try {
await res.unstable_revalidate(/menu/ + req.body.data.slug)
return res.json({ revalidated: true })
} catch (err) {
// If there was an error, Next.js will continue
// to show the last successfully generated page
return res.status(500).send(Error revalidating)
}
}4. 使用 AVIF 实现更快的图像优化和更小的图像内置的图像优化API已更新以支持与ISR页面相同的模式,即在后台提供过时的图像并重新验证。此外,它还支持 AVIF 图像,使图像比 WebP 小 20%。
此功能是可选的,在编辑图片配置的时候可以选择启用。在文件next.config.js中配置下面参数即可:
// next.config.js
const nextConfig = {
reactStrictMode: true,
images: {
formats: [image/avif, image/webp],
domains: [imgix.cosmicjs.com],
},
}
module.exports = nextConfigCosmic 特征概述
可定制的 API:用户自己定义 API 的 schema,models和 controllers。为方便起见, Cosmic 同时提供了REST 和 GraphQL API的方式。源码下载快速且安全的内容管理系统和 API 工具包。Webhooks在你需要的任何地方回调,以获得你想要的功能,使用 Cosmic API 开箱即用。包含Imgix集成,可让你为针对跨平台体验优化的动态应用程序进行强大的图像处理。Cosmic 操作第一步创建免费的 Cosmic 帐户。让我们选择“从头开始”(Start from scratch)选项。
现在让我们将内容放进groups,用Object Type来共享组里的内容。例如,部分名称、标题、简介和图片等具有类似属性的部分,这些模块希望得到复用以为不同部分创建内容。
创建Object Type并添加部分属性用来在“Content Model”中定义“Metafields”。
现在,你可以为部分创建一个Object Type模型,并且可以像这样填充内容。
以类似的方式,你可以按照当前的数据模型、架构设计定义模块并创建Object Type:
Singleton 为一个单独的模型Multiple 为可重复使用的模型是时候获取 Next.js 应用程序的值了将 Cosmic 模块安装到 Next.js 应用程序中。
npm i cosmicjs
# or
yarn add cosmicjs然后,转到 Cosmic 面板 Your Bucket > Settings > API Access并找到你的 Bucket slug 和 API 读取密钥。
将此 Bucket slug 和 API 读取密钥添加到你的 Next.js 应用程序.env中。
//.env
COSMIC_BUCKET_SLUG=your_cosmic_slug
COSMIC_READ_KEY=your_cosmic_read_key要使用模板 UI,你需要在GitHub中将它克隆。打开终端,粘贴或键入此代码以安装所有依赖项,然后运行它。
git clone https://github.com/cosmicjs/nextjs-restaurant-website-cms.git
cd nextjs-restaurant-website-cms
npm install
#or
yarn install
npm run dev
#or
yarn dev向我们之前在 Cosmic 面板中创建的函数getDataFromBucket请求,并按类型从 Cosmic 中获取我们创建的内容params。
// src/lib/api.js
import Cosmic from cosmicjs;
const BUCKET_SLUG = process.env.COSMIC_BUCKET_SLUG
const READ_KEY = process.env.COSMIC_READ_KEY
const bucket = Cosmic().bucket({
slug: BUCKET_SLUG,
read_key: READ_KEY,
});
export async function getDataFromBucket(preview) {
const params = {
type: header,
props: title,slug,metadata,created_at,
sort: -created_at,
...(preview && { status: all }),
}
const data = await bucket.getObjects(params)
return data.objects
}显示我们的内容,将其与我们的 UI 集成,并将一些元素呈现到主页。为此,你需要将此添加到index.js。
// pages/index.js
import Head from next/head;
import Home from components/Home;
import Layout from components/Layout;
import Footer from components/Footer;
import AboutUs from components/AboutUs;
import SpacialMenu from components/Menu;
import Introduction from components/Introduction;
import VideoIntro from components/VideoIntro;
import Gallery from components/Gallery;
import Contacts from components/Contact;
import { getDataFromBucket } from lib/api;
import chooseByType from utils/chooseValueByType;
function Template({ data }) {
return (
<>
)
}
export async function getStaticProps({ preview }) {
const data = (await getDataFromBucket(preview)) || [];
return {
props: { data },
}
}
export default Template;下面函数chooseByType将过滤我们在 Cosmic 面板中创建的 Object Type。(Slug)
(Slug)
// src/utils/chooseValueByType.js
const chooseByType = (data, slugName) => {
if( data && slugName ) {
const chooseBySlug = data?.filter(content => Object.values(content).includes(slugName));
return chooseBySlug ? chooseBySlug[0] : [];
}
}
export default chooseByType;
制作菜单项页面在 Next.js 中,你可以创建动态路由,可以考虑用下面pages/menu/[slug].js页面来创建单个菜单项页面和动态路由:
// pages/menu/[slug].js
import Head from next/head;
import { useRouter } from next/router;
import Layout from components/Layout;
import Footer from components/Footer;
import Contacts from components/Contact;
import MenuIntro from components/MenuIntro;
import VideoIntro from components/VideoIntro;
import Gallery from components/Gallery;
import { getAllDataWithSlug,getDataFromBucket } from lib/api;
import chooseByType from utils/chooseValueByType;
function Menu({ data }) {
const {
query: { slug},
} = useRouter();
return (
<>
)
}
export async function getStaticProps({ params, preview = null }) {
const data = (await getDataFromBucket(preview)) || [];
return {
props: { data },
}
}
export async function getStaticPaths() {
const dataWithSlug = (await getAllDataWithSlug()) || [];
return {
paths: dataWithSlug.map((menu) => `/menu/${ menu.slug}`),
fallback: true,
}
}
export default Menu;该函数getServerSideProps用于每次调用此路由时从 Cosmic 获取数据。在pages/api/revalidate.js中,我们在unstable_revalidate()被调用时使用unstable_revalidate函数来按需重新验证页面。如果出现错误,Next.js 将继续显示最后成功生成的页面。
在Vercel上部署代码库后,你可以通过转到 Cosmic 面板并导航到Bucket Settings > Webhooks来启用内容更新的重新验证。编辑内容时要触发的事件是object.edited.published。Webhook URL 端点将如下所示:${ YOUR_VERCEL_DEPLOYMENT_URL}/api/revalidate。
这也使得在创建或更新来自无头部的CMS 的内容时,你的网站更容易更新。
现在来测试一下,在 Cosmic 面板中编辑内容,并查看静态内容立即更新。
结论
现在,你已拥有一个动态的、可定制的、完全集成的模板,其中包含新的 Next.js 和 Cosmic 功能。你可以为其他类型的企业定制,并按照自己的喜好来使用。
译者介绍
吴河东,社区编辑,具有5年工作经验,从事电商相关IT工作。擅长后台开发,大数据,算法等。
原文标题:Build a Production Ready Restaurant Website with Next.js 12 and Cosmic,作者:Naira Gezhoyan