feat(vue-renderer): allow adding async attribute to <script> tags (#8347)

This commit is contained in:
Daniel Roe 2020-12-01 11:10:44 +00:00 committed by GitHub
parent 68d8fb8487
commit 8d9d6a94d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 23 additions and 3 deletions

View File

@ -68,6 +68,7 @@ export interface NuxtOptionsRender {
) => string[] ) => string[]
} }
injectScripts?: boolean injectScripts?: boolean
asyncScripts?: boolean
resourceHints?: boolean resourceHints?: boolean
ssr?: boolean ssr?: boolean
ssrLog?: boolean | 'collapsed' ssrLog?: boolean | 'collapsed'

View File

@ -51,7 +51,7 @@ export default class ModernRenderer extends SSRRenderer {
return scripts return scripts
} }
const scriptPattern = /<script[^>]*?src="([^"]*?)" defer><\/script>/g const scriptPattern = /<script[^>]*?src="([^"]*?)" defer( async)?><\/script>/g
const modernScripts = scripts.replace(scriptPattern, (scriptTag, jsFile) => { const modernScripts = scripts.replace(scriptPattern, (scriptTag, jsFile) => {
const legacyJsFile = jsFile.replace(this.publicPath, '') const legacyJsFile = jsFile.replace(this.publicPath, '')

View File

@ -42,7 +42,11 @@ export default class SSRRenderer extends BaseRenderer {
} }
renderScripts (renderContext) { renderScripts (renderContext) {
return this.addAttrs(renderContext.renderScripts(), 'script') let renderedScripts = this.addAttrs(renderContext.renderScripts(), 'script')
if (this.options.render.asyncScripts) {
renderedScripts = renderedScripts.replace(/defer>/g, 'defer async>')
}
return renderedScripts
} }
renderStyles (renderContext) { renderStyles (renderContext) {
@ -190,7 +194,11 @@ export default class SSRRenderer extends BaseRenderer {
const statePath = urlJoin(url, 'state.js') const statePath = urlJoin(url, 'state.js')
const stateUrl = urlJoin(staticAssetsBase, statePath) const stateUrl = urlJoin(staticAssetsBase, statePath)
staticAssets.push({ path: statePath, src: stateScript }) staticAssets.push({ path: statePath, src: stateScript })
APP += `<script defer src="${stateUrl}"></script>` if (this.options.render.asyncScripts) {
APP += `<script defer async src="${stateUrl}"></script>`
} else {
APP += `<script defer src="${stateUrl}"></script>`
}
preloadScripts.push(stateUrl) preloadScripts.push(stateUrl)
} else { } else {
APP += `<script>${stateScript}</script>` APP += `<script>${stateScript}</script>`

View File

@ -414,6 +414,11 @@ describe('basic ssr', () => {
expect(html).toContain('Auto discovered component!') expect(html).toContain('Auto discovered component!')
}) })
test('/ (normal <script>)', async () => {
const { html } = await nuxt.server.renderRoute('/')
expect(html).toContain('" defer>')
})
// Close server and ask nuxt to stop listening to file changes // Close server and ask nuxt to stop listening to file changes
afterAll(async () => { afterAll(async () => {
await nuxt.close() await nuxt.close()

View File

@ -62,6 +62,11 @@ describe('with-config', () => {
expect(html).toContain('<script src="/test/orion/') expect(html).toContain('<script src="/test/orion/')
}) })
test('/ (async <script>)', async () => {
const { html } = await nuxt.server.renderRoute('/')
expect(html).toContain('" defer async>')
})
test('/ (custom postcss.config.js)', async () => { test('/ (custom postcss.config.js)', async () => {
const { html } = await nuxt.server.renderRoute('/') const { html } = await nuxt.server.renderRoute('/')
expect(html).toContain('::-moz-placeholder') expect(html).toContain('::-moz-placeholder')

View File

@ -100,6 +100,7 @@ export default {
push: true, push: true,
shouldPush: (file, type) => type === 'script' shouldPush: (file, type) => type === 'script'
}, },
asyncScripts: true,
bundleRenderer: { bundleRenderer: {
shouldPreload: (file, type) => { shouldPreload: (file, type) => {
return ['script', 'style', 'font'].includes(type) return ['script', 'style', 'font'].includes(type)