diff --git a/package.json b/package.json index 99549173..58a1733d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-storefront", - "version": "8.7.3", + "version": "8.8.0", "description": "Build and deploy e-commerce progressive web apps (PWAs) in record time.", "module": "./index.js", "license": "Apache-2.0", diff --git a/src/NextScript.js b/src/NextScript.js new file mode 100644 index 00000000..041160f2 --- /dev/null +++ b/src/NextScript.js @@ -0,0 +1,30 @@ +import React from 'react' +import { NextScript as OriginalNextScript } from 'next/document' +import PropTypes from 'prop-types' + +/** + * A replacement for NextScript from `next/document` that gives you greater control over how script elements are rendered. + * This should be used in the body of `pages/_document.js` in place of `NextScript`. + */ +export default class NextScript extends OriginalNextScript { + static propTypes = { + /** + * Set to `defer` to use `defer` instead of `async` when rendering script elements. + */ + mode: PropTypes.oneOf(['async', 'defer']), + } + + static defaultProps = { + mode: 'async', + } + + getScripts() { + return super.getScripts().map(script => { + return React.cloneElement(script, { + key: script.props.src, + defer: this.props.mode === 'defer' ? true : undefined, + async: this.props.mode === 'async' ? true : undefined, + }) + }) + } +} diff --git a/test/NextScript.test.js b/test/NextScript.test.js new file mode 100644 index 00000000..ca38a4bf --- /dev/null +++ b/test/NextScript.test.js @@ -0,0 +1,38 @@ +import React, { Component } from 'react' +import { mount } from 'enzyme' + +describe('NextScriptDeferred', () => { + let NextScript + + beforeEach(() => { + jest.isolateModules(() => { + jest.doMock('next/document', () => ({ + NextScript: class OriginalNextScript extends Component { + getScripts() { + return [