Skip to content

Commit

Permalink
fix: remove ":$" from virtual module ids to allow dev server to work …
Browse files Browse the repository at this point in the history
…with proxies (#12157)

Co-authored-by: Simon H <[email protected]>
Co-authored-by: Ben McCann <[email protected]>
  • Loading branch information
3 people authored Jan 13, 2025
1 parent c2ffdcf commit e201fa9
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 39 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-colts-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

fix: remove ":$" from virtual module ids to allow dev server to work with proxies
10 changes: 7 additions & 3 deletions packages/kit/src/exports/vite/build/build_service_worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'node:fs';
import * as vite from 'vite';
import { dedent } from '../../../core/sync/utils.js';
import { s } from '../../../utils/misc.js';
import { get_config_aliases, strip_virtual_prefix, get_env } from '../utils.js';
import { get_config_aliases, strip_virtual_prefix, get_env, normalize_id } from '../utils.js';
import { create_static_module } from '../../../core/env.js';
import { env_static_public, service_worker } from '../module_ids.js';

Expand Down Expand Up @@ -68,7 +68,8 @@ export async function build_service_worker(
name: 'service-worker-build-virtual-modules',
resolveId(id) {
if (id.startsWith('$env/') || id.startsWith('$app/') || id === '$service-worker') {
return `\0virtual:${id}`;
// ids with :$ don't work with reverse proxies like nginx
return `\0virtual:${id.substring(1)}`;
}
},

Expand All @@ -83,7 +84,10 @@ export async function build_service_worker(
return create_static_module('$env/static/public', env.public);
}

const stripped = strip_virtual_prefix(id);
const normalized_cwd = vite.normalizePath(process.cwd());
const normalized_lib = vite.normalizePath(kit.files.lib);
const relative = normalize_id(id, normalized_lib, normalized_cwd);
const stripped = strip_virtual_prefix(relative);
throw new Error(
`Cannot import ${stripped} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
);
Expand Down
24 changes: 1 addition & 23 deletions packages/kit/src/exports/vite/graph_analysis/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import path from 'node:path';
import { posixify } from '../../../utils/filesystem.js';
import { strip_virtual_prefix } from '../utils.js';
import { normalize_id, strip_virtual_prefix } from '../utils.js';
import { app_server, env_dynamic_private, env_static_private } from '../module_ids.js';

const ILLEGAL_IMPORTS = new Set([env_dynamic_private, env_static_private, app_server]);
Expand Down Expand Up @@ -85,25 +85,3 @@ export function module_guard(context, { cwd, lib }) {
}
};
}

/**
* Removes cwd/lib path from the start of the id
* @param {string} id
* @param {string} lib
* @param {string} cwd
*/
export function normalize_id(id, lib, cwd) {
if (id.startsWith(lib)) {
id = id.replace(lib, '$lib');
}

if (id.startsWith(cwd)) {
id = path.relative(cwd, id);
}

if (id === app_server) {
return '$app/server';
}

return posixify(id);
}
14 changes: 10 additions & 4 deletions packages/kit/src/exports/vite/graph_analysis/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { assert, test } from 'vitest';
import { module_guard } from './index.js';
import * as module_ids from '../module_ids.js';

/**
*
Expand Down Expand Up @@ -44,7 +45,7 @@ test('throws an error when importing $env/static/private', () => {
importedIds: ['~/src/routes/+page.svelte']
},
'~/src/routes/+page.svelte': {
importedIds: ['\0virtual:$env/static/private']
importedIds: ['\0virtual:env/static/private']
}
},
`Cannot import $env/static/private into client-side code:
Expand All @@ -60,7 +61,7 @@ test('throws an error when dynamically importing $env/static/private', () => {
importedIds: ['~/src/routes/+page.svelte']
},
'~/src/routes/+page.svelte': {
dynamicallyImportedIds: ['\0virtual:$env/static/private']
dynamicallyImportedIds: ['\0virtual:env/static/private']
}
},
`Cannot import $env/static/private into client-side code:
Expand All @@ -76,7 +77,7 @@ test('throws an error when importing $env/dynamic/private', () => {
importedIds: ['~/src/routes/+page.svelte']
},
'~/src/routes/+page.svelte': {
importedIds: ['\0virtual:$env/dynamic/private']
importedIds: ['\0virtual:env/dynamic/private']
}
},
`Cannot import $env/dynamic/private into client-side code:
Expand All @@ -92,7 +93,7 @@ test('throws an error when dynamically importing $env/dynamic/private', () => {
importedIds: ['~/src/routes/+page.svelte']
},
'~/src/routes/+page.svelte': {
dynamicallyImportedIds: ['\0virtual:$env/dynamic/private']
dynamicallyImportedIds: ['\0virtual:env/dynamic/private']
}
},
`Cannot import $env/dynamic/private into client-side code:
Expand All @@ -101,6 +102,11 @@ test('throws an error when dynamically importing $env/dynamic/private', () => {
);
});

// nginx does not process URLs containing the sequence `:$`
test('":$" is not in virtual module ids', () => {
assert.notInclude(Object.values(module_ids).join(''), ':$');
});

test('throws an error when importing a .server.js module', () => {
check(
{
Expand Down
18 changes: 14 additions & 4 deletions packages/kit/src/exports/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import { build_server_nodes } from './build/build_server.js';
import { build_service_worker } from './build/build_service_worker.js';
import { assets_base, find_deps } from './build/utils.js';
import { dev } from './dev/index.js';
import { is_illegal, module_guard, normalize_id } from './graph_analysis/index.js';
import { is_illegal, module_guard } from './graph_analysis/index.js';
import { preview } from './preview/index.js';
import { get_config_aliases, get_env, strip_virtual_prefix } from './utils.js';
import { get_config_aliases, get_env, normalize_id, strip_virtual_prefix } from './utils.js';
import { write_client_manifest } from '../../core/sync/write_client_manifest.js';
import prerender from '../../core/postbuild/prerender.js';
import analyse from '../../core/postbuild/analyse.js';
Expand Down Expand Up @@ -376,16 +376,26 @@ async function kit({ svelte_config }) {
parsed_importer.name === parsed_service_worker.name;

if (importer_is_service_worker && id !== '$service-worker' && id !== '$env/static/public') {
const normalized_cwd = vite.normalizePath(cwd);
const normalized_lib = vite.normalizePath(kit.files.lib);
throw new Error(
`Cannot import ${id} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
`Cannot import ${normalize_id(
id,
normalized_lib,
normalized_cwd
)} into service-worker code. Only the modules $service-worker and $env/static/public are available in service workers.`
);
}

import_map.set(id, importer);
}

// treat $env/static/[public|private] as virtual
if (id.startsWith('$env/') || id.startsWith('__sveltekit/') || id === '$service-worker') {
if (id.startsWith('$env/') || id === '$service-worker') {
// ids with :$ don't work with reverse proxies like nginx
return `\0virtual:${id.substring(1)}`;
}
if (id.startsWith('__sveltekit/')) {
return `\0virtual:${id}`;
}
},
Expand Down
10 changes: 5 additions & 5 deletions packages/kit/src/exports/vite/module_ids.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { fileURLToPath } from 'node:url';

export const env_static_private = '\0virtual:$env/static/private';
export const env_static_public = '\0virtual:$env/static/public';
export const env_dynamic_private = '\0virtual:$env/dynamic/private';
export const env_dynamic_public = '\0virtual:$env/dynamic/public';
export const env_static_private = '\0virtual:env/static/private';
export const env_static_public = '\0virtual:env/static/public';
export const env_dynamic_private = '\0virtual:env/dynamic/private';
export const env_dynamic_public = '\0virtual:env/dynamic/public';

export const service_worker = '\0virtual:$service-worker';
export const service_worker = '\0virtual:service-worker';

export const sveltekit_environment = '\0virtual:__sveltekit/environment';
export const sveltekit_paths = '\0virtual:__sveltekit/paths';
Expand Down
50 changes: 50 additions & 0 deletions packages/kit/src/exports/vite/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import { posixify } from '../../utils/filesystem.js';
import { negotiate } from '../../utils/http.js';
import { filter_private_env, filter_public_env } from '../../utils/env.js';
import { escape_html } from '../../utils/escape.js';
import {
app_server,
env_dynamic_private,
env_dynamic_public,
env_static_private,
env_static_public,
service_worker
} from './module_ids.js';

/**
* Transforms kit.alias to a valid vite.resolve.alias array.
Expand Down Expand Up @@ -105,4 +113,46 @@ export function not_found(req, res, base) {
}
}

/**
* Removes cwd/lib path from the start of the id
* @param {string} id
* @param {string} lib
* @param {string} cwd
*/
export function normalize_id(id, lib, cwd) {
if (id.startsWith(lib)) {
id = id.replace(lib, '$lib');
}

if (id.startsWith(cwd)) {
id = path.relative(cwd, id);
}

if (id === app_server) {
return '$app/server';
}

if (id === env_static_private) {
return '$env/static/private';
}

if (id === env_static_public) {
return '$env/static/public';
}

if (id === env_dynamic_private) {
return '$env/dynamic/private';
}

if (id === env_dynamic_public) {
return '$env/dynamic/public';
}

if (id === service_worker) {
return '$service-worker';
}

return posixify(id);
}

export const strip_virtual_prefix = /** @param {string} id */ (id) => id.replace('\0virtual:', '');

0 comments on commit e201fa9

Please sign in to comment.