在手机上是SPA的Gatsby应用,在桌面上有不同的路线。

问题描述 投票:1回答:1

"■▄▄■▓摘要

最近我的团队开始了一个落地页的项目,为了有好的SEO,我们选择了使用Gatsby。在我们项目的某一个环节,设计师把移动端的布局改成了SPA,和桌面端的布局还是有不同的路线和页面。

参考那个例子。

enter image description hereenter image description here

由于Gatsby在构建的时候就会创建页面,我们不知道环境是移动端还是桌面端,所以很难想办法处理这种行为。


🐛工作方法

我们团队认为暂时解决这个问题的一个快速方法是 map 节之间和隐藏比在桌面屏幕。而最大的问题是。在第一次加载页面时,内容几乎需要一秒钟的时间来加载,因为它不再是静态的了。

      <div>
        {
          breakpoints.md
            ? pages.map((page) => renderPage(page))
            : renderPage(selectedPageRef.current)
        }
      </div>


🚀目标

我想讨论的是一个解决方案,它可以改变页面在桌面和移动端的行为,而不会扼杀应用的SEO。

reactjs static single-page-application gatsby
1个回答
0
投票

首先,可以借助CSS媒体查询实现以下功能(隐藏侧边栏或将其转化为顶部导航)。enter image description here

然后,你可以设置一个useMediaQuery钩子(比如这里有一个 实施)来有条件地呈现 AboutEvents 组件的导入,可以采用以下两种方式之一。

A) 如果大多数用户使用的是桌面版,你可以在移动视图中用以下方法推迟导入其他两个组件(关于和事件): 1) 如果用户使用的是桌面版,你可以用以下方法推迟导入其他两个组件(关于和事件)。可加载组件:

索引页将看起来像这样。

import React from "react"
import Loadable from "@loadable/component"
import useMediaQuery from "use-media-query-hook"
import Sidebar from "../components/Sidebar"
import Home from "../components/Home"

const LoadableAbout = Loadable(() => import("../components/About"))
const LoadableEvents = Loadable(() => import("../components/Events"))-

const IndexPage = () => {
  const isMobile = useMediaQuery("(max-width: 425px)")
  return (
    <div>
      <Sidebar />
      <Home />
      {isMobile && <LoadableAbout />}
      {isMobile && <LoadableEvents />}
    </div>
  )
}

export default IndexPage

B) 如果大多数用户使用移动设备,你可以在构建时将这两个组件包含在主捆绑包中。

索引页将看起来像这样。

import React from "react"
import useMediaQuery from "use-media-query-hook"
import Sidebar from "../components/Sidebar"
import Home from "../components/Home"
import About from "../components/About"
import Events from "../components/Events"

const IndexPage = () => {
  const isMobile = useMediaQuery("(max-width: 425px)")
  return (
    <div>
      <Sidebar />
      <Home />
      {isMobile && <About />}
      {isMobile && <Events />}
    </div>
  )
}

export default IndexPage

关于SEO,搜索引擎将只看到主要组件("主页 "在路由""中,"关于 "在 "about "中,等等),因为...。isMobile 默认为 null 在上述实现中,在构建时。

关于速度,主要组件在HTML中是静态渲染的。只有在移动SPA视图中,才需要加载其他部分。


2
投票

如果你不能通过使用 mediaqueries 而你必须显示两个不同的组件,而不是相同的样式。解决这个问题的变通方法是检查什么是 window 大小,并显示一个或另一个布局。它会在显示头之前产生一个最小的延迟(如果是缓存的话微不足道),但这是我能够猜测的唯一方法。

因此,使用Gatsby的默认结构在 <Layout> 组件,你应该有这样的东西。

return (
    <>
      <Header siteTitle={data.site.siteMetadata.title} />
      <div>
        <main>{children}</main>
        <footer>
          © {new Date().getFullYear()}, Built with
          {` `}
          <a href="https://www.gatsbyjs.org">Gatsby</a>
        </footer>
      </div>
    </>
  )

所以,在你的 <Header> 你应该检查你的 window 大小,并渲染一个组件或另一个组件。

export const Header = (props) => {
  let currentWidth;

  if (typeof window !== 'undefined') currentWidth = useWindowWidth();

  return typeof window !== 'undefined' ? currentWidth >= 768 ? <DesktopPane /> : <MobilePane /> : null;
};

正如你所看到的,在返回时我检查了一下 window 是在三元链条件下定义的。如果 window 未定义(即 undefined)它返回一个 null. 如果定义了它,它就会检查当前窗口的宽度(currentWidth),还有一个三元条件,显示移动或桌面菜单。

作为一个最佳实践,链式三元不是最干净的解决方案,它们很难读取和维护,但目前,这个解决方案是可行的(当然必须重构)。

在这种情况下。useWindowWidth() 是一个自定义的钩子,在每个 window 但你可以使用任何你喜欢的尺寸。它看起来像。

import {useEffect, useState} from 'react';

const getWidth = () => window.innerWidth
  || document.documentElement.clientWidth
  || document.body.clientWidth;

export const useWindowWidth = () => {
  let [width, setWidth] = useState(getWidth());

  useEffect(() => {
    let timeoutId = null;
    const resizeListener = () => {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => setWidth(getWidth()), 150);
    };
    window.addEventListener('resize', resizeListener);
    return () => {
      window.removeEventListener('resize', resizeListener);
    };
  }, []);

  return width;
};

代码提供: https:/usehooks.com使用窗口大小。

请注意,在Gatsby的项目中,通常会检查是否有 window!==undefined 由于你所论证的观点。在compilationbuild点还没有定义。你可以查看更多关于 调试他们文档中的HTML Builds.

© www.soinside.com 2019 - 2024. All rights reserved.