加快盖茨比的表现 [英] Speed Up Gatsby Performance

查看:56
本文介绍了加快盖茨比的表现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我不确定如何解决这个bundle.js的问题,但是我找到了一个有趣的文档,关于这个主题

src/templates/pages.js

  import从'react'进行React从'prop-types'导入PropTypes从反应头盔"导入头盔从"../layouts/layout"导入布局从'../../util/AnalyticsContext'导入AnalyticsContext,{analyticsEvents}从"../WPComponents/横幅"导入横幅从"../WPComponents/CheckmarkList"导入CheckmarkList从"../WPComponents/CopyGrid"导入CopyGrid从"../WPComponents/Drawers"导入抽屉从"../WPComponents/Explainers"导入解释器从"../WPComponents/Featured"导入精选从"../WPComponents/Form"导入表单从'../WPComponents/Hero'导入Hero从"../WPComponents/Pricing"导入定价从"../WPComponents/PromoApp"导入PromoApp从"../WPComponents/PromoCircles"导入PromoCircles从"../WPComponents/PromoSlider"导入PromoSlider从'../WPComponents/ReachAnimation'导入ReachAnimation从"../WPComponents/Resources"导入资源从'../WPComponents/SimpleExplainer'导入SimpleExplainer从'../WPComponents/SimpleMedia'导入SimpleMedia从"../WPComponents/Solution"导入解决方案从"../WPComponents/感言"导入感言从"../WPComponents/Disclaimer"导入免责声明const PageTemplate = props =>{const {pageContext,data,location} =道具const组件=(pageContext.acf和& pageContext.acf.section_page)||[]让头盔const {yoast} = pageContext如果(最早){const {标题,metadesc,opengraph_title,opengraph_description,opengraph_image,典范,} =酵母头盔=(<头盔标题= {标题||''}meta = {[{名称:"robots",内容:"noindex",},{名称:"description",内容:metadesc ||''},{属性:"og:title",内容:opengraph_title ||''},{属性:'og:site_name',内容:标题||''},{属性:"og:type",内容:网站"},{属性:"og:description",内容:opengraph_description ||''},{属性:"og:image",内容:opengraph_image&&opengraph_image.source_url,},典范?{属性:"og:url",内容:规范||''}:{},]}/>)}返回 (< AnalyticsContext.Provider值= {{... analyticsEvents,}}><布局位置= {位置}>{头盔}{components.map(component => {开关(component .__ typename){案例'WordPressAcf_hero':返回<英雄键= {component.id} {... component}/>案例'WordPressAcf_featured':return< Featured key = {component.id} {... component}/>案例"WordPressAcf_solution":返回<解决方案键= {component.id} {... component}/>案例'WordPressAcf_resources':return< Resources key = {component.id} {... component}/>案例'WordPressAcf_simplemedia':返回< SimpleMedia key = {component.id} {... component}/>案例'WordPressAcf_promoapp':返回< PromoApp键= {component.id} {... component}/>案例"WordPressAcf_reach_animation":返回< ReachAnimation键= {component.id} {... component}/>案例'WordPressAcf_promoslider':返回< PromoSlider键= {component.id} {... component}/>案例'WordPressAcf_promocircles':返回< PromoCircles键= {component.id} {... component}/>案例'WordPressAcf_testimonials':返回<推荐键= {component.id} {... component}/>案例"WordPressAcf_banner":返回<横幅键= {component.id} {... component}/>案例'WordPressAcf_explainers':return< Explainers key = {component.id} {... component}/>案例'WordPressAcf_copygrid':返回< CopyGrid key = {component.id} {... component}/>案例'WordPressAcf_drawers':返回<抽屉键= {component.id} {... component}/>案例'WordPressAcf_simpleexplainer':返回< SimpleExplainer key = {component.id} {... component}/>案例'WordPressAcf_disclaimer':返回<免责声明键= {component.id} {... component}/>案例'WordPressAcf_pricing':返回 (<定价键= {component.id} {... component}/>)案例'WordPressAcf_checkmarklist':返回< CheckmarkList键= {component.id} {... component}/>案例'WordPressAcf_form':返回<表单键= {component.id} {... component}/>默认:console.log('无法识别类型:',component .__ typename)返回}})}</布局></AnalyticsContext.Provider>)}PageTemplate.propTypes = {pageContext:PropTypes.shape({acf:PropTypes.object,媒体:PropTypes.shape({边缘:PropTypes.array,}),}),}导出默认的PageTemplate 

pageCreators.js

  const path = require('path')const genericPageTemplate ='src/templates/page.js'const pageCreator = templatePath =>(操作,pageContext)=>{actions.createPage({组件:path.resolve(templatePath),路径:pageContext.pagePath,语境: {... pageContext,},})}module.exports = {createGenericPage:pageCreator(genericPageTemplate),} 

createPages.js

  const {createGenericPage} = require('./pageCreators')const generatePages = allWordpressPage =>{返回allWordpressPage.edges.map(edge => edge.node)}module.exports =(数据,操作)=>{如果(!data){console.error('createPages()','Error','`data` is undefined')抛出新错误('检索数据时出错:数据未定义')}const {allWordpressPage} =数据const pages = allWordpressPage&&generatePages(allWordpressPage)如果(!页面){console.error('createPages()','错误','无法建立页面.allWordpressPage是虚假的)抛出新的错误(``错误检索数据:allWordpressPage是虚假的'')}页数pages.forEach(page => {//跳过模块"页面如果(page.pagePath ==='/modules/'){返回;}createGenericPage(操作,页面)})} 

gatsby-node.js

 /***在此文件中实现Gatsby的Node API.**请参阅:https://www.gatsbyjs.org/docs/node-apis/*/const fs = require('fs')const queryAll = require('./util/queryAll')const createPages = require('./util/createPages')Exports.createPages =({graphql,actions})=>{返回graphql(queryAll).then(res => {如果(错误){res.errors.forEach(错误=> {console.error('错误:',error.message)})}createPages(res.data,操作)}).catch(错误=> {console.error('无法创建页面:',{error})})}Exports.sourceNodes =({action,schema})=>{const {createTypes} =操作const AdditionalTypeDefs = fs.readFileSync(`type-defs.gql`,{编码:`utf-8`,})createTypes(additionalTypeDefs)}//开发环境的临时修复程序:https://github.com/gatsbyjs/gatsby/issues/11934#issuecomment-469046186exports.onCreateWebpackConfig =({getConfig,stage})=>{const config = getConfig()如果(stage.startsWith('develop')&& config.resolve){config.resolve.alias = {... config.resolve.alias,'react-dom':'@ hot-loader/react-dom',}}} 

大约4个月前,我对此进行了调查,这是我发现的,但是下面的某些原因是由于灯塔确定页面速度的错误所致.Gatsby网站,因此有些可能不再适用(例如,在图像上使用 fadeIn = {false} loading ="eager" ,并使用 a标记而不是 gatsby-link 中的 Link .如果这些技巧之一不再成立,请发表评论或进行编辑.


  • 使用 gatsby-plugin-preact (大而轻松更改)

  • 使用< a> 标记而不是 gatsby-link

  • 使用 gatsby-plugin-purgecss (删除所有未使用的CSS.如果您使用的是Bootstrap之类的CSS框架,则非常有用

  • 在Gatsby Images上使用 fadeIn = {false} loading ="eager" 或将渐隐的持续时间设置为较短: durationFadeIn = {250}

  • 使用 gatsby-plugin-preconnect

  • 如果您有背景图片,请将其分成两张图片,一张用于折叠上方,另一张用于折叠下方(页面的初始视图在开始时就需要加载较少的图片)

  • 在让盖茨比对其进行优化之前,请手动优化折叠图像.这是一个网站我发现这样做很有帮助,但是您也许可以为此找到一个好的开源软件

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

      ...const ref = useRef()const onScreen = useOnScreen(ref,'0px')让showWidget如果(在屏幕上){showWidget = true}...返回 (< div ref = {ref}>{showWidget&&< ThirdPartyIframe/>}</div>) 

我读过的其他技巧包括


进一步阅读的资源

我创建了一个Reddit帖子,在其中发布了类似内容,我建议阅读下面的评论.它引用了这个非常受欢迎的github线程,我发现在灯塔是ap标签.(使用盖茨比)

  • Pagespeed洞察力避免仅链接关键请求列表导航,然后是我的域名两次
  • 使用Netlify和Gatsby减少初始服务器响应时间
  • 最大的满足要求的绘画就是其中之一大gatsby-background-image且速度很慢 PageSpeed Insights诊断确保在网络字体加载"
  • https://www.gatsbyjs.org/docs/how-code-splitting-works/

    While I don't completely understand these docs yet I believe that I edit this async-requires.js file to include multiple export component lines and this should result in multiple javascript bundles instead of the main large one. Perhaps if there are multiple js bundles the site will load faster because it is not just bottle necked by one. So a page can load in the specific bundle it needs to render and async load the one it doesn't need.

    Below is some of the code that I think relates to the task at hand. I'm still a bit of a beginner when it comes to gatsby so I'm not exactly sure what I can change here to allow for better performance.

    Thank you for the help.

    async-requires.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" */)
    }
    
    

    src/templates/pages.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
    

    pageCreators.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),
    }
    

    createPages.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)
        })
    }
    

    gatsby-node.js

    /**
     * Implement Gatsby's Node APIs in this file.
     *
     * See: https://www.gatsbyjs.org/docs/node-apis/
     */
    
    const fs = require('fs')
    
    const queryAll = require('./util/queryAll')
    const createPages = require('./util/createPages')
    
    exports.createPages = ({ graphql, actions }) => {
      return graphql(queryAll)
        .then(res => {
          if (res.errors) {
            res.errors.forEach(error => {
              console.error('Error:', error.message)
            })
          }
    
          createPages(res.data, actions)
        })
        .catch(error => {
          console.error('failed to create pages:', { error })
        })
    }
    
    exports.sourceNodes = ({ actions, schema }) => {
      const { createTypes } = actions
    
      const additionalTypeDefs = fs.readFileSync(`type-defs.gql`, {
        encoding: `utf-8`,
      })
      createTypes(additionalTypeDefs)
    }
    
    // temporary fix for dev env: https://github.com/gatsbyjs/gatsby/issues/11934#issuecomment-469046186
    exports.onCreateWebpackConfig = ({ getConfig, stage }) => {
      const config = getConfig()
      if (stage.startsWith('develop') && config.resolve) {
        config.resolve.alias = {
          ...config.resolve.alias,
          'react-dom': '@hot-loader/react-dom',
        }
      }
    }
    

    解决方案

    I looked into this a lot about 4 months ago and this is what I found, but some of the reasons below were due to bugs in how lighthouse determined pagespeed on Gatsby websites, so a few may not true anymore (for example, using fadeIn={false} and loading="eager" on images, and using a tags instead of Link from gatsby-link. Please leave a comment or edit if one of these tips is no longer true.


    • using gatsby-plugin-preact (big and easy change)

    • using <a> tags instead of gatsby-link

    • using gatsby-plugin-purge-css (removes all you unused CSS. Useful if you're using a CSS framework like bootstrap)

    • using fadeIn={false} and loading="eager" on Gatsby Images, or setting the duration of the fade in to be lower: durationFadeIn={250}

    • Preconnecting to certain 3rd party sites with gatsby-plugin-preconnect

    • If you have a background image, split it into 2 images, one for above the fold and one for below the fold (your initial view of the page has to load less at the beginning)

    • Optimizing my above the fold images manually before letting gatsby optimize them. This was a website I found helpful for doing that, but you may be able to find a good open source software for that.

    • Loading third party iframes after only after the user scrolls past them. Ex:

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

    Other tips I've read about include


    RESOURCES TO READ FURTHER

    I created a reddit post where I posted something similar, I'd recommend reading the comments underneath. It references this github thread which is pretty popular, and I found this post to be the most helpful on the thread.

    As well, here's a number of questions I posted related to increasing the lighthouse score for Gatsby projects. You shouldn't need them with the information listed above, but maybe they'll be useful or you'll learn something from them

    这篇关于加快盖茨比的表现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆