Skip to content

Commit d3624bc

Browse files
authored
Added NextScript component (#101)
* Added NextScriptDeferred component that allows you to import scripts with defer instead of async in _document.js. * Add mode * add missing files
1 parent 4e29c0e commit d3624bc

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-storefront",
3-
"version": "8.7.3",
3+
"version": "8.8.0",
44
"description": "Build and deploy e-commerce progressive web apps (PWAs) in record time.",
55
"module": "./index.js",
66
"license": "Apache-2.0",

src/NextScript.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react'
2+
import { NextScript as OriginalNextScript } from 'next/document'
3+
import PropTypes from 'prop-types'
4+
5+
/**
6+
* A replacement for NextScript from `next/document` that gives you greater control over how script elements are rendered.
7+
* This should be used in the body of `pages/_document.js` in place of `NextScript`.
8+
*/
9+
export default class NextScript extends OriginalNextScript {
10+
static propTypes = {
11+
/**
12+
* Set to `defer` to use `defer` instead of `async` when rendering script elements.
13+
*/
14+
mode: PropTypes.oneOf(['async', 'defer']),
15+
}
16+
17+
static defaultProps = {
18+
mode: 'async',
19+
}
20+
21+
getScripts() {
22+
return super.getScripts().map(script => {
23+
return React.cloneElement(script, {
24+
key: script.props.src,
25+
defer: this.props.mode === 'defer' ? true : undefined,
26+
async: this.props.mode === 'async' ? true : undefined,
27+
})
28+
})
29+
}
30+
}

test/NextScript.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React, { Component } from 'react'
2+
import { mount } from 'enzyme'
3+
4+
describe('NextScriptDeferred', () => {
5+
let NextScript
6+
7+
beforeEach(() => {
8+
jest.isolateModules(() => {
9+
jest.doMock('next/document', () => ({
10+
NextScript: class OriginalNextScript extends Component {
11+
getScripts() {
12+
return [<script src="foo.js" async />]
13+
}
14+
15+
render() {
16+
return <>{this.getScripts()}</>
17+
}
18+
},
19+
}))
20+
21+
NextScript = require('react-storefront/NextScript').default
22+
})
23+
})
24+
25+
it('should remove async and add defer to all script tags returned from super.getScripts', () => {
26+
const wrapper = mount(<NextScript mode="defer" />)
27+
const scriptProps = wrapper.find('script').props()
28+
expect(scriptProps.async).toBe(undefined)
29+
expect(scriptProps.defer).toBe(true)
30+
})
31+
32+
it('should use async by default', () => {
33+
const wrapper = mount(<NextScript />)
34+
const scriptProps = wrapper.find('script').props()
35+
expect(scriptProps.async).toBe(true)
36+
expect(scriptProps.defer).toBe(undefined)
37+
})
38+
})

0 commit comments

Comments
 (0)