fix(generator): respect publicPath for static assets (#8344)

* fix: respect publicPath for static assets

* test: add test for correct `publicPath` URL handling
This commit is contained in:
Daniel Roe 2020-11-14 22:10:16 +00:00 committed by GitHub
parent e934da3c36
commit b050861332
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 7 deletions

View File

@ -6,7 +6,7 @@ import defu from 'defu'
import htmlMinifier from 'html-minifier' import htmlMinifier from 'html-minifier'
import { parse } from 'node-html-parser' import { parse } from 'node-html-parser'
import { isFullStatic, flatRoutes, isString, isUrl, promisifyRoute, waitFor } from '@nuxt/utils' import { isFullStatic, flatRoutes, isString, isUrl, promisifyRoute, urlJoin, waitFor } from '@nuxt/utils'
export default class Generator { export default class Generator {
constructor (nuxt, builder) { constructor (nuxt, builder) {
@ -28,9 +28,11 @@ export default class Generator {
) )
// Payloads for full static // Payloads for full static
if (this.isFullStatic) { if (this.isFullStatic) {
const { build: { publicPath: _publicPath }, router: { base } } = this.options
const publicPath = isUrl(_publicPath) ? _publicPath : base
const { staticAssets } = this.options.generate const { staticAssets } = this.options.generate
this.staticAssetsDir = path.resolve(this.distNuxtPath, staticAssets.dir, staticAssets.version) this.staticAssetsDir = path.resolve(this.distNuxtPath, staticAssets.dir, staticAssets.version)
this.staticAssetsBase = this.options.generate.staticAssets.versionBase this.staticAssetsBase = urlJoin(publicPath, this.options.generate.staticAssets.versionBase)
} }
// Shared payload // Shared payload

View File

@ -306,7 +306,7 @@ export default {
route = route.substr(base.length) route = route.substr(base.length)
} }
route = (route.replace(/\/+$/, '') || '/').split('?')[0].split('#')[0] route = (route.replace(/\/+$/, '') || '/').split('?')[0].split('#')[0]
const src = urlJoin(base, staticAssetsBase, route, 'payload.js') const src = urlJoin(staticAssetsBase, route, 'payload.js')
try { try {
const payload = await window.__NUXT_IMPORT__(decodeURI(route), encodeURI(src)) const payload = await window.__NUXT_IMPORT__(decodeURI(route), encodeURI(src))
this.setPagePayload(payload) this.setPagePayload(payload)

View File

@ -175,7 +175,6 @@ export default class SSRRenderer extends BaseRenderer {
if (renderContext.staticAssetsBase) { if (renderContext.staticAssetsBase) {
const preloadScripts = [] const preloadScripts = []
renderContext.staticAssets = [] renderContext.staticAssets = []
const routerBase = this.options.router.base
const { staticAssetsBase, url, nuxt, staticAssets } = renderContext const { staticAssetsBase, url, nuxt, staticAssets } = renderContext
const { data, fetch, mutations, ...state } = nuxt const { data, fetch, mutations, ...state } = nuxt
@ -189,7 +188,7 @@ export default class SSRRenderer extends BaseRenderer {
const stateScriptKb = (stateScript.length * 4 /* utf8 */) / 100 const stateScriptKb = (stateScript.length * 4 /* utf8 */) / 100
if (stateScriptKb > 10) { if (stateScriptKb > 10) {
const statePath = urlJoin(url, 'state.js') const statePath = urlJoin(url, 'state.js')
const stateUrl = urlJoin(routerBase, 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>` APP += `<script defer src="${stateUrl}"></script>`
preloadScripts.push(stateUrl) preloadScripts.push(stateUrl)
@ -199,7 +198,7 @@ export default class SSRRenderer extends BaseRenderer {
// Page level payload.js (async loaded for CSR) // Page level payload.js (async loaded for CSR)
const payloadPath = urlJoin(url, 'payload.js') const payloadPath = urlJoin(url, 'payload.js')
const payloadUrl = urlJoin(routerBase, staticAssetsBase, payloadPath) const payloadUrl = urlJoin(staticAssetsBase, payloadPath)
const routePath = (url.replace(/\/+$/, '') || '/').split('?')[0] // remove trailing slah and query params const routePath = (url.replace(/\/+$/, '') || '/').split('?')[0] // remove trailing slah and query params
const payloadScript = `__NUXT_JSONP__("${routePath}", ${devalue({ data, fetch, mutations })});` const payloadScript = `__NUXT_JSONP__("${routePath}", ${devalue({ data, fetch, mutations })});`
staticAssets.push({ path: payloadPath, src: payloadScript }) staticAssets.push({ path: payloadPath, src: payloadScript })

View File

@ -0,0 +1,53 @@
import http from 'http'
import { resolve } from 'path'
import serveStatic from 'serve-static'
import finalhandler from 'finalhandler'
import { Builder, Generator, getPort, loadFixture, Nuxt, rp } from '../utils'
let port
const url = route => 'http://localhost:' + port + route
const rootDir = resolve(__dirname, '..', 'fixtures/full-static')
const distDir = resolve(rootDir, '.nuxt-generate')
let builder
let server = null
let generator = null
describe('full-static', () => {
beforeAll(async () => {
const config = await loadFixture('full-static', {
generate: {
static: false,
dir: '.nuxt-generate'
}
})
const nuxt = new Nuxt(config)
await nuxt.ready()
builder = new Builder(nuxt)
builder.build = jest.fn()
generator = new Generator(nuxt, builder)
await generator.generate()
const serve = serveStatic(distDir)
server = http.createServer((req, res) => {
serve(req, res, finalhandler(req, res))
})
port = await getPort()
server.listen(port)
})
test('/payload (custom build.publicPath)', async () => {
const { body: html } = await rp(url('/payload'))
expect(html).toContain('<script src="https://cdn.nuxtjs.org/test/')
expect(html).toContain('<link rel="preload" href="https://cdn.nuxtjs.org/test/_nuxt/static/')
})
// Close server and ask nuxt to stop listening to file changes
afterAll(async () => {
await server.close()
})
})

View File

@ -9,7 +9,7 @@ export default {
// base: '/test', // base: '/test',
}, },
build: { build: {
publicPath: '/test/_nuxt/' publicPath: 'https://cdn.nuxtjs.org/test/_nuxt/'
}, },
foo: { foo: {
shell: process.env.SHELL shell: process.env.SHELL