加快盖茨比的表现

时间:2020-02-04 20:35:29

标签: javascript node.js reactjs gatsby

我被赋予一项工作任务,以提高项目的性能。目前,Google灯塔的得分波动不定,但总体上来说得分并不是很高,因此我们正在尝试找出如何提高其性能以向我们的领导者炫耀。

我们的项目将整个Gatsby网站作为单个JavaScript包加载。这将从站点创建一个页面应用程序,该应用程序允许通过JavaScript快速加载新页面。但是,与我们的WordPress网站一样大的东西,会产生很大的兆字节捆绑。如此大的文件包会大大降低页面速度。

我不确定如何解决这个bundle.js的问题,但是我找到了一个有趣的文档,主题为https://www.gatsbyjs.org/docs/how-code-splitting-works/

虽然我还没有完全理解这些文档,但我相信我会编辑此async-requires.js文件以包含多个导出组件行,这应该会导致多个javascript包,而不是主要的大包。也许如果有多个js捆绑包,则该站点将加载得更快,因为它不只是一个瓶颈。因此,页面可以加载需要呈现的特定包,而异步加载不需要的包。

以下是我认为与手头任务相关的一些代码。关于gatsby,我还是一个初学者,所以我不确定在这里可以进行哪些更改以提高性能。

谢谢您的帮助。

async-requires.js

  app.useGlobalPipes(
    new ValidationPipe({
      transform: true,
      forbidUnknownValues: true,
      transformOptions: {
        enableImplicitConversion: true,
      },
      exceptionFactory: errors => new ClassValidationException(errors),
    }),
  );

src / templates / pages.js

const preferDefault = m => m && m.default || m

exports.components = {
  "component---src-templates-page-js": () => import("../src/templates/page.js" /* webpackChunkName: "component---src-templates-page-js" */),
  "component---cache-dev-404-page-js": () => import("dev-404-page.js" /* webpackChunkName: "component---cache-dev-404-page-js" */),
  "component---src-pages-404-js": () => import("../src/pages/404.js" /* webpackChunkName: "component---src-pages-404-js" */)
}

pageCreators.js

import React from 'react'
import PropTypes from 'prop-types'
import Helmet from 'react-helmet'
import Layout from '../layouts/layout'
import AnalyticsContext, { analyticsEvents } from '../../util/AnalyticsContext'

import Banner from '../WPComponents/Banner'
import CheckmarkList from '../WPComponents/CheckmarkList'
import CopyGrid from '../WPComponents/CopyGrid'
import Drawers from '../WPComponents/Drawers'
import Explainers from '../WPComponents/Explainers'
import Featured from '../WPComponents/Featured'
import Form from '../WPComponents/Form'
import Hero from '../WPComponents/Hero'
import Pricing from '../WPComponents/Pricing'
import PromoApp from '../WPComponents/PromoApp'
import PromoCircles from '../WPComponents/PromoCircles'
import PromoSlider from '../WPComponents/PromoSlider'
import ReachAnimation from '../WPComponents/ReachAnimation'
import Resources from '../WPComponents/Resources'
import SimpleExplainer from '../WPComponents/SimpleExplainer'
import SimpleMedia from '../WPComponents/SimpleMedia'
import Solution from '../WPComponents/Solution'
import Testimonials from '../WPComponents/Testimonials'
import Disclaimer from '../WPComponents/Disclaimer'

const PageTemplate = props => {
  const { pageContext, data, location } = props
  const components = (pageContext.acf && pageContext.acf.section_page) || []
  let helmet
  const { yoast } = pageContext

  if (yoast) {
    const {
      title,
      metadesc,
      opengraph_title,
      opengraph_description,
      opengraph_image,
      canonical,
    } = yoast

    helmet = (
      <Helmet
        title={title || ' '}
        meta={[
          {
            name: 'robots',
            content: 'noindex',
          },
          {
            name: 'description',
            content: metadesc || ' ',
          },
          {
            property: 'og:title',
            content: opengraph_title || ' ',
          },
          { property: 'og:site_name', content: title || ' ' },
          { property: 'og:type', content: 'website' },
          {
            property: 'og:description',
            content: opengraph_description || ' ',
          },
          {
            property: 'og:image',
            content: opengraph_image && opengraph_image.source_url,
          },
          canonical
            ? {
                property: 'og:url',
                content: canonical || ' ',
              }
            : {},
        ]}
      />
    )
  }

  return (
    <AnalyticsContext.Provider
      value={{
        ...analyticsEvents,
      }}
    >
      <Layout location={location}>
        {helmet}
        {components.map(component => {
          switch (component.__typename) {
            case 'WordPressAcf_hero':
              return <Hero key={component.id} {...component} />
            case 'WordPressAcf_featured':
              return <Featured key={component.id} {...component} />
            case 'WordPressAcf_solution':
              return <Solution key={component.id} {...component} />
            case 'WordPressAcf_resources':
              return <Resources key={component.id} {...component} />
            case 'WordPressAcf_simplemedia':
              return <SimpleMedia key={component.id} {...component} />
            case 'WordPressAcf_promoapp':
              return <PromoApp key={component.id} {...component} />
            case 'WordPressAcf_reach_animation':
              return <ReachAnimation key={component.id} {...component} />
            case 'WordPressAcf_promoslider':
              return <PromoSlider key={component.id} {...component} />
            case 'WordPressAcf_promocircles':
              return <PromoCircles key={component.id} {...component} />
            case 'WordPressAcf_testimonials':
              return <Testimonials key={component.id} {...component} />
            case 'WordPressAcf_banner':
              return <Banner key={component.id} {...component} />
            case 'WordPressAcf_explainers':
              return <Explainers key={component.id} {...component} />
            case 'WordPressAcf_copygrid':
              return <CopyGrid key={component.id} {...component} />
            case 'WordPressAcf_drawers':
              return <Drawers key={component.id} {...component} />
            case 'WordPressAcf_simpleexplainer':
              return <SimpleExplainer key={component.id} {...component} />
            case 'WordPressAcf_disclaimer':
              return <Disclaimer key={component.id} {...component} />
            case 'WordPressAcf_pricing':
              return (
                <Pricing key={component.id} {...component} /> 
              )
            case 'WordPressAcf_checkmarklist':
              return <CheckmarkList key={component.id} {...component} />
            case 'WordPressAcf_form':
              return <Form key={component.id} {...component} />
            default:
              console.log('Could not recongize type:', component.__typename)
              return
          }
        })}
      </Layout>
    </AnalyticsContext.Provider>
  )
}

PageTemplate.propTypes = {
  pageContext: PropTypes.shape({
    acf: PropTypes.object,
    media: PropTypes.shape({
      edges: PropTypes.array,
    }),
  }),
}

export default PageTemplate

createPages.js

const path = require('path')
const genericPageTemplate = 'src/templates/page.js'

const pageCreator = templatePath => (actions, pageContext) => {

  actions.createPage({
    component: path.resolve(templatePath),
    path: pageContext.pagePath,
    context: {
      ...pageContext,
    },
  })
}

module.exports = {
  createGenericPage: pageCreator(genericPageTemplate),
}

gatsby-node.js

const { createGenericPage } = require('./pageCreators')

const generatePages = allWordpressPage => {
  return allWordpressPage.edges.map(edge => edge.node)
}

module.exports = (data, actions) => {
  if (!data) {
    console.error('createPages()', 'Error', '`data` is undefined')
    throw new Error('Error retrieving data: data is undefined')
  }

  const { allWordpressPage } = data

  const pages = allWordpressPage && generatePages(allWordpressPage)

  if (!pages) {
    console.error(
      'createPages()',
      'Error',
      'Could not build pages. allWordpressPage was falsy'
    )
    throw new Error('Error retreiving data: allWordpressPage was falsy')
  }

  pages &&
    pages.forEach(page => {

      // skip the 'modules' page
      if (page.pagePath === '/modules/') {
        return;
      }

      createGenericPage(actions, page)
    })
}

1 个答案:

答案 0 :(得分:2)

大约 4 个月前,我对此进行了大量研究,这就是我发现的,但以下一些原因是由于灯塔如何确定 Gatsby 网站上的页面速度的错误,所以一些可能不再正确(例如,在图像上使用 fadeIn={false}loading="eager",并使用 a 标签而不是 Link 中的 gatsby-link。如果这些提示之一不是,请发表评论或编辑更真实。


  • 使用 gatsby-plugin-preact(大而容易的变化)

  • 使用 <a> 标签而不是 gatsby-link(显然现在感觉这个问题已经解决了)

  • 使用 gatsby-plugin-purge-css(删除所有未使用的 CSS。如果您使用像 bootstrap 这样的 CSS 框架很有用)

  • 在 Gatsby Images 上使用 fadeIn={false}loading="eager",或者将淡入的持续时间设置得更短:durationFadeIn={250}

  • 使用 gatsby-plugin-preconnect

    预连接到某些 3rd 方网站
  • 如果您有背景图片,请将其分成 2 张图片,一张用于首屏,一张用于首屏(您对页面的初始视图在开始时必须加载较少)

  • 在让 gatsby 优化它们之前手动优化我的折叠图像。 This was a website 我发现这样做很有帮助,但您可能会为此找到一个好的开源软件。

  • 仅在用户滚动经过第三方 iframe 后加载它们。例如:

       ...
       const ref = useRef()
       const onScreen = useOnScreen(ref, '0px')
       let showWidget
       if (onScreen){
           showWidget = true
       }
       ...
       return (
           <div ref={ref}>
               {showWidget && <ThirdPartyIframe /> }
           </div>
       )
    

我读过的其他提示包括


进一步阅读的资源

I created a reddit post 在我发布类似内容的地方,我建议阅读下面的评论It references this github thread which is pretty popular,我发现 this post 对线程最有帮助。

此外,这里是我发布的一些与提高 Gatsby 项目的灯塔分数相关的问题。您不应该使用上面列出的信息需要它们,但也许它们会很有用,或者您会从中学到一些东西