了解基于Next.js的SSR-SSG解决方案?
时间:2023-03-14 23:59:26
科技观察
本文主要讲述如何使用Next.js框架实现服务端渲染,将有效提高网页的SEO和首屏渲染速度。说不定哪天会用上吧!1、服务器端渲染(SSR)服务器端渲染(SSR,ServerSideRender)和客户端渲染(CSR,ClientSideRender)的核心区别简单来说就是完整的HTML文档是在服务器端组装还是在浏览器。SSR的另一个概念是同构渲染,可以看看知乎上的讨论:什么是前端同构渲染?[1]同构渲染简单来说就是一段代码,服务端先使用服务端渲染(SSR),生成HTML和初始化数据,客户端拿到代码和初始化数据后,对DOM进行客户端水化通过修补和绑定事件到HTMLDOM。这个整个过程称为同构渲染。SSR的原理,本文不再赘述,有兴趣的朋友推荐阅读这篇文章:《彻底理解服务端渲染 - SSR原理》二、Next.jsNext.js[2]是一个用于生产环境的React框架,无需配置,自带默认情况下生产环境需要的所有功能的最佳开发实践:支持静态渲染和服务端渲染,支持TypeScript,智能打包,路由预加载等功能。同时,Next.js还提供了以下开箱即用的SDK来辅助Web应用的开发:看了SSR原理一文,可以看到配置对server的支持还是挺麻烦的-端渲染,但借助Next.js,您可以轻松开始改造对现有Web应用程序的服务器端渲染的支持。是否使用服务端渲染要综合考虑利弊。毕竟服务器端渲染会增加服务器的计算开销,稳定性比CSR差。3.创建一个Next.js应用初始化一个Next.js应用可以直接通过脚手架快速完成:npxcreate-next-app@latest--ts#oryarncreatenext-app--typescript会中途要求输入项目名,自动installtherequired模块执行yarndev后,需要在浏览器中手动打开网址:http://localhost:3000,可以看到如下页面:首页内容对应./pages/index。tsx文件初始目录结构如下:.├──pages//采用常规路由(文件系统路由)│├──_app.tsx│├──api//API目录|├──hello.ts│└──index.tsx//首页├──public//publicresources│├──favicon.ico│└──vercel.svg├──styles//styles│├──Home.module.css│└──globals.css├──next-env.d.ts//Next相关TS定义├──next.config.js//Next.js自定义配置├──node_modules├──package.json├──tsconfig.json├──README.md└──纱线。lock4.页面路由通常我们的web应用有多个页面和多个路由,所以会涉及到页面之间的跳转,所以熟悉Next.js的路由用法是很有必要的。上面说了,Next.js是常规路由,基于文件系统,对应./pages目录,当在./pages目录下添加页面文件时,Next.js会自动识别并注册对应的文件路由4.1索引路由Next.js会自动将文件夹内的“index”文件注册为文件夹的首页4.2嵌套路由Next.js支持嵌套文件的路由,如果创建嵌套文件夹结构,文件仍然会被自动路由同理路由解析。4.3动态参数路由常见于博客的文章详情页,例如。文章的id是动态变化的。在Next.js中,方括号可以用来解析对应的命名参数。更多动态路由请参考:https://nextjs.org/docs/routing/dynamic-routes4.4路由跳转之前提到过Next.js中的路由预加载功能需要使用next/link由Next.js提供,写法如下:.属性href的值为跳转页面的路径字符串或URL对象:importLinkfrom'next/link'functionArticles({articles}){return(
)}exportdefaultArticles如果需要通过js跳转到路由,可以使用Next.js提供的next/router[3]中的useRouter[4]Hook。4.5代码拆分和预加载通过Next.js的路由功能,可以自动完成页面需要的代码按需加载当前页面,同时自动预加载页面上属于自己应用的链接.这意味着在呈现主页时,最初不会提供来自其他页面的代码,同时确保即使您有数百个页面,主页也能按需快速加载。只加载您请求的页面的代码也意味着页面变得独立,如果一个页面抛出错误,应用程序的其余部分仍然可以工作。在Next.js的生产版本中,只要Link组件出现在浏览器的视口中,Next.js就会在后台自动预取链接页面的代码。当您点击一个链接时,目标页面的代码已经在后台加载,页面转换几乎是即时的。5.静态资源所有的静态资源都可以放在./public目录下,Next.js会自动为里面的文件注册路由。按照文件系统的方式,类似于Page的路由。5.1图片元素一般网页中的图片都是这样写的:
但是这种写法会需要开发者手动优化,比如按需加载,错误处理等。考虑到这一点,Next.js提供开箱即用的next/image[5]以减轻开发人员的负担。事实上,你可以从这里学习。在其他项目中,对于业务的图片统一处理,可以封装一个Image组件来提高研发效率。importImagefrom'next/image'constYourComponent=()=>(
)exportdefaultYourComponent;5.2元数据网页的元数据,即html->head标签中的内容Next.js提供了next/head[6]用于声明性的写入网页的head内容。importLinkfrom'next/link'importHeadfrom'next/head'exportdefaultfunctionFirstPost(){return(<>
FirstPostFirstPost
>)}另外,如果我们有修改的需求,可以创建一个pages/_document.js文件,通过“自定义文档[7]”继承统一转换所有网页输出的公共内容》5.3JS脚本文件比如我们使用第三方库Jquery,虽然在组件中可以直接写:但是,通过这种方式包含脚本没有明确指示何时加载在同一页面上获取的其他JavaScript代码。如果特定脚本阻止渲染并延迟页面内容的加载,它会显着影响性能。因此,可以优化importLinkfrom'next/link'importHeadfrom'next/head'importScriptfrom'next/script'exportdefaultfunctionFirstPost(){return(<>
FirstPost//js脚本文件加载后的回调函数console.log(`scriptloadedcorrectly`)}/>FirstPost
/>)}5.4CSSFileNext.js内置了对CSS和SASS的支持,允许开发者通过导入.css和.sass文件来导入样式文件,同时也支持TailwindCSS。需要手动安装SASS模块yarnaddsass也默认支持CSS-in-JS。借助styled-jsx[9]模块,您可以直接在React组件中编写CSS,同时限制范围而不影响其他组件。如果需要CSS模块化[10],CSS文件名的格式应为*.module.css。importstylesfrom'./layout.module.css'exportdefaultfunctionLayout({children}){return{children} }全局CSS注入写在根目录./styles目录下,同时在./pages/_app.tsx文件中只引入全局样式文件import'../styles/globals.css'//引入全局样式importtype{AppProps}from'next/app'functionMyApp({Component,pageProps}:AppProps){return
}exportdefaultMyAppNext.js使用PostCSS[11]编译CSS,如何自定义PostCSS配置可以参考:【自定义PostCSS配置】12]】6.Pre-renderingandDataacquisitionNext.jssupport:Pre-renderingontheserversideStaticpagegenerationandserver-siderenderingStaticgenerationwithandwithoutdata一些预定义的方法(生命周期函数)注入数据6.1预渲染默认情况下,下一步。jspre-rendering渲染每个页面。这意味着Next.js会提前为每个页面生成HTML,预渲染可以带来更好的性能和SEO。每个生成的HTML都与该页面所需的最少JavaScript代码相关联。当浏览器加载页面时,其JavaScript代码运行并使页面完全交互。预渲染和不预渲染的对比如下:6.2静态生成和服务端渲染Next.js支持两种预渲染形式:静态生成和服务端渲染在构造期间生成HTML。然后在每个请求上重新使用预呈现的HTML。服务器端呈现:一种预呈现方法,可在每次请求时生成HTML。6.3获取数据(1)静态生成时获取数据在服务端构建生成静态页面之前,有时需要获取一些数据,可以借助getStaticProps方法获取。在页面组件中,同时导出一个getStaticProps方法:exportdefaultfunctionHomePage(props){...}//导出异步数据获取方法exportasyncfunctiongetStaticProps(){//获取数据,比如从数据库、API、文件等获取数据。constdata=...//返回的参数会根据键值return{props:...}赋值给HomePage组件的同名入参}}注意该方法只在页面组件导出(2)服务器渲染时获取用户个人数据等数据中心页面不需要SEO优化,其数据通常需要实时更新获取,所以采用SSR方式,SSR可以使用getServerSideProps方法获取服务器端的数据。方法类似于构造时获取数据的方法:exportdefaultfunctionHomePage(props){...}//异步导出获取数据方法exportasyncfunctiongetServerSideProps(){//获取数据,比如从数据库、API、文件等constdata=...//返回的参数会根据key值赋值给同名的HomePage组件参考return{props:...}}(3)客户端渲染时获取数据如果不需要在“预渲染”时获取数据,即不需要在“静态生成”和“服务端渲染”时获取数据,那么网络请求相关的代码可以写在相应的页面组件生成中。Next.js团队提供了一个基于ReactHooks的useSWR钩子,推荐使用,它可以处理缓存、重新验证、焦点跟踪、间隔重新获取等。一个简单的例子如下:)return
loading...
return
hello{data.name}!
}类似一些封装的请求Hook,useSWR也支持自定义请求库,默认使用pollyfill的fetchmodule(unfetch[13]),官方提供的中文文档也很清楚,地址:https://swr.vercel.app/zh-CN/docs/getting-started动态路由上面提到了预渲染,动态路由的预渲染如何处理?这里需要依赖方法getStaticPaths来获取动态路由并生成页面列表。//./pages/post/[id].tsximportLayoutfrom'../../components/layout'exportdefaultfunctionPost({id,article}){return(
{article.title}{article.title}
{id}
{article.date})}exportasyncfunctiongetStaticPaths(){//返回所有可能的文章ids对应的列表constpaths=[{params:{id:'ssg-SSR'}},{params:{id:'pre-rendering'}}]return{paths,fallback:false,//如果paths值中找不到id,指向404页面}}exportasyncfunctiongetStaticProps({params}){//通过params.id获取必要的文章数据//parmas是路由中的参数对象constaticle=getContentById(parmas.id);return{props:{id,artcile,}}}关于fallback,参考:fallbackprops[14]自己搭建一个404页面,文件路径为:./pages/404.tsxexportdefaultfunctionCustom404(){return
404-PageNotFound
}八、BFFAPI初始目录结构中的./pages/api/hello.ts文件是一个API页面,其路由同页面路由importtype{NextApiRequest,NextApiResponse}from'next'typeData={name:string}exportdefaultfunctionhandler(req:NextApiRequest,res:NextApiResponse
){res.status(200).json({name:'JohnDoe'})}在./pages/api/目录下,前端开发者编写自己想要的API应用,称为ServerlessFunctions,类似于bytes的“light”service[15]”9.部署官方推荐使用Vercel[16]完成一键式自动化构建。Deployment先执行构建,构建过程中会自动进行相关优化。yarnbuild//实际执行nextbuild然后启动服务:yarnstart//生产环境实际执行nextstart-p8080,然后使用PM2[17]管理daemon进程然后使用Nginx作为网关,配置域名,SSL,并映射到本地8080端口扩展Next.js以及更多细节和API,需要深入了解的朋友可以参考:Next.jsAPI文档[18]除了Next.js,Razzle.js[19]]也可以学习。推荐阅读:《彻底理解服务端渲染 - SSR原理》《魅族官网基于 next.js 重构实践总结与分享[20]》《SWR - 用于数据请求的 React Hooks 库[21]》《react 服务端(SSR) 框架next.js开发个人网站分享[22]》《Next.js 应用开发实践[23]》总结通过Next的初步使用。强烈推荐这种方法,但它的缺点也很明显。服务器的稳定性会降低,可以通过增加成本来提高稳定性。对比它的优势,还是值得投资的!Next.js初始化一些生产配置构建完成,对于开发者来说,开箱即用的感觉真的很棒!参考[1]什么是前端同构渲染?:https://www.zhihu.com/question/325952676[2]Next.js:https://nextjs.org/[3]next/router:https://nextjs.org/docs/api-reference/next/link[4]useRouter:https://nextjs.org/docs/api-reference/next/router#userouter[5]next/image:https://nextjs.org/docs/api-reference/next/image[6]next/head:https://nextjs.org/docs/api-reference/next/head[7]自定义文档:https://nextjs.org/docs/advanced-features/custom-document[8]next/script:https://nextjs.org/docs/api-reference/next/script[9]styled-jsx:https://github.com/vercel/styled-jsx[10]CSS模块化:https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css[11]PostCSS:https://postcss.org/[12]自定义配置PostCSS:https://nextjs.org/docs/advanced-features/customizing-postcss-config[13]unfetch:https://www.npmjs.com/package/unfetch[14]后备道具:https://nextjs.org/docs/basic-features/data-fetching#the-fallback-key-required[15]轻服务:https://qingfuwu.cn/[16]Vercel:https://vercel.com/[17]PM2:https://pm2.keymetrics.io/[18]Next.jsAPI文档:https://nextjs.org/docs/api-reference/cli[19]Razzle.js:https://razzlejs.org/[20]魅族官网基于next.js重构实践总结与分享:https://zhuanlan.zhihu.com/p/113853235[21]SWR-用于数据请求的ReactHooks库:https://swr.vercel.app/zh-CN/docs/getting-started[22]react服务器端(SSR)框架next.js开发个人网站分享:http://www.liuweibo.cn/p/206[23]Next.js应用开发实践:https://nextjs-in-action-cn.taonan.lu/【编辑推荐】鸿蒙官方战略合作共建——阿里云,鸿蒙技术社区发现的首个高危漏洞,工信部为何暂停合作?Python面向对象中常用的内置成员介绍。七个优秀的Linux滚动发行版。Linux容器与Docker的比较。再次爆破漏洞!!