Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix encoding issues with payload paths #8738

Merged
merged 10 commits into from
Feb 2, 2021
3 changes: 2 additions & 1 deletion packages/generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"devalue": "^2.0.1",
"fs-extra": "^9.1.0",
"html-minifier": "^4.0.0",
"node-html-parser": "^2.1.0"
"node-html-parser": "^2.1.0",
"ufo": "^0.5.4"
},
"publishConfig": {
"access": "public"
Expand Down
11 changes: 10 additions & 1 deletion packages/generator/src/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fsExtra from 'fs-extra'
import defu from 'defu'
import htmlMinifier from 'html-minifier'
import { parse } from 'node-html-parser'
import { decode, parseURL, withoutTrailingSlash } from 'ufo'

import { isFullStatic, flatRoutes, isString, isUrl, promisifyRoute, urlJoin, waitFor, requireModule } from '@nuxt/utils'

Expand Down Expand Up @@ -161,14 +162,22 @@ export default class Generator {
return requireModule(path.join(this.options.buildDir, 'routes.json'))
}

normalizeRoute (url) {
let pathname = decode(parseURL(url).pathname)
if (!this.options.router || !this.options.router.trailingSlash) {
danielroe marked this conversation as resolved.
Show resolved Hide resolved
pathname = withoutTrailingSlash(pathname) || '/'
}
return pathname
}

async generateRoutes (routes) {
const errors = []

this.routes = []
this.generatedRoutes = new Set()

routes.forEach(({ route, ...props }) => {
route = decodeURI(route)
route = this.normalizeRoute(route)
this.routes.push({ route, ...props })
// Add routes to the tracked generated routes (for crawler)
this.generatedRoutes.add(route)
Expand Down
20 changes: 11 additions & 9 deletions packages/vue-renderer/src/renderers/ssr.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { format } from 'util'
import fs from 'fs-extra'
import consola from 'consola'
import { TARGETS, urlJoin } from '@nuxt/utils'
import { parsePath, withoutTrailingSlash } from 'ufo'
import { decode, parseURL, withoutTrailingSlash } from 'ufo'
import devalue from '@nuxt/devalue'
import { createBundleRenderer } from 'vue-server-renderer'
import BaseRenderer from './base'
Expand Down Expand Up @@ -180,7 +180,13 @@ export default class SSRRenderer extends BaseRenderer {
if (renderContext.staticAssetsBase) {
const preloadScripts = []
renderContext.staticAssets = []
const { staticAssetsBase, url, nuxt, staticAssets } = renderContext
const { staticAssetsBase, nuxt, staticAssets } = renderContext

let pathname = decode(parseURL(renderContext.url).pathname)
danielroe marked this conversation as resolved.
Show resolved Hide resolved
if (!this.options.router.trailingSlash) {
pathname = withoutTrailingSlash(pathname) || '/'
}

const { data, fetch, mutations, ...state } = nuxt

// Initial state
Expand All @@ -192,7 +198,7 @@ export default class SSRRenderer extends BaseRenderer {
// Make chunk for initial state > 10 KB
const stateScriptKb = (stateScript.length * 4 /* utf8 */) / 100
if (stateScriptKb > 10) {
const statePath = urlJoin(url, 'state.js')
const statePath = urlJoin(pathname, 'state.js')
const stateUrl = urlJoin(staticAssetsBase, statePath)
staticAssets.push({ path: statePath, src: stateScript })
if (this.options.render.asyncScripts) {
Expand All @@ -208,13 +214,9 @@ export default class SSRRenderer extends BaseRenderer {
// Save payload only if no error or redirection were made
if (!renderContext.nuxt.error && !renderContext.redirected) {
// Page level payload.js (async loaded for CSR)
const payloadPath = urlJoin(url, 'payload.js')
const payloadPath = urlJoin(pathname, 'payload.js')
const payloadUrl = urlJoin(staticAssetsBase, payloadPath)
let routePath = parsePath(url).pathname // remove query params
if (!this.options.router.trailingSlash) {
routePath = withoutTrailingSlash(routePath) || '/'
}
const payloadScript = `__NUXT_JSONP__("${routePath}", ${devalue({ data, fetch, mutations })});`
const payloadScript = `__NUXT_JSONP__("${pathname}", ${devalue({ data, fetch, mutations })});`
staticAssets.push({ path: payloadPath, src: payloadScript })
preloadScripts.push(payloadUrl)
// Add manifest preload
Expand Down
19 changes: 17 additions & 2 deletions test/dev/full-static.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import http from 'http'
import { resolve } from 'path'
import { join, resolve } from 'path'
import serveStatic from 'serve-static'
import finalhandler from 'finalhandler'
import glob from 'glob'
import { Builder, Generator, getPort, loadFixture, Nuxt, rp } from '../utils'

let port
Expand Down Expand Up @@ -43,7 +44,21 @@ describe('full-static', () => {
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/')
expect(html).toContain(
'<link rel="preload" href="https://cdn.nuxtjs.org/test/_nuxt/static/'
)
})

test('/encoding/中文', async () => {
const { body: html } = await rp(url('/encoding/中文'))

const paths = ['encoding/中文/state.js', 'encoding/中文/payload.js']

paths.forEach((path) => {
const files = glob.sync(join(distDir, '**', path))
expect(html).toContain(path)
expect(files).toContainEqual(expect.stringContaining(path))
})
})

// Close server and ask nuxt to stop listening to file changes
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/full-static/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
<NLink to="/store">
Store
</NLink>
<NLink to="/encoding/中文">
Encoding
</NLink>
<NLink to="/pagination/1">
Pagination
</NLink>
Expand Down
5 changes: 5 additions & 0 deletions test/fixtures/full-static/pages/encoding/中文.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<div>
<h1>Encoded path</h1>
</div>
</template>