Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: gatsbyjs/gatsby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: gatsby@2.27.3
Choose a base ref
...
head repository: gatsbyjs/gatsby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: gatsby@2.27.4
Choose a head ref
  • 2 commits
  • 9 files changed
  • 3 contributors

Commits on Nov 26, 2020

  1. fix(gatsby-link): don't prefetch same page (#28307) (#28313)

    * fix(gatsby-link): don't prefetch same page
    
    * test prefect intersection-observer
    
    Co-authored-by: gatsbybot <mathews.kyle+gatsbybot@gmail.com>
    (cherry picked from commit 3666130)
    
    Co-authored-by: Ward Peeters <ward@coding-tech.com>
    pieh and wardpeet authored Nov 26, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    58f12d5 View commit details
  2. chore(release): Publish

     - gatsby-admin@0.3.4
     - gatsby-link@2.6.1
     - gatsby@2.27.4
    vladar committed Nov 26, 2020
    Copy the full SHA
    48d2a60 View commit details
4 changes: 4 additions & 0 deletions packages/gatsby-admin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -3,6 +3,10 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [0.3.4](https://github.com/gatsbyjs/gatsby/compare/gatsby-admin@0.3.3...gatsby-admin@0.3.4) (2020-11-26)

**Note:** Version bump only for package gatsby-admin

## [0.3.3](https://github.com/gatsbyjs/gatsby/compare/gatsby-admin@0.3.2...gatsby-admin@0.3.3) (2020-11-25)

**Note:** Version bump only for package gatsby-admin
4 changes: 2 additions & 2 deletions packages/gatsby-admin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gatsby-admin",
"version": "0.3.3",
"version": "0.3.4",
"main": "index.js",
"author": "Max Stoiber",
"license": "MIT",
@@ -20,7 +20,7 @@
"@typescript-eslint/parser": "^2.34.0",
"csstype": "^2.6.13",
"formik": "^2.2.5",
"gatsby": "^2.27.3",
"gatsby": "^2.27.4",
"gatsby-interface": "^0.0.225",
"gatsby-plugin-typescript": "^2.7.0",
"gatsby-plugin-webfonts": "^1.1.3",
6 changes: 6 additions & 0 deletions packages/gatsby-link/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [2.6.1](https://github.com/gatsbyjs/gatsby/compare/gatsby-link@2.6.0...gatsby-link@2.6.1) (2020-11-26)

### Bug Fixes

- **gatsby-link:** don't prefetch same page ([#28307](https://github.com/gatsbyjs/gatsby/issues/28307)) ([#28313](https://github.com/gatsbyjs/gatsby/issues/28313)) ([58f12d5](https://github.com/gatsbyjs/gatsby/commit/58f12d512e14ee4998d8c0de74c7e29f792aa3e8))

# [2.6.0](https://github.com/gatsbyjs/gatsby/compare/gatsby-link@2.6.0-next.0...gatsby-link@2.6.0) (2020-11-19)

**Note:** Version bump only for package gatsby-link
2 changes: 1 addition & 1 deletion packages/gatsby-link/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "gatsby-link",
"description": "An enhanced Link component for Gatsby sites with support for resource prefetching",
"version": "2.6.0",
"version": "2.6.1",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ exports[`<Link /> matches basic snapshot 1`] = `
<div>
<a
class="link"
href="/"
href="/active"
style="color: black;"
>
link
90 changes: 84 additions & 6 deletions packages/gatsby-link/src/__tests__/index.js
Original file line number Diff line number Diff line change
@@ -44,7 +44,30 @@ const getWithAssetPrefix = (prefix = ``) => {
return withAssetPrefix
}

const setup = ({ sourcePath = `/active`, linkProps, pathPrefix = `` } = {}) => {
const setup = ({ sourcePath = `/`, linkProps, pathPrefix = `` } = {}) => {
let intersectionInstances = new WeakMap()
// mock intersectionObserver
global.IntersectionObserver = jest.fn(cb => {
let instance = {
observe: ref => {
intersectionInstances.set(ref, instance)
},
unobserve: ref => {
intersectionInstances.delete(ref)
},
disconnect: () => {},
trigger: ref => {
cb([
{
target: ref,
isIntersecting: true,
},
])
},
}

return instance
})
global.__BASE_PATH__ = pathPrefix
const source = createMemorySource(sourcePath)
const history = createHistory(source)
@@ -66,22 +89,31 @@ const setup = ({ sourcePath = `/active`, linkProps, pathPrefix = `` } = {}) => {

return Object.assign({}, utils, {
link: utils.getByText(`link`),
triggerInViewport: ref => {
intersectionInstances.get(ref).trigger(ref)
},
})
}

describe(`<Link />`, () => {
it(`matches basic snapshot`, () => {
const { container } = setup()
const { container } = setup({
linkProps: { to: `/active` },
})
expect(container).toMatchSnapshot()
})

it(`matches active snapshot`, () => {
const { container } = setup({ linkProps: { to: `/active` } })
const { container } = setup({
sourcePath: `/active`,
linkProps: { to: `/active` },
})
expect(container).toMatchSnapshot()
})

it(`matches partially active snapshot`, () => {
const { container } = setup({
sourcePath: `/active`,
linkProps: { to: `/active/nested`, partiallyActive: true },
})
expect(container).toMatchSnapshot()
@@ -150,19 +182,28 @@ describe(`<Link />`, () => {

it(`handles relative link with "./"`, () => {
const location = `./courses?sort=name`
const { link } = setup({ linkProps: { to: location } })
const { link } = setup({
sourcePath: `/active`,
linkProps: { to: location },
})
expect(link.getAttribute(`href`)).toEqual(`/active/courses?sort=name`)
})

it(`handles relative link with "../"`, () => {
const location = `../courses?sort=name`
const { link } = setup({ linkProps: { to: location } })
const { link } = setup({
sourcePath: `/active`,
linkProps: { to: location },
})
expect(link.getAttribute(`href`)).toEqual(`/courses?sort=name`)
})

it(`handles bare relative link`, () => {
const location = `courses?sort=name`
const { link } = setup({ linkProps: { to: location } })
const { link } = setup({
sourcePath: `/active`,
linkProps: { to: location },
})
expect(link.getAttribute(`href`)).toEqual(`/active/courses?sort=name`)
})

@@ -383,3 +424,40 @@ describe(`state`, () => {
)
})
})

describe(`prefetch`, () => {
beforeEach(() => {
global.___loader = {
enqueue: jest.fn(),
}
})

it(`it prefetches when in viewport`, () => {
const to = `/active`

const { link, triggerInViewport } = setup({
linkProps: { to },
})

triggerInViewport(link)

expect(global.___loader.enqueue).toHaveBeenCalledWith(
`${global.__BASE_PATH__}${to}`
)
})

it(`it does not prefetch if link is current page`, () => {
const to = `/active`

const { link, triggerInViewport } = setup({
sourcePath: `/active`,
linkProps: { to },
})

triggerInViewport(link)

expect(global.___loader.enqueue).not.toHaveBeenCalledWith(
`${global.__BASE_PATH__}${to}`
)
})
})
147 changes: 81 additions & 66 deletions packages/gatsby-link/src/index.js
Original file line number Diff line number Diff line change
@@ -93,6 +93,14 @@ const createIntersectionObserver = (el, cb) => {
return { instance: io, el }
}

function GatsbyLinkLocationWrapper(props) {
return (
<Location>
{({ location }) => <GatsbyLink {...props} _location={location} />}
</Location>
)
}

class GatsbyLink extends React.Component {
constructor(props) {
super(props)
@@ -108,23 +116,35 @@ class GatsbyLink extends React.Component {
this.handleRef = this.handleRef.bind(this)
}

_prefetch() {
let currentPath = window.location.pathname

// reach router should have the correct state
if (this.props._location && this.props._location.pathname) {
currentPath = this.props._location.pathname
}

const rewrittenPath = rewriteLinkPath(this.props.to, currentPath)
const newPathName = parsePath(rewrittenPath).pathname

// Prefech is used to speed up next navigations. When you use it on the current navigation,
// there could be a race-condition where Chrome uses the stale data instead of waiting for the network to complete
if (currentPath !== newPathName) {
___loader.enqueue(newPathName)
}
}

componentDidUpdate(prevProps, prevState) {
// Preserve non IO functionality if no support
if (this.props.to !== prevProps.to && !this.state.IOSupported) {
___loader.enqueue(
parsePath(rewriteLinkPath(this.props.to, window.location.pathname))
.pathname
)
this._prefetch()
}
}

componentDidMount() {
// Preserve non IO functionality if no support
if (!this.state.IOSupported) {
___loader.enqueue(
parsePath(rewriteLinkPath(this.props.to, window.location.pathname))
.pathname
)
this._prefetch()
}
}

@@ -148,10 +168,7 @@ class GatsbyLink extends React.Component {
if (this.state.IOSupported && ref) {
// If IO supported and element reference found, setup Observer functionality
this.io = createIntersectionObserver(ref, () => {
___loader.enqueue(
parsePath(rewriteLinkPath(this.props.to, window.location.pathname))
.pathname
)
this._prefetch()
})
}
}
@@ -181,70 +198,68 @@ class GatsbyLink extends React.Component {
partiallyActive,
state,
replace,
_location,
/* eslint-enable no-unused-vars */
...rest
} = this.props

if (process.env.NODE_ENV !== `production` && !isLocalLink(to)) {
console.warn(
`External link ${to} was detected in a Link component. Use the Link component only for internal links. See: https://gatsby.dev/internal-links`
)
}

const prefixedTo = rewriteLinkPath(to, _location.pathname)
if (!isLocalLink(prefixedTo)) {
return <a href={prefixedTo} {...rest} />
}

return (
<Location>
{({ location }) => {
const prefixedTo = rewriteLinkPath(to, location.pathname)
return isLocalLink(prefixedTo) ? (
<Link
to={prefixedTo}
state={state}
getProps={getProps}
innerRef={this.handleRef}
onMouseEnter={e => {
if (onMouseEnter) {
onMouseEnter(e)
}
___loader.hovering(parsePath(prefixedTo).pathname)
}}
onClick={e => {
if (onClick) {
onClick(e)
}

if (
e.button === 0 && // ignore right clicks
!this.props.target && // let browser handle "target=_blank"
!e.defaultPrevented && // onClick prevented default
!e.metaKey && // ignore clicks with modifier keys...
!e.altKey &&
!e.ctrlKey &&
!e.shiftKey
) {
e.preventDefault()

let shouldReplace = replace
const isCurrent =
encodeURI(prefixedTo) === window.location.pathname
if (typeof replace !== `boolean` && isCurrent) {
shouldReplace = true
}
// Make sure the necessary scripts and data are
// loaded before continuing.
window.___navigate(prefixedTo, {
state,
replace: shouldReplace,
})
}

return true
}}
{...rest}
/>
) : (
<a href={prefixedTo} {...rest} />
)
<Link
to={prefixedTo}
state={state}
getProps={getProps}
innerRef={this.handleRef}
onMouseEnter={e => {
if (onMouseEnter) {
onMouseEnter(e)
}
___loader.hovering(parsePath(prefixedTo).pathname)
}}
onClick={e => {
if (onClick) {
onClick(e)
}

if (
e.button === 0 && // ignore right clicks
!this.props.target && // let browser handle "target=_blank"
!e.defaultPrevented && // onClick prevented default
!e.metaKey && // ignore clicks with modifier keys...
!e.altKey &&
!e.ctrlKey &&
!e.shiftKey
) {
e.preventDefault()

let shouldReplace = replace
const isCurrent = encodeURI(prefixedTo) === _location.pathname

if (typeof replace !== `boolean` && isCurrent) {
shouldReplace = true
}
// Make sure the necessary scripts and data are
// loaded before continuing.
window.___navigate(prefixedTo, {
state,
replace: shouldReplace,
})
}

return true
}}
</Location>
{...rest}
/>
)
}
}
@@ -263,7 +278,7 @@ const showDeprecationWarning = (functionName, altFunctionName, version) =>
)

export default React.forwardRef((props, ref) => (
<GatsbyLink innerRef={ref} {...props} />
<GatsbyLinkLocationWrapper innerRef={ref} {...props} />
))

export const navigate = (to, options) => {
Loading