mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-30 09:27:13 +00:00
feat(modern): remove inlined safari fix in csp mode (#7306)
This commit is contained in:
parent
ab3ff4de00
commit
2bd2c3853d
@ -23,6 +23,14 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
return this.dev ? 'cheap-module-eval-source-map' : false
|
return this.dev ? 'cheap-module-eval-source-map' : false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCspScriptPolicy () {
|
||||||
|
const { csp } = this.buildContext.options.render
|
||||||
|
if (csp) {
|
||||||
|
const { policies = {} } = csp
|
||||||
|
return policies['script-src'] || policies['default-src'] || []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getFileName (...args) {
|
getFileName (...args) {
|
||||||
if (this.buildContext.buildOptions.analyze) {
|
if (this.buildContext.buildOptions.analyze) {
|
||||||
const [key] = args
|
const [key] = args
|
||||||
@ -144,9 +152,12 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (modern) {
|
if (modern) {
|
||||||
|
const scriptPolicy = this.getCspScriptPolicy()
|
||||||
|
const noUnsafeInline = scriptPolicy && !scriptPolicy.includes('\'unsafe-inline\'')
|
||||||
plugins.push(new ModernModePlugin({
|
plugins.push(new ModernModePlugin({
|
||||||
targetDir: path.resolve(buildDir, 'dist', 'client'),
|
targetDir: path.resolve(buildDir, 'dist', 'client'),
|
||||||
isModernBuild: this.isModern
|
isModernBuild: this.isModern,
|
||||||
|
noUnsafeInline
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,9 +10,10 @@ const assetsMap = {}
|
|||||||
const watcher = new EventEmitter()
|
const watcher = new EventEmitter()
|
||||||
|
|
||||||
export default class ModernModePlugin {
|
export default class ModernModePlugin {
|
||||||
constructor ({ targetDir, isModernBuild }) {
|
constructor ({ targetDir, isModernBuild, noUnsafeInline }) {
|
||||||
this.targetDir = targetDir
|
this.targetDir = targetDir
|
||||||
this.isModernBuild = isModernBuild
|
this.isModernBuild = isModernBuild
|
||||||
|
this.noUnsafeInline = noUnsafeInline
|
||||||
}
|
}
|
||||||
|
|
||||||
apply (compiler) {
|
apply (compiler) {
|
||||||
@ -83,18 +84,40 @@ export default class ModernModePlugin {
|
|||||||
const legacyAssets = (await this.getAssets(fileName))
|
const legacyAssets = (await this.getAssets(fileName))
|
||||||
.filter(a => a.tagName === 'script' && a.attributes)
|
.filter(a => a.tagName === 'script' && a.attributes)
|
||||||
|
|
||||||
// inject Safari 10 nomodule fix
|
|
||||||
data.body.push({
|
|
||||||
tagName: 'script',
|
|
||||||
closeTag: true,
|
|
||||||
innerHTML: safariNoModuleFix
|
|
||||||
})
|
|
||||||
|
|
||||||
for (const a of legacyAssets) {
|
for (const a of legacyAssets) {
|
||||||
a.attributes.nomodule = true
|
a.attributes.nomodule = true
|
||||||
data.body.push(a)
|
data.body.push(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.noUnsafeInline) {
|
||||||
|
// inject the fix as an external script
|
||||||
|
const safariFixFilename = 'safari-nomodule-fix.js'
|
||||||
|
const safariFixPath = legacyAssets[0].attributes.src
|
||||||
|
.split('/')
|
||||||
|
.slice(0, -1)
|
||||||
|
.concat([safariFixFilename])
|
||||||
|
.join('/')
|
||||||
|
|
||||||
|
compilation.assets[safariFixFilename] = {
|
||||||
|
source: () => Buffer.from(safariNoModuleFix),
|
||||||
|
size: () => Buffer.byteLength(safariNoModuleFix)
|
||||||
|
}
|
||||||
|
data.body.push({
|
||||||
|
tagName: 'script',
|
||||||
|
closeTag: true,
|
||||||
|
attributes: {
|
||||||
|
src: safariFixPath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// inject Safari 10 nomodule fix
|
||||||
|
data.body.push({
|
||||||
|
tagName: 'script',
|
||||||
|
closeTag: true,
|
||||||
|
innerHTML: safariNoModuleFix
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
delete assetsMap[fileName]
|
delete assetsMap[fileName]
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
|
@ -54,6 +54,11 @@ describe('modern client mode (SPA)', () => {
|
|||||||
expect(response).toContain('<link rel="modulepreload" crossorigin="use-credentials" href="/_nuxt/modern-commons.app.js" as="script">')
|
expect(response).toContain('<link rel="modulepreload" crossorigin="use-credentials" href="/_nuxt/modern-commons.app.js" as="script">')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should contain safari nomodule fix', async () => {
|
||||||
|
const { body: response } = await rp(url('/'), { headers: { 'user-agent': modernUA } })
|
||||||
|
expect(response).toContain('src="/_nuxt/safari-nomodule-fix.js" crossorigin="use-credentials"')
|
||||||
|
})
|
||||||
|
|
||||||
test('should contain modern http2 pushed resources', async () => {
|
test('should contain modern http2 pushed resources', async () => {
|
||||||
const { headers: { link } } = await rp(url('/'), { headers: { 'user-agent': modernUA } })
|
const { headers: { link } } = await rp(url('/'), { headers: { 'user-agent': modernUA } })
|
||||||
expect(link).toEqual([
|
expect(link).toEqual([
|
||||||
|
1
test/fixtures/modern/nuxt.config.js
vendored
1
test/fixtures/modern/nuxt.config.js
vendored
@ -11,6 +11,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
render: {
|
render: {
|
||||||
|
csp: true,
|
||||||
crossorigin: 'use-credentials',
|
crossorigin: 'use-credentials',
|
||||||
http2: {
|
http2: {
|
||||||
push: true
|
push: true
|
||||||
|
Loading…
Reference in New Issue
Block a user