1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Add crossOrigin via props to _document Head and NextScript (#5646)

This alternative implementation of https://github.com/zeit/next.js/pull/5150 follows @timneutkens suggestion of using props.

Fixes #5150 
Fixes #3630
This commit is contained in:
Adam Lane 2018-11-13 12:36:09 -08:00 committed by Tim Neutkens
parent e8f7847645
commit 4ce095df89
4 changed files with 36 additions and 13 deletions

View file

@ -1484,6 +1484,14 @@ module.exports = {
Note: Next.js will automatically use that prefix in the scripts it loads, but this has no effect whatsoever on `/static`. If you want to serve those assets over the CDN, you'll have to introduce the prefix yourself. One way of introducing a prefix that works inside your components and varies by environment is documented [in this example](https://github.com/zeit/next.js/tree/master/examples/with-universal-configuration).
If your CDN is on a separate domain and you would like assets to be requested using a [CORS aware request](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) you can extend _document.js and specify the `crossOrigin` attribute on Head and NextScripts which is then used for all Next.js asset tags.
```js
<Head crossOrigin="anonymous">...</Head>
<body>
<Main/>
<NextScript crossOrigin="anonymous"/>
</body>
```
## Production deployment
To deploy, instead of running `next`, you want to build for production usage ahead of time. Therefore, building and starting are separate commands:

View file

@ -40,7 +40,8 @@ export class Head extends Component {
}
static propTypes = {
nonce: PropTypes.string
nonce: PropTypes.string,
crossOrigin: PropTypes.string
}
getCssLinks () {
@ -60,6 +61,7 @@ export class Head extends Component {
nonce={this.props.nonce}
rel='stylesheet'
href={`${assetPrefix}/_next/${file}`}
crossOrigin={this.props.crossOrigin}
/>
})
}
@ -73,6 +75,7 @@ export class Head extends Component {
href={`${assetPrefix}/_next/${bundle.file}`}
as='script'
nonce={this.props.nonce}
crossOrigin={this.props.crossOrigin}
/>
})
}
@ -95,6 +98,7 @@ export class Head extends Component {
rel='preload'
href={`${assetPrefix}/_next/${file}`}
as='script'
crossOrigin={this.props.crossOrigin}
/>
})
}
@ -117,9 +121,9 @@ export class Head extends Component {
return <head {...this.props}>
{head}
{page !== '/_error' && <link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}`} as='script' nonce={this.props.nonce} />}
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_app.js`} as='script' nonce={this.props.nonce} />
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} as='script' nonce={this.props.nonce} />
{page !== '/_error' && <link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} />}
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_app.js`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} />
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} as='script' nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} />
{this.getPreloadDynamicChunks()}
{this.getPreloadMainLinks()}
{this.getCssLinks()}
@ -148,7 +152,8 @@ export class NextScript extends Component {
}
static propTypes = {
nonce: PropTypes.string
nonce: PropTypes.string,
crossOrigin: PropTypes.string
}
getDynamicChunks () {
@ -158,7 +163,8 @@ export class NextScript extends Component {
async
key={bundle.file}
src={`${assetPrefix}/_next/${bundle.file}`}
nonce={this.props.nonce}
nonce={this.props.nonce}
crossOrigin={this.props.crossOrigin}
/>
})
}
@ -180,6 +186,7 @@ export class NextScript extends Component {
src={`${assetPrefix}/_next/${file}`}
nonce={this.props.nonce}
async
crossOrigin={this.props.crossOrigin}
/>
})
}
@ -195,13 +202,13 @@ export class NextScript extends Component {
const pagePathname = getPagePathname(page)
return <Fragment>
{devFiles ? devFiles.map((file) => <script key={file} src={`${assetPrefix}/_next/${file}`} nonce={this.props.nonce} />) : null}
{staticMarkup ? null : <script id="__NEXT_DATA__" type="application/json" nonce={this.props.nonce} dangerouslySetInnerHTML={{
{devFiles ? devFiles.map((file) => <script key={file} src={`${assetPrefix}/_next/${file}`} nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} />) : null}
{staticMarkup ? null : <script id="__NEXT_DATA__" type="application/json" nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} dangerouslySetInnerHTML={{
__html: NextScript.getInlineScriptSource(this.context._documentProps)
}} />}
{page !== '/_error' && <script async id={`__NEXT_PAGE__${page}`} src={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}`} nonce={this.props.nonce} />}
<script async id={`__NEXT_PAGE__/_app`} src={`${assetPrefix}/_next/static/${buildId}/pages/_app.js`} nonce={this.props.nonce} />
<script async id={`__NEXT_PAGE__/_error`} src={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} nonce={this.props.nonce} />
{page !== '/_error' && <script async id={`__NEXT_PAGE__${page}`} src={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}`} nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} />}
<script async id={`__NEXT_PAGE__/_app`} src={`${assetPrefix}/_next/static/${buildId}/pages/_app.js`} nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} />
<script async id={`__NEXT_PAGE__/_error`} src={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} nonce={this.props.nonce} crossOrigin={this.props.crossOrigin} />
{staticMarkup ? null : this.getDynamicChunks()}
{staticMarkup ? null : this.getScripts()}
</Fragment>

View file

@ -44,7 +44,7 @@ export default class MyDocument extends Document {
return (
<html>
<Head nonce='test-nonce'>
<Head nonce='test-nonce' crossOrigin='anonymous'>
{csp ? <meta httpEquiv='Content-Security-Policy' content={csp} /> : null}
<style>{`body { margin: 0 } /* custom! */`}</style>
</Head>
@ -52,7 +52,7 @@ export default class MyDocument extends Document {
<p id='custom-property'>{this.props.customProperty}</p>
<p id='document-hmr'>Hello Document HMR</p>
<Main />
<NextScript nonce='test-nonce' />
<NextScript nonce='test-nonce' crossOrigin='anonymous' />
</body>
</html>
)

View file

@ -35,6 +35,14 @@ export default function ({ app }, suiteName, render, fetch) {
expect(noncesAdded).toBe(true)
})
test('It adds crossOrigin to all scripts and preload links', async () => {
const $ = await get$('/')
const crossOrigin = 'anonymous'
$('script, link[rel=preload]').each((index, element) => {
expect($(element).attr('crossorigin') === crossOrigin).toBeTruthy()
})
})
test('It renders ctx.renderPage with enhancer correctly', async () => {
const $ = await get$('/?withEnhancer=true')
const nonce = 'RENDERED'