Remix vs Next.Js 你应该使用哪一个?

2022-11-24 0 611

每日分享新一代,最流行的软件设计知识与新一代行业趋势,希望大家能够全屏帕西基,喔支持,下跪关注,点赞,回帖。

Remix vs Next.Js 你应该使用哪一个?

现如今,当他们想如前所述 React 建立两个捷伊 Web 工程项目时,他们有很多相同的架构优先选择。

现如今,当他们想如前所述 React 建立两个捷伊 Web 工程项目时,他们有很多相同的架构优先选择。作为一名开发者,您会发觉极难晓得如果优先选择哪一类,或者哪一类最适合您的需求。您可能将晓得最常用的架构众所周知是Next.js,Netflix、Twitch 或 Uber 等公司通常采用它。它被认为是增长最快的 React 架构众所周知。其他人极难与 Next.js 竞争,即使它囊括了三种相同的页面图形思路,但自2021年 11月以来,他们似乎有了两个捷伊、新鲜的、强悍的架构,称为Remix。对不起沙利文比,我没忘记你,我喜欢你在聚合动态公交站点时的组织工作形式。为什么须要 Next.js 或 Remix 而不是普通的 React也许你没;这取决于。重点是了解 React 插件怎样组织工作,您可能将会发现哪些难题以及 Next.js 或 Remix 等架构怎样解决这些难题。关于 React 的关键点是您能制作白眉林插件(SPA),其中仅采用两个 HTML 文档来呈现出大部份页面,因此路由器保留在应用程序。但这到底是什么意思呢?当发出如上所述允诺时,应用程序会立即收到两个包含大部份插件的 HTML 框页面。没预图形的文本。当使用者导航促发时,JavaScript 仅替换这些与允诺的路由器相关的模块和文本,但 HTML 文档保持不变。具体而言,应用程序全权负责应读取哪个 JavaScript 文档以呈现出当前页面。换言之,应用程序呈现出(CSR)。CSR 能非常花俏因此有助于建立不须要关心 SEO、内存或缓慢的如上所述图形的插件。SSlow Initial Render——当使用者第二次登陆时,可能将须要很长时间才能读取第两个文本页面。这意味着让他们得到两个盲点页面,直到 JavaScript 读取并呈现出大部份文本。SEO——即使文本只有两个 HTML 页面,所以极难让浏览器和SNS媒体机器对文本进行检索。内存难题——HTML 结构无法内存,即使它在第二次图形时不可用。在这一点上,您可能将认为 SPA 是撒旦,但想想这么多公司采用的大部份内部插件或他们销售的插件产品。当您想利用 SPA 的组织工作形式而又不失去我以后提到的四点时,Next.js或Remix就会出现。优点是中文网站能在发送至应用程序以后在服务端呈现出。SSR vs SSG vs ISR我已经解释了 CSR 的含义和组织工作原理,现在果不其然我来聊聊其他花俏的页面呈现出思路。 Next.js是两个强悍的快捷键,即使它提供了三个照相狸尾豆的相同快捷键,而Remix全然倚赖 SSR(目前)。但这些思路究竟是怎样运作的呢?服务端图形(SSR)当两个页面被允诺时,它在发送至应用程序以后在伺服器上全然呈现出。对这些拥有大量lussin和文本的中文网站而言,这是两个很好的优先选择。动态公交站点聚合(SSG)该思路在构筑期间按路由器聚合大部份页面。出现提示时,只会将允诺的页面发送到应用程序。也就是说,这构建了两个典型的动态中文网站。对这些几乎没或没lussin且页面不多的动态中文网站而言,它可能将是两个合适的优先选择。数据中的每个更动单厢促发大部份页面的重新聚合。增量动态再生(ISR)Next.js 提供了这个概念,是 SSR 和 SSG 的混合体。它类似于 SSG,但您能设置两个间隔时间,让您晓得何时如果重新聚合您的页面。适用于这些具有动态文本的动态公交站点。Next.js 的强项在于它允许您在每个页面上的这三个快捷键之间切换,因此您能让每个快捷键遵循相同的思路。所以也许你会问自己,“如果 Next.js 只适用于 SSR,我为什么要用 Remix 替换它”。答案很简单,现如今,插件和中文网站往往具有lussin,因此很少有适合 SSG 或 ISR 场景的示例。考虑到这一点,Remix 提供了两个较低级别的 API。例如,它公开了 Request 对象,因此您能在呈现出页面以后轻松修改标头,而在 Next.js 中,您须要中间件来实现它。路由器这两个架构都采用如前所述文档的路由器系统来呈现出页面。每个页面都保留在相同的文档中。每个页面都与如前所述其文档名的路由器相关联。最后,每个页面单厢呈现出两个 React 模块。混音中的路由器您将在中添加每个路由器/app/routes,因此在其中建立的每个文档或文档夹都将被视为两个路由器。混音路由器1此外,您会发现两个文档,/app/root.jsx,其中是“根路由器”,是整个插件的布局。它包含、和 标签,以及其他与 Remix 相关的文本。Next.js 中的路由器您将在中添加每条路线/pages,它的组织工作形式与 Remix 全然相同。nextjs 路由器1在这种情况下,您可能将有也可能将没pages/app.jsand pages/document.js。其中App用于如上所述化页面,文档包含标签。Next.js 默认采用它们,无需额外配置。但是,如果您须要自定义它们,您能建立这两个文档,以这种形式覆盖默认文档。检索路线他们都采用相同的系统来呈现出容器路线。Next.js 示例:pages/index.js=>/(根页面)pages/posts/index.js或者pages/posts.js=>/posts混音示例:routes/index.js=>/(根页面)routes/posts/index.js或者routes/posts.js=>/posts嵌套路由器Remix 建立在 React Router 之上,由同两个团队开发,所以你能想象在嵌套路由器方面谁是赢家。其背后的想法是建立两个活动路由器来挂载包含多个嵌套路由器的布局,以便每个路由器管理自己的文本。如果我必须用 React 语言来解释它,我会告诉你想象每个嵌套路由器都是两个模块,因此根据 URL 路径,它们能被挂载和卸载。为实现这一点,Remix 采用了React-router 模块。它用在父路由器上,告诉它们只要被促发就图形子路由器元素。请记住,大部份这些嵌套路由器都已预读取到伺服器上,因此几乎每个读取状态都能删除。听起来不像是 SSR 和 SPA 的混合体?另一方面,Next.js 确实支持嵌套路由器,但它们作为单独的页面组织工作。如果您想实现类似于 Remix 所做的事情,您可能将如果自定义您的app.js.两者的示例:routes/posts/news/index.js=>/posts/news动态路线它们通过基于动态的 URL 参数呈现出相同的文本来组织工作,但它采用单个路由器文档。在这种情况下,两个架构都支持此功能,但采用相同的命名约定。Next.js 示例:pages/posts/[postId].js=>/posts/some-post-slugpages/products/[category]/[productId].js=>/products/keyboards/some-keyboard-slug或/products/headphones/some-headphone-slug它有自己的钩子,useRouter将为您提供这些动态参数(postId、类别、productId)的当前值。混音示例:/app/routes/posts/$postId.js=>/posts/some-post-slug/app/routes/products/$category/$productId.js=>/products/keyboards/some-keyboard-slug或/products/headphones/some-headphone-slug您能采用useParamReact Router hook 来访问这些动态参数。须要读取文档的路由器怎么办?想象一下,您须要您的中文网站包含典型文档robots.txt和sitemap.xml文档。在 Next.js 和 Remix 中,您都能将它们添加到/public 目录。但是 Remix 能让你通过路由器系统实现它,只需建立两个/app/routes/[sitemap.xml].js或/app/routes/[robots.txt].js数据nst productList = await getProductList() return { props:{ productList, slug: params.slug }}}getServe const productList = await getProductList() return { props:{ productList, slug: params.slug }}}/*** Here you would have your own getStaticProps/getServerSideProps functions * depending on what system you choose.**/ const PageName =(props)=>{ const { productList }= props // Here you could render the requested data return (

{JSON.stringify(productList, null,4)}
)}Remix 采用相同的形式读取数据;它为您提供了两个loader在每个路由器文件上采用的函数,该文档将在运行时在服务端运行。在页面模块本身上,您将能够采用useLoaderData挂钩来收集这些数据。/*** Here you would have your own getStaticProps/getServerSideProps functions * depending on what system you choose.**/export const async loader =( {params}) =>{ const productList = await getProductList() return { productList, slug: params.slug }};export default function PageName(){ const { productList }= useLoaderData();// Here you could render the requested data return (
{JSON.stringify(productList, null,4)}
)}数据突变Next.js 没内置的形式来执行突变,你必须手动进行。另一方面,Remix 建立了两个表单模块,并像采用应用程序的本机 HTML 表单元素一样采用它。如果您不输入任何操作 URL,它将对表单采用相同的路由器。如果方法是GET,loader将促发导出函数,如果方法是POST,action将促发定义在模块中的导出函数。此外,您能采用提供的 useTransition 挂钩根据允诺状态管理插件的行为,而无需像往常一样手动管理它。export const loader = async ({ params })=>{ // Each time this page receive a GET Request, this loader will be executed const userData = await getSomeUserData(params.slug) return { userData // it contains the User Name }}export const action = async ({ request })=>{ // Each time this page receive a POST Request, this loader will be executed const form = await request.formData() const content = form.get(content) return redirect(/)}export default function App(){ const { name }= useLoaderData(); return (
{Hello there ${name}}
Content:</label><input type=”submit” value=”Add New”/></Form></div>)}造型Next.js 带有照相狸尾豆的内置 CSS 支持,因此您能直接将其导入到/pages/app.js 所需的任何 style.css 文档中。您还能添加其他 CSS 架构,采用一些配置或插件很容易实现。linksRemix 更喜欢通过提供模块和导出功能来专注于对 Web 标准更加友好的解决方案。import styles from “./styles/app.css”;export function links(){ return [{ rel:”stylesheet”, href: styles },{ rel:”stylesheet”, href:https://…..},];}export default function App(){ return (<html lang=”en”><head><Links /></head><body><Outlet /></body></html>);}您可能将认为仅仅读取两个样式表有点过分了,但是如果我告诉您能在每个页面上单独采用它,让您仅在须要时读取特定样式/字体怎么办?另外,在这里你能采用其他的 CSS 架构,只需很少的配置,比如 Tailwindcss。图像优化Next.js 在这里获胜,即使它有自己的内置模块next/image,能实现图像优化、延迟读取、大小控制和集成读取器。不幸的是,目前 Remix 没任何图像优化支持。搜检索擎优化在本文的开头,我告诉过您这些架构背后的关键点众所周知是解决 SPA 的 SEO 难题。它们都有自己的内置机制来动态管理每个页面上如果采用哪些元数据,例如关键字、标题、描述等。next/head在 Next.js 中,您能通过将其导入页面/路由器来采用其内置模块。import Head from next/headexport default function PostPage(){ return (<div><Head><title>Post Page Title</title><meta name=”description” content=”Post Page Description”/></Head><p> All the metadata inside Head component will be injected into the documents head </p></div>)}另一方面,Remix 为他们提供了两个meta导出函数,能接收页面的允诺数据以及 URL 参数。export const meta =({ data, params })=>{ charset:”utf-8″, viewport:”width=device-width,initial-scale=1″, title: Post ${data.title}, description: data.description,};export default function PostPage(){ return (<div><p> All the metadata returned on meta function will be injected into the documents head </p></div>)}错误处理Next.js 使您能在捕获某些错误时定义自定义页面,例如400或 500错误。但是除了路由器或状态错误之外的任何其他错误单厢导致页面中断。Remix 让您尽情发挥想象力,这样您就能覆盖和自定义您想的每个错误。他们添加了错误边界,这是一类处理错误的独特概念——在 React v16中引入。您能通过在您的甚至每个页面上采用CatchBoundary,和ErrorBoundary导出的函数轻松地覆盖这些错误。root.tsx让他们添加一些视觉示例。// Here you will catch any controlled error and will tell the framework what information should be shownconst CatchBoundary =()=>{ let caught = useCatch(); switch (caught.status){ case 401:// Document is a custom React Component which contains <html>,<head>,<body>, etc return (<Document title={${caught.status}${caught.statusText}}><h1>{caught.status}{caught.statusText}</h1></Document>); case 404: return <PageNotFoundComponent />;// Yes, you can also use a React Component default: throw new Error( Unexpected caught response with status:${caught.status});}};// Here you will have a more generic advise for when an uncontrolled error has been triggeredconst ErrorBoundary =( { error }) =>{ return (<Document title=”Uh-oh!”><h1>App Error</h1><pre>{error.message}</pre><p> Replace this UI with what you want users to see when your app throws uncaught errors.</p></Document>);};export const loader: LoaderFunction = async ({ params })=>{ const post = await getPost(params.slug); if (!post){ throw new Response(“Not Found”,{ status:404,});} return json({ post });};export default function PostPage(){ const { post }= useLoaderData(); return (<div><pre>{JSON.stringify(post, null,4)}</pre></div>)}部署Next.js 很容易部署在任何支持 Node.js 的伺服器上。它还集成了无伺服器部署到 Vercel 的功能,Netlify 有自己的适配器,因此您能轻松部署插件。Remix 如前所述 Web Fetch API 而不是 Node.js 构筑,因此它能在 Vercel、Netlify、Architect(Node.js 伺服器)以及 Cloudflare 等非 Node.js 环境中运行。它还会在您开始工程项目时为您提供照相狸尾豆的适配器,因此如果您晓得要将工程项目部署到哪里,就能直奔主题。Remix 最重要的事情众所周知是它不再采用 Webpack。相反,它采用 Esbuild,它在捆绑和部署方面速度极快。其他提及每当您想优先选择 Next.js 或 Remix 时,还有其他关键点须要考虑,但我想收集这些在我看来作为开发者在开发工程项目时具有更大影响的因素。但如果您想了解更多,这里有一些我在本文中没谈到的事情的回顾。实时重新读取。Next.js 采用热模块重新读取(HMR)并默认启用,而在 Remix 上,您必须在 root.tsx 上添加两个模块以强制您的插件在代码更动时重新读取。Remix 支持 Cookie、会话和身份验证,而 Next.js 不支持——您必须采用外部库。Next.js 内置了对字体和脚本优化的支持,而 Remix 则没。两者都让您照相狸尾豆地采用 Typescript。Remix 无需执行 JavaScript 即可完成其大部分功能,而 Next.js 则不会。Remix 能在嵌套路由器中包含独立路由器两者都能采用 Tailwindcss 快速组织工作,并有自己的指南来实现它。Next.js 内置了对国际化路由器的支持。Next.js 对 AMP 具有照相狸尾豆的支持,而 Remix 则没。</p> <div id=”more-content”></div> </div> </div> </div> <div class=”module-container module-detail-ad-middle”> <div id=”_9ibbd4tzi5j” class=”n-sad-area ” data-ctkey=”0561cfbbb8ace5f0″ data-slot-id=”u3626365″ data-ad-id=”12513″ data-creative-type=”” data-display=”inlay-fix”></div> <div data-ctkey=”0561cfbbb8ace5f0″ data-slot-id=”u3626365″ data-ad-id=”12513″ data-creative-type=””> <div id=”_9ibbd4tzi5j”></div> <script> (function() { (window.slotbydup=window.slotbydup || []).push({ id: u3626365, exps: rsst&&rsst.getSearch()[expid], container: _9ibbd4tzi5j, ctkey: 0561cfbbb8ace5f0, async: true }); })(); </script> </div> </div> <div class=”module-container module-related-recommend” data-track-area=”2″ monkey=”rightFeed”> <div class=”container module-header border-left”> <div class=”element”> <div class=”content”>相关推荐</div> </div> </div> <ul class=”news-list container no-top-gap”> </ul> <div class=”container load-more”> <div class=”element”></div> </div> </div> <div class=”page-bottom-ad”> <div class=”module-container bottom-ads-wrapper module-detail-ad-middle” data-track-area=”3″> <div id=”_n3nyoy05ntj” class=”n-sad-area ” data-ctkey=”05eabf03e58e44c2″ data-slot-id=”u6056255″ data-ad-id=”12527″ data-creative-type=”” data-display=”inlay-fix”></div> <div data-ctkey=”05eabf03e58e44c2″ data-slot-id=”u6056255″ data-ad-id=”12527″ data-creative-type=””> <div id=”_n3nyoy05ntj”></div> <script> (function() { (window.slotbydup=window.slotbydup || []).push({ id: u6056255, exps: rsst&&rsst.getSearch()[expid], container: _n3nyoy05ntj, ctkey: 05eabf03e58e44c2, async: true }); })(); </script> </div> </div> <div class=”module-container bottom-ads-wrapper module-detail-ad-middle” data-track-area=”3″> <div id=”_6soy2epkw0h” class=”n-sad-area ” data-ctkey=”05a98512cc699d3a” data-slot-id=”u6056252″ data-ad-id=”12528″ data-creative-type=”” data-display=”inlay-fix”></div> <div data-ctkey=”05a98512cc699d3a” data-slot-id=”u6056252″ data-ad-id=”12528″ data-creative-type=””> <div id=”_6soy2epkw0h”></div> <script> (function() { (window.slotbydup=window.slotbydup || []).push({ id: u6056252, exps: rsst&&rsst.getSearch()[expid], container: _6soy2epkw0h, ctkey: 05a98512cc699d3a, async: true }); })(); </script> </div> </div> </div> </div> </div> <div id=”recommend-wrap” class=”aside fixed”> <div class=”scroll-touch-layout”> <div class=”news-wrapper pull-layout page-layout module-channel” data-uid=”C055F0A236EE312BC8F14C10CF93542A” data-track-area=”0″> <ul class=”news-list container content-loading no-top-gap”> </ul> </div> </div> </div> <div class=”widget-btn”> <div class=”btn refresh”></div> <div class=”btn top”></div> </div></div> <script> if (window.performance) { window.performance.firstPaintEnd = new Date().getTime() – t.navigationStart; window.performance.mark && window.performance.mark(firstPaintEnd); } </script> <script src=”//cpucdn.baidu.com/static/20221116114058/js/common/coreMobilePc.js”></script> <script> if (!GLOBAL_CONF.global.debug) { var _hmt = window._hmt || []; _hmt.push([_setVisitTag, 5921, ]); deployBaiduTJ(7e45c71c9fc634f2b7f1555da47b0b3f); } </script><script> require.config({ waitSeconds: 30, baseUrl: //cpucdn.baidu.com/static/20221116114058/js, paths: { videojs: common/videojs/dist/video.min, @: node_modules } }); </script> <script src=”//cpucdn.baidu.com/static/20221116114058/js/zui/detail-news.js”></script> <script> var entry = [zui/detail-news]; </script> <script> $(function () { require(entry, function(Detail) { new Detail().init({ iswap: true, contentType: news, contentId: 71703722555714149, scene: detail }); }); }) </script> </body> </html> <!–03264518360401831946112412–> <script> var _trace_page_logid = 0326451836; </script>

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务