feat(modern): remove inlined safari fix in csp mode (#7306)

This commit is contained in:
Xin Du (Clark) 2020-05-03 19:15:24 +01:00 committed by GitHub
parent ab3ff4de00
commit 2bd2c3853d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 9 deletions

View File

@ -23,6 +23,14 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
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) {
if (this.buildContext.buildOptions.analyze) {
const [key] = args
@ -144,9 +152,12 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
}
if (modern) {
const scriptPolicy = this.getCspScriptPolicy()
const noUnsafeInline = scriptPolicy && !scriptPolicy.includes('\'unsafe-inline\'')
plugins.push(new ModernModePlugin({
targetDir: path.resolve(buildDir, 'dist', 'client'),
isModernBuild: this.isModern
isModernBuild: this.isModern,
noUnsafeInline
}))
}

View File

@ -10,9 +10,10 @@ const assetsMap = {}
const watcher = new EventEmitter()
export default class ModernModePlugin {
constructor ({ targetDir, isModernBuild }) {
constructor ({ targetDir, isModernBuild, noUnsafeInline }) {
this.targetDir = targetDir
this.isModernBuild = isModernBuild
this.noUnsafeInline = noUnsafeInline
}
apply (compiler) {
@ -83,16 +84,38 @@ export default class ModernModePlugin {
const legacyAssets = (await this.getAssets(fileName))
.filter(a => a.tagName === 'script' && a.attributes)
for (const a of legacyAssets) {
a.attributes.nomodule = true
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
})
for (const a of legacyAssets) {
a.attributes.nomodule = true
data.body.push(a)
}
delete assetsMap[fileName]

View File

@ -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">')
})
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 () => {
const { headers: { link } } = await rp(url('/'), { headers: { 'user-agent': modernUA } })
expect(link).toEqual([

View File

@ -11,6 +11,7 @@ export default {
}
},
render: {
csp: true,
crossorigin: 'use-credentials',
http2: {
push: true