Skip to content

Commit

Permalink
Dedupe only items with unique key (vercel#5800)
Browse files Browse the repository at this point in the history
Fixes vercel#3705
Fixes vercel#4656

- No longer automatically dedupe certain tags. Only the ones we know are *never* going to be duplicate like charSet, title etc.
- Fix `key=""` behavior, making sure that if a unique key is provided tags are deduped based on that.

For example:

```jsx
<meta property='fb:pages' content='one'>
<meta property='fb:pages' content='two'>
```

Would currently cause

```jsx
<meta property='fb:pages' content='two'>
```

### After this change:

```jsx
<meta property='fb:pages' content='one'>
<meta property='fb:pages' content='two'>
```

Then if you use next/head multiple times / want to be able to override:

```jsx
<meta property='fb:pages' content='one' key="not-unique-key">
<meta property='fb:pages' content='two' key="not-unique-key">
```

Would cause:

```jsx
<meta property='fb:pages' content='two'>
```

As `key` gets deduped correctly after this PR, similar to how React itself works.
  • Loading branch information
timneutkens authored Dec 3, 2018
1 parent 58f5dd2 commit 9890e06
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 8 deletions.
6 changes: 3 additions & 3 deletions packages/next-server/lib/head.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ function onStateChange (head) {
}
}

const METATYPES = ['name', 'httpEquiv', 'charSet', 'itemProp', 'property']
const ALLOWED_DUPLICATES = ['article:tag', 'og:image', 'og:image:alt', 'og:image:width', 'og:image:height', 'og:image:type', 'og:image:secure_url', 'og:image:url']
const METATYPES = ['name', 'httpEquiv', 'charSet', 'itemProp']

/*
returns a function for filtering head child elements
Expand All @@ -71,6 +70,7 @@ function unique () {
if (h.key && h.key.indexOf('.$') === 0) {
if (keys.has(h.key)) return false
keys.add(h.key)
return true
}
switch (h.type) {
case 'title':
Expand All @@ -89,7 +89,7 @@ function unique () {
} else {
const category = h.props[metatype]
const categories = metaCategories[metatype] || new Set()
if (categories.has(category) && ALLOWED_DUPLICATES.indexOf(category) === -1) return false
if (categories.has(category)) return false
categories.add(category)
metaCategories[metatype] = categories
}
Expand Down
9 changes: 6 additions & 3 deletions test/integration/basic/pages/head.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export default () => <div>
{/* allow duplicates for specific tags */}
<meta property='article:tag' content='tag1' key='tag1key' />
<meta property='article:tag' content='tag2' key='tag2key' />
<meta property='dedupe:tag' content='tag3' key='tag3key' />
<meta property='dedupe:tag' content='tag4' key='tag4key' />
<meta property='dedupe:tag' content='tag3' key='same-key' />
<meta property='dedupe:tag' content='tag4' key='same-key' />
<meta property='og:image' content='ogImageTag1' key='ogImageTag1Key' />
<meta property='og:image' content='ogImageTag2' key='ogImageTag2Key' />
<meta property='og:image:alt' content='ogImageAltTag1' key='ogImageAltTag1Key' />
Expand All @@ -30,6 +30,9 @@ export default () => <div>
<meta property='og:image:url' content='ogImageUrlTag1' key='ogImageUrlTag1Key' />
<meta property='og:image:url' content='ogImageUrlTag2' key='ogImageUrlTag2Key' />

<meta property='fb:pages' content='fbpages1' />
<meta property='fb:pages' content='fbpages2' />

<React.Fragment>
<title>Fragment title</title>
<meta content='meta fragment' />
Expand All @@ -43,5 +46,5 @@ export default () => <div>
<link rel='stylesheet' href='dedupe-style.css' key='my-style' />
<link rel='stylesheet' href='dedupe-style.css' key='my-style' />
</Head>
<h1>I can haz meta tags</h1>
<h1>I can have meta tags</h1>
</div>
5 changes: 3 additions & 2 deletions test/integration/basic/test/rendering.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function ({ app }, suiteName, render, fetch) {
const html = await (render('/head'))
expect(html.includes('<meta charSet="iso-8859-5" class="next-head"/>')).toBeTruthy()
expect(html.includes('<meta content="my meta" class="next-head"/>')).toBeTruthy()
expect(html.includes('I can haz meta tags')).toBeTruthy()
expect(html.includes('I can have meta tags')).toBeTruthy()
})

test('header helper dedupes tags', async () => {
Expand Down Expand Up @@ -65,7 +65,8 @@ export default function ({ app }, suiteName, render, fetch) {
expect(html).toContain('<meta property="og:image:secure_url" content="ogImageSecureUrlTag1" class="next-head"/>')
expect(html).toContain('<meta property="og:image:secure_url" content="ogImageSecureUrlTag2" class="next-head"/>')
expect(html).toContain('<meta property="og:image:url" content="ogImageUrlTag1" class="next-head"/>')
expect(html).toContain('<meta property="og:image:url" content="ogImageUrlTag2" class="next-head"/>')
expect(html).toContain('<meta property="fb:pages" content="fbpages1" class="next-head"/>')
expect(html).toContain('<meta property="fb:pages" content="fbpages2" class="next-head"/>')
})

test('header helper renders Fragment children', async () => {
Expand Down

0 comments on commit 9890e06

Please sign in to comment.