diff --git a/package.json b/package.json
index 7d47662a2525c1..9fcde84dc9704c 100644
--- a/package.json
+++ b/package.json
@@ -51,7 +51,7 @@
"prompts": "^2.4.1",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
- "sirv": "^1.0.14",
+ "sirv": "^1.0.17",
"ts-jest": "^27.0.4",
"ts-node": "^10.1.0",
"typescript": "^4.3.5",
diff --git a/packages/playground/assets/__tests__/assets.spec.ts b/packages/playground/assets/__tests__/assets.spec.ts
index 083148c59aff89..3e361e6e33acc4 100644
--- a/packages/playground/assets/__tests__/assets.spec.ts
+++ b/packages/playground/assets/__tests__/assets.spec.ts
@@ -183,6 +183,19 @@ test('?url import', async () => {
)
})
+describe('unicode url', () => {
+ test('from js import', async () => {
+ const src = readFile('テスト-測試-white space.js')
+ expect(await page.textContent('.unicode-url')).toMatch(
+ isBuild
+ ? `data:application/javascript;base64,${Buffer.from(src).toString(
+ 'base64'
+ )}`
+ : `/foo/テスト-測試-white space.js`
+ )
+ })
+})
+
test('new URL(..., import.meta.url)', async () => {
expect(await page.textContent('.import-meta-url')).toMatch(assetMatch)
})
diff --git a/packages/playground/assets/index.html b/packages/playground/assets/index.html
index 8668fa03b4f483..9755cf40470e03 100644
--- a/packages/playground/assets/index.html
+++ b/packages/playground/assets/index.html
@@ -1,5 +1,9 @@
+
+
new URL(`./${dynamic}`, import.meta.url)
import fooUrl from './foo.js?url'
text('.url', fooUrl)
+ import unicodeUrl from './テスト-測試-white space.js?url'
+ text('.unicode-url', unicodeUrl)
+
const metaUrl = new URL('./nested/asset.png', import.meta.url)
text('.import-meta-url', metaUrl)
document.querySelector('.import-meta-url-img').src = metaUrl
diff --git a/packages/playground/assets/static/white space.png "b/packages/playground/assets/nested/\343\203\206\343\202\271\343\203\210-\346\270\254\350\251\246-white space.png"
similarity index 100%
rename from packages/playground/assets/static/white space.png
rename to "packages/playground/assets/nested/\343\203\206\343\202\271\343\203\210-\346\270\254\350\251\246-white space.png"
diff --git "a/packages/playground/assets/\343\203\206\343\202\271\343\203\210-\346\270\254\350\251\246-white space.js" "b/packages/playground/assets/\343\203\206\343\202\271\343\203\210-\346\270\254\350\251\246-white space.js"
new file mode 100644
index 00000000000000..506a726f7f3d63
--- /dev/null
+++ "b/packages/playground/assets/\343\203\206\343\202\271\343\203\210-\346\270\254\350\251\246-white space.js"
@@ -0,0 +1 @@
+console.log('test unicode')
diff --git a/packages/vite/package.json b/packages/vite/package.json
index 6e82ac3a70c110..8cd2fd2538ed0f 100644
--- a/packages/vite/package.json
+++ b/packages/vite/package.json
@@ -113,7 +113,7 @@
"resolve.exports": "^1.0.2",
"rollup-plugin-license": "^2.5.0",
"selfsigned": "^1.10.11",
- "sirv": "^1.0.14",
+ "sirv": "^1.0.17",
"source-map": "^0.6.1",
"source-map-support": "^0.5.19",
"strip-ansi": "^6.0.0",
diff --git a/packages/vite/src/node/server/middlewares/static.ts b/packages/vite/src/node/server/middlewares/static.ts
index d630fa815821d1..8bff43a1f1ab69 100644
--- a/packages/vite/src/node/server/middlewares/static.ts
+++ b/packages/vite/src/node/server/middlewares/static.ts
@@ -8,6 +8,7 @@ import {
ensureLeadingSlash,
fsPathFromId,
isImportRequest,
+ isInternalRequest,
isWindows,
slash
} from '../../utils'
@@ -34,8 +35,8 @@ export function servePublicMiddleware(dir: string): Connect.NextHandleFunction {
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
return function viteServePublicMiddleware(req, res, next) {
- // skip import request
- if (isImportRequest(req.url!)) {
+ // skip import request and internal requests `/@fs/ /@vite-client` etc...
+ if (isImportRequest(req.url!) || isInternalRequest(req.url!)) {
return next()
}
serve(req, res, next)
@@ -50,15 +51,19 @@ export function serveStaticMiddleware(
// Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`
return function viteServeStaticMiddleware(req, res, next) {
- const url = req.url!
-
// only serve the file if it's not an html request
// so that html requests can fallthrough to our html middleware for
// special processing
- if (path.extname(cleanUrl(url)) === '.html') {
+ // also skip internal requests `/@fs/ /@vite-client` etc...
+ if (
+ path.extname(cleanUrl(req.url!)) === '.html' ||
+ isInternalRequest(req.url!)
+ ) {
return next()
}
+ const url = decodeURI(req.url!)
+
// apply aliases to static requests as well
let redirected: string | undefined
for (const { find, replacement } of config.resolve.alias) {
diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts
index 204c9c8c360c4a..26fb1a0a6793cd 100644
--- a/packages/vite/src/node/server/middlewares/transform.ts
+++ b/packages/vite/src/node/server/middlewares/transform.ts
@@ -93,7 +93,7 @@ export function transformMiddleware(
return
}
- let url = removeTimestampQuery(req.url!).replace(
+ let url = decodeURI(removeTimestampQuery(req.url!)).replace(
NULL_BYTE_PLACEHOLDER,
'\0'
)
diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts
index 56baeedb884f8a..3e350e5051c221 100644
--- a/packages/vite/src/node/utils.ts
+++ b/packages/vite/src/node/utils.ts
@@ -4,7 +4,13 @@ import fs from 'fs'
import os from 'os'
import path from 'path'
import { pathToFileURL, URL } from 'url'
-import { FS_PREFIX, DEFAULT_EXTENSIONS, VALID_ID_PREFIX } from './constants'
+import {
+ FS_PREFIX,
+ DEFAULT_EXTENSIONS,
+ VALID_ID_PREFIX,
+ CLIENT_PUBLIC_PATH,
+ ENV_PUBLIC_PATH
+} from './constants'
import resolve from 'resolve'
import builtins from 'builtin-modules'
import { FSWatcher } from 'chokidar'
@@ -122,8 +128,17 @@ export const isJSRequest = (url: string): boolean => {
}
const importQueryRE = /(\?|&)import=?(?:&|$)/
+const internalPrefixes = [
+ FS_PREFIX,
+ VALID_ID_PREFIX,
+ CLIENT_PUBLIC_PATH,
+ ENV_PUBLIC_PATH
+]
+const InternalPrefixRE = new RegExp(`^(?:${internalPrefixes.join('|')})`)
const trailingSeparatorRE = /[\?&]$/
export const isImportRequest = (url: string): boolean => importQueryRE.test(url)
+export const isInternalRequest = (url: string): boolean =>
+ InternalPrefixRE.test(url)
export function removeImportQuery(url: string): string {
return url.replace(importQueryRE, '$1').replace(trailingSeparatorRE, '')
diff --git a/yarn.lock b/yarn.lock
index 6d3f4de600ec5b..5e661a8f64859a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -877,6 +877,11 @@
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.17.tgz#25fdbdfd282c2f86ddf3fcefbd98be99cd2627e2"
integrity sha512-0p1rCgM3LLbAdwBnc7gqgnvjHg9KpbhcSphergHShlkWz8EdPawoMJ3/VbezI0mGC5eKCDzMaPgF9Yca6cKvrg==
+"@polka/url@^1.0.0-next.20":
+ version "1.0.0-next.20"
+ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.20.tgz#111b5db0f501aa89b05076fa31f0ea0e0c292cd3"
+ integrity sha512-88p7+M0QGxKpmnkfXjS4V26AnoC/eiqZutE8GLdaI5X12NY75bXSdTY9NkmYb2Xyk1O+MmkuO6Frmsj84V6I8Q==
+
"@rollup/plugin-alias@^3.1.5":
version "3.1.5"
resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.5.tgz#73356a3a1eab2e1e2fd952f9f53cd89fc740d952"
@@ -6972,7 +6977,7 @@ simple-swizzle@^0.2.2:
dependencies:
is-arrayish "^0.3.1"
-sirv@^1.0.12, sirv@^1.0.14:
+sirv@^1.0.12:
version "1.0.14"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.14.tgz#b826343f573e12653c5b3c3080a3a2a6a06595cd"
integrity sha512-czTFDFjK9lXj0u9mJ3OmJoXFztoilYS+NdRPcJoT182w44wSEkHSiO7A2517GLJ8wKM4GjCm2OXE66Dhngbzjg==
@@ -6981,6 +6986,15 @@ sirv@^1.0.12, sirv@^1.0.14:
mime "^2.3.1"
totalist "^1.0.0"
+sirv@^1.0.17:
+ version "1.0.17"
+ resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.17.tgz#86e2c63c612da5a1dace1c16c46f524aaa26ac45"
+ integrity sha512-qx9go5yraB7ekT7bCMqUHJ5jEaOC/GXBxUWv+jeWnb7WzHUFdcQPGWk7YmAwFBaQBrogpuSqd/azbC2lZRqqmw==
+ dependencies:
+ "@polka/url" "^1.0.0-next.20"
+ mime "^2.3.1"
+ totalist "^1.0.0"
+
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"