范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

使用Next。js创建Blog

  Next.js 已经成为 React 应用程序最重要的框架之一。它可以帮助开发人员在没有模板的情况下构建更好的服务器端渲染 React 应用程序。
  Next.js 之所以能成为目前最好的 React 框架之一,与其很多特性离不开,比如打包构建、路由预取、TypeScript、SEO 等。
  对于那些想要拥有一个简单但功能强大的博客的人来说,使用 Next.js 创建博客是当今的最佳选择。
  SEO(搜索引擎优化)是改进应用程序在搜索引擎排名的过程。对于任何想要在搜索引擎上获得更好排名并带来更多流量的博客来说,这都是非常重要的。
  我们将在本文中使用 Next.js 来构建博客。我们将介绍 SSG(静态站点生成)的工作原理,并完成 SEO 友好的博客。 入门
  使用官方推荐的Create Next App创建项目 npx create-next-app@latest --typescript # or yarn create next-app --typescript # or pnpm create next-app --typescript 复制代码
  为什么要使用Create Next App 交互式体验:不带任何参数运行npx create-next-app@latest,将会开启交互模式,引导创建项目 零依赖:Create Next App没有依赖,毫秒级创建项目 离线支持:Create Next App侦测网络状态,无网状态将使用本地依赖缓存 支持模板:通过加入--example参数,可以拉取官方仓库任何模板 集成测试:集成测试功能
  创建完成后项目目录构造如下: . ├── README.md ├── next-env.d.ts ├── next.config.js ├── node_modules ├── package.json ├── pages ├── pnpm-lock.yaml ├── public ├── styles └── tsconfig.json 复制代码安装依赖pnpm install globby gray-matter dayjs @chakra-ui/react prismjs @emotion/react @emotion/styled framer-motion next-mdx-remote remark-gfm 复制代码创建文章
  根目录新增_posts目录,在_posts目录下创建两个mdx文件(_posts/js/helloWorld.mdx,_posts/demo.mdx),为什么是mdx文件呢?mdx支持渲染组件,支持引入导出组件,详细文档参考MDX 创建公共函数目录
  根目录新增utils目录,在utils目录下创建getAllPosts.js并写入如下函数 import fs from "fs" import {globby} from "globby" import matter from "gray-matter" const dayjs = require("dayjs") const relativeTime = require("dayjs/plugin/relativeTime")  dayjs.extend(relativeTime)  //获取所有文章 const GetAllPosts = async () => {   const posts = await globby(["_posts"])   return posts     .reduce((prev, next) => {       const fileContents = fs.readFileSync(next, "utf8")       const {data, content} = matter(fileContents)       const postData = {         ...data,         group: dayjs(data.date).format("MMM/YYYY"),         date: dayjs(data.date).format("MMM DD, YYYY"),         fromNow: dayjs(data.date).fromNow(),         modified: dayjs(data.modified).format("MMM DD, YYYY"),         content,         slug: next.replace(/^_posts//, "").replace(/.mdx$/, "")       }       !data.draft && prev.push(postData)       return prev     }, [])     .sort((a, b) => dayjs(b.date) - dayjs(a.date)) }  // 根据slug导出文章 const GetPostBySlug = (slug) => {   // eslint-disable-next-line no-undef   return new Promise((resolve, reject) => {     GetAllPosts()       .then((posts) => {         const post = posts.find((post) =>           post.slug.includes(`${slug.join("/")}`)         )         resolve(post)       })       .catch(() => {         reject({})       })   }) }  export {GetAllPosts, GetPostBySlug} 复制代码创建组件
  根目录新增components目录 创建PostPage.tsx组件,内容如下: import React, {useEffect} from "react" import Prism from "prismjs" import {Box} from "@chakra-ui/react"  // 以下按需引入 require("prismjs/components/prism-go") require("prismjs/components/prism-python") require("prismjs/components/prism-javascript") require("prismjs/components/prism-css") require("prismjs/components/prism-bash") require("prismjs/components/prism-swift") require("prismjs/components/prism-tsx") require("prismjs/components/prism-jsx") require("prismjs/components/prism-typescript") require("prismjs/components/prism-sql") require("prismjs/themes/prism-okaidia.min.css")  const PostPage = ({children}) => {   useEffect(() => {     const highlight = async () => {       await Prism.highlightAll()     }     highlight().then(() => {})   }, [children])   return (            {children}        ) } export default PostPage 复制代码创建pages/index.tsx import NextLink from "next/link" import {Fragment} from "react" import {   List,   LinkOverlay,   ListItem,   Container,   Heading,   Image } from "@chakra-ui/react"  const IndexPage = ({groupByMonthPosts}) => {   return (            {Object.keys(groupByMonthPosts).map((group) => {         return (                                       {group}                                         {groupByMonthPosts[group].map((post) => {                 return (                                                               {post.title}                                          {post.tags.map((tag) => {                       return (                         {tag}                       )                     })}                                    )               })}                                 )       })}        ) }  export default IndexPage  export async function getStaticProps() {   const {GetAllPosts} = await import("utils/getAllPosts")   const posts = await GetAllPosts()   const groupByMonthPosts = posts.reduce((prev, next) => {     if (Array.isArray(prev[next.group])) {       prev[next.group].push(next)     } else {       prev[next.group] = []       prev[next.group].push(next)     }     return prev   }, {})   return {     props: {       groupByMonthPosts     }   } } 复制代码创建pages/[...slug].tsx import {MDXRemote} from "next-mdx-remote" import {serialize} from "next-mdx-remote/serialize" import dynamic from "next/dynamic" import ErrorPage from "next/error" import NextLink from "next/link" import {useRouter} from "next/router" import React from "react" import remarkGfm from "remark-gfm" import components from "utils/components" import {   Container,   Box,   Heading,   Text,   Link,   Image,   Center } from "@chakra-ui/react"  const PostPage = dynamic(() => import("components/PostPage"))  const Post = ({title, description, date, originalUrl, mdxSource, cover}) => {   const router = useRouter()   if (!router.isFallback && !mdxSource) {     return    }   return (                                       Published {date}                             {title}                  {originalUrl && (           
本文翻译自: {originalUrl}
)}
{title}
) } export const getStaticPaths = async () => { const {GetAllPosts} = await import("utils/getAllPosts") const allPosts = await GetAllPosts() const paths = allPosts.map((post) => ({ params: { slug: post.slug.split("/") } })) return { paths, fallback: false } } export const getStaticProps = async ({params}) => { const {GetPostBySlug} = await import("utils/getAllPosts") const {content, ...data} = await GetPostBySlug(params.slug) const mdxSource = await serialize(content, { mdxOptions: { remarkPlugins: [[remarkGfm]], rehypePlugins: [] }, scope: data }) return { props: { ...data, mdxSource } } } export default Post 复制代码   至此,基本框架搭建完成,接下来调整样式及组件的引入,以及 mdx 渲染修正。 调整样式   可选   引入tailwind.css,执行pnpm install -D tailwindcss postcss autoprefixer && npx tailwindcss init -p   修改tailwind.config.js,如下: /** @type {import("tailwindcss").Config} */ module.exports = { content: [ "./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}" ], theme: { extend: {} }, plugins: [] } 复制代码   修改全局样式styles/globals.scss @tailwind base; @tailwind components; @tailwind utilities; 复制代码   必须   修改pages/_app.tsx,引入chakra-ui的配置 // pages/_app.js import {ChakraProvider} from "@chakra-ui/react" function MyApp({Component, pageProps}) { return ( ) } export default MyApp 复制代码   到这里,不出意外,你的界面应该是长这样   点击链接,应该会报错,未引入utils/components,这个是配置 mdx 内元素渲染的组件,参考MDX Components,mdx 提供默认的渲染组件,所以,这个是非必须的,不需要删除即可   个人比较喜欢 chakra-ui,所以将组件都转成了 chakra-ui 提供的组件,配置如下: import CanIUse from "components/CanIUse" import {Heading, Link, Box} from "@chakra-ui/react" import {FiExternalLink} from "react-icons/fi" const components = { CanIUse, h2: (props) => ( {props.children} ), h3: (props) => ( {props.children} ), h4: (props) => ( {props.children} ), h5: (props) => ( {props.children} ), p: (props) => ( {props.children} ), p: (props) => {props.children}, a: (props) => { return ( {props.children} ) } } export default components 复制代码   好了,到这里基本完成了基于Next.js的博客搭建。 部署到Vercel   Next.js部署到Vercel无需更改和配置,无缝衔接。   【Source Code】   也可以参考我的个人网站Manon.icu | Home

听说各种手游里都有一种职业者,叫做托,这个托到底要怎么去当?找游戏商申请吗?说一下,之前我在58同城找了一份工作就是手游推广员,看着招聘条件还不错,除了玩游戏就是玩游戏。就去面试了。刚开始也不懂,甚至不知道工作内容,反正就是看那些人坐电脑前打游戏,同时还挂如何能确保国足每次都能进入世界杯决赛圈?一,如何确保,怎样确保?中国男足目前的实力和水平,能成为世界杯的常客吗?不要白日做梦,天方夜谭,要实事求是,切合实际看问题。二,从现在开始,每届世界杯都由中国承办,以东道主名义,每半身裙怎么穿才时髦?哈喽,大家好,我是楚哥。现在天气逐渐变热,裙装也要马上崭露头角,其中半身裙的穿搭频率相对来说较为高一些,因为它的先天优势造就了它多变的可塑性。不过想要整体看起来令人舒服时髦好看,还曝恒大欲退出中超,中国足球路在何方?恒大失败连累到足球,中超房地产足球很多,后续还会有多家会重蹈覆辙,经济状况不佳现原形当然陈戌源的冠名中性化有些作用,但此前的中超要么是垄断国企,要么是来钱快的房地产企业,作用的居然为什么有些人不护肤反而皮肤很好?天生丽质这类人,的的确确存在,尤其是皮肤,并不需要很费力就能让皮肤状态很好,看起来真的好省钱除却遗传因素,好皮肤也跟日常习惯有关。如果是经常熬夜的人,要么就会有长痘的困扰,要么就会房高33层,现在只剩5楼跟30楼,总价一样选哪层好些?我在33,一共34,南北通透,优点,视野很开阔,空气很新鲜,光线非常好,敞亮,马路上传来的车躁也很小,一年四季看不见苍蝇,蚊子,楼上不住人,没有下水管噪音,自来水一般都是二次供水,乌鸦巧用鲜树叶熄灭起火草堆,有灵性的动物,大家怎么看?近日,广东珠海的一只消防鸦火了,这只乌鸦是由广东珠海的一位男子在自己家门口发现的,发现时,乌鸦正在给一个起火的草堆灭火,而且发现了男子在拍摄后,乌鸦并没有被吓走,而是按部就班的救火为什么我国双层巴士普及不起来?谢谢邀请上下客时间长,影响交通秩序是其最致命的弱点,看似增加了载客量,但安全性降低,车内空间狭小,行驶速度不能快,用作观光是不错的选择,我在宁波那时候特别喜欢乘双层巴士,起点到终点国台酒和习酒400左右哪一种好喝有面子?首先回答你的问题,我认为400左右的国台酒和习酒,还是选择习酒窖藏1998,喝起来不仅有面子而且还有里子。国台酒1999年开始在茅台镇建厂,2001年3月22日成立国台酒业,号称茅武汉有哪些火车站?武汉总共有三个火车站点1武汉火车站武汉火车站位于中国湖北省武汉市洪山区杨春湖畔,毗邻三环线,武汉站为高铁站,是我国第一个上部大型建筑与下部桥梁共同作用的新型结构火车站武汉候车站可无千灯湖在佛山本地人眼中是一种怎么样的存在?1千灯湖现在不是睡城,广发人保汇丰友邦万达宜家以及其他中小型企业,官方统计现在就业人数6万,后面还有创投小镇,海天,尚品宅配,广州银行,农商行后台就业人数会越来越多,现在有不少家在
我是独生子,女朋友是独生女,要养4个老人,我现在的工资4千多,我现在该怎么办?你现在怎么办?你现在的主要任务,就是自己养活自己。才那么区区4000块钱一个月,居然还杞人忧天起来,担心如何抚养照顾四个老人,你能养活自己就不错了。我大致算算题主你的年龄。中国的独月收入到手6000,在青岛算是什么生活水平?作为一个青岛人,想回答一下这个问题。月收入到手6000,在青岛算是什么生活水平?到手6000,那么税前加上五险一金应该在7000,就算按照最低的基数缴纳社保,那么税前应该也在650你们有没有被HR骗去面试,实际上他们公司根本不缺人?有何经历?我自己没有过这样的经历,但本身作为一名HR,我知道有同行HR有这样的骚操作(捂脸)第一种情况,招聘HR纯拿你当小白兔练练手。偶然一次跟一位同行负责招聘的HR聊天,问最近在忙什么,他在青岛的八零后现在工资都是多少?我的工资是200天,满勤就是6000,但是很少满勤!做数控的,偶尔出去干点私活,或者晚上在家做配电箱,多少能补一补,媳妇不上班,两个孩子,不靠父母!就得拼,没办法青岛地区消费太高了退了休的人如果犯了罪,还能不能领到退休金?谢邀退了休的人如果犯了罪,还能不能领到退休金?退了休的人如果犯了罪,能不能领到退休金要分两种情况一,如果退休后犯了罪,但犯罪情节轻微,没被追究刑事责任,也就是老百姓说的没判刑,没劳如果让出租车公司大规模兼并,司机全部改为佣金雇佣制,五险一金,你觉得可行吗?无论怎么整,出租车司机都没有话语权!不要跟我说我消极,现在就是这样!底层老百姓,一个普普通通的出租司机我现在什么都不想说了,因为从上到下都只是想整治我们,而不是从司机角度看待这个问你见过周围人得到报应吗?前年,老家对门一个阿姨家里遇了点事,可以说一夜之间损失67万,更重要的是,两口子好长时间接受不了,想不明白,结果都病倒在床,睡了大概小半年的时候,才慢慢走出了那起突发事件。事情是这山东枣庄一个月工资7000,什么水平?10002000大有人在,20003000最为普遍,7000凤毛麟角,四线城市房价破万。你好,很高兴回答这个问题我是枣庄本地人,7000属于工资收入中的上等水平,现在公务员教师医生为什么有人说当下中小学生作文千篇一律?学生学业负担重,在书山题海中艰难跋涉。没时间静心读书,更不能随心所欲地读自己喜欢的书。日常读书是为了完成阅读理解题,应付考试,功利性强,肢解了文本。死记硬背几句美文是为了粉饰作文,我在北中医学了八年的中医,结果到就业之时只能去社区医院,非常不甘心,又不想回地方,怎么办?千万别听毒鸡汤。过来人告诉你。2003年本科毕业进不去三甲,果断不去卫生院,读硕。三年后进入三甲。三年规培。苦苦熬到如今,因为一直在三甲工作,现在如果要跳槽可以轻松进入三甲,乙,二郑州大学和信息工程大学哪个才是郑州最好的学校?对于一般的河南人来说,郑州大学就是河南省的小北大小清华,基本上无人不知。而解放军信息工程大学的知名度小多了,如果不是想报考军校或者就在这所大学周边,还真不知道这所大学。郑州大学是我