Skip to content

Commit 25009f2

Browse files
authored
feat: enable support for exports condition (#502)
* feat: enable support for exports condition * fix: use const instead of hardcoded string * fix: don't pass export condition to esbuild as it defers resolve to vite anyways
1 parent 90ff974 commit 25009f2

File tree

17 files changed

+177
-5
lines changed

17 files changed

+177
-5
lines changed

.changeset/curly-readers-invite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': minor
3+
---
4+
5+
Enable resolving via "svelte" exports condition
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as Dependency } from './src/components/Dependency.svelte';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"version": "1.0.0",
3+
"private": true,
4+
"name": "e2e-test-dep-svelte-exports-simple",
5+
"dependencies": {
6+
"e2e-test-dep-cjs-only": "file:../cjs-only"
7+
},
8+
"type": "module",
9+
"exports": {
10+
"./*": {
11+
"svelte": "./src/components/*"
12+
},
13+
".": {
14+
"svelte": "./index.js"
15+
}
16+
}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script>
2+
const label = 'dependency-import';
3+
import * as cjsOnly from 'e2e-test-dep-cjs-only';
4+
const { cjs } = cjsOnly;
5+
</script>
6+
7+
<div id="dependency-import"><span class="label">{label}</span></div>
8+
<div id="sticky-dep" class="sticky-dep">sticky-dep</div>
9+
<div id="cjs-only-dependency">{cjs()}</div>
10+
11+
<style>
12+
.label {
13+
color: green;
14+
}
15+
.sticky-dep {
16+
position: sticky;
17+
}
18+
</style>

packages/e2e-tests/prebundle-svelte-deps/__tests__/prebundle-svelte-deps.spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ test('should render Hybrid import', async () => {
1111
});
1212

1313
test('should render Simple import', async () => {
14-
expect(await getText('#hybrid .label')).toBe('dependency-import');
14+
expect(await getText('#simple .label')).toBe('dependency-import');
15+
});
16+
17+
test('should render Exports Simple import', async () => {
18+
expect(await getText('#exports-simple .label')).toBe('dependency-import');
1519
});
1620

1721
test('should render Nested import', async () => {
@@ -29,6 +33,7 @@ if (!isBuild) {
2933
const metadata = JSON.parse(metadataFile);
3034
const optimizedPaths = Object.keys(metadata.optimized);
3135
expect(optimizedPaths).toContain('e2e-test-dep-svelte-simple');
36+
expect(optimizedPaths).toContain('e2e-test-dep-svelte-exports-simple');
3237
expect(optimizedPaths).toContain('e2e-test-dep-svelte-api-only');
3338
expect(optimizedPaths).toContain('e2e-test-dep-svelte-nested');
3439
});

packages/e2e-tests/prebundle-svelte-deps/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"e2e-test-dep-svelte-api-only": "file:../_test_dependencies/svelte-api-only",
1313
"e2e-test-dep-svelte-hybrid": "file:../_test_dependencies/svelte-hybrid",
1414
"e2e-test-dep-svelte-nested": "file:../_test_dependencies/svelte-nested",
15-
"e2e-test-dep-svelte-simple": "file:../_test_dependencies/svelte-simple"
15+
"e2e-test-dep-svelte-simple": "file:../_test_dependencies/svelte-simple",
16+
"e2e-test-dep-svelte-exports-simple": "file:../_test_dependencies/svelte-exports-simple"
1617
},
1718
"devDependencies": {
1819
"@sveltejs/vite-plugin-svelte": "workspace:*",

packages/e2e-tests/prebundle-svelte-deps/src/App.svelte

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script>
22
import Hybrid from 'e2e-test-dep-svelte-hybrid';
33
import Simple from 'e2e-test-dep-svelte-simple';
4+
import { Dependency } from 'e2e-test-dep-svelte-exports-simple';
45
import { Message as Nested } from 'e2e-test-dep-svelte-nested';
56
import { setSomeContext } from 'e2e-test-dep-svelte-api-only';
67
import { getContext } from 'svelte';
@@ -19,4 +20,7 @@
1920
<Nested id="message" message="nested" />
2021
</div>
2122
<div id="api-only">api loaded: {apiOnlyLoaded}</div>
23+
<div id="exports-simple">
24+
<Dependency />
25+
</div>
2226
</main>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { browserLogs, page } from '~utils';
2+
3+
test('should not have failed requests', async () => {
4+
browserLogs.forEach((msg) => {
5+
expect(msg).not.toMatch('404');
6+
});
7+
});
8+
9+
test('should load dependency with exports svelte condition', async () => {
10+
for (const parent of ['#index-import', '#deep-import']) {
11+
expect(await page.textContent(`${parent} #dependency-import`)).toBe('dependency-import');
12+
expect(await page.textContent(`${parent} #sticky-dep`)).toBe('sticky-dep');
13+
expect(await page.textContent(`${parent} #cjs-only-dependency`)).toBe('cjs');
14+
}
15+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
7+
<title>Svelte app</title>
8+
9+
<script type="module" src="/src/main.js"></script>
10+
</head>
11+
12+
<body></body>
13+
</html>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "e2e-tests-css-none",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "vite build",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
"e2e-test-dep-svelte-exports-simple": "file:../_test_dependencies/svelte-exports-simple"
13+
},
14+
"devDependencies": {
15+
"@sveltejs/vite-plugin-svelte": "workspace:*",
16+
"svelte": "3.53.1",
17+
"vite": "^3.2.3"
18+
}
19+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<script>
2+
import { Dependency } from 'e2e-test-dep-svelte-exports-simple';
3+
import DeepDependency from 'e2e-test-dep-svelte-exports-simple/Dependency.svelte';
4+
</script>
5+
6+
<div id="index-import">
7+
<Dependency />
8+
</div>
9+
<div id="deep-import">
10+
<DeepDependency />
11+
</div>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import App from './App.svelte';
2+
3+
const app = new App({
4+
target: document.body
5+
});
6+
7+
export default app;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/// <reference types="svelte" />
2+
/// <reference types="vite/client" />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'vite';
2+
import { svelte } from '@sveltejs/vite-plugin-svelte';
3+
4+
// https://vitejs.dev/config/
5+
export default defineConfig({
6+
plugins: [svelte({ compilerOptions: { css: 'none' } })]
7+
});

packages/vite-plugin-svelte/src/utils/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ export const SVELTE_HMR_IMPORTS = [
1818
'svelte-hmr/runtime/proxy-adapter-dom.js',
1919
'svelte-hmr'
2020
];
21+
22+
export const SVELTE_EXPORT_CONDITIONS = ['svelte'];

packages/vite-plugin-svelte/src/utils/options.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
import { ConfigEnv, ResolvedConfig, UserConfig, ViteDevServer, normalizePath } from 'vite';
33
import { log } from './log';
44
import { loadSvelteConfig } from './load-svelte-config';
5-
import { SVELTE_HMR_IMPORTS, SVELTE_IMPORTS, SVELTE_RESOLVE_MAIN_FIELDS } from './constants';
5+
import {
6+
SVELTE_EXPORT_CONDITIONS,
7+
SVELTE_HMR_IMPORTS,
8+
SVELTE_IMPORTS,
9+
SVELTE_RESOLVE_MAIN_FIELDS
10+
} from './constants';
611
// eslint-disable-next-line node/no-missing-import
712
import type { CompileOptions, Warning } from 'svelte/types/compiler/interfaces';
813
import type {
@@ -315,7 +320,8 @@ export async function buildExtraViteConfig(
315320
const extraViteConfig: Partial<UserConfig> = {
316321
resolve: {
317322
mainFields: [...SVELTE_RESOLVE_MAIN_FIELDS],
318-
dedupe: [...SVELTE_IMPORTS, ...SVELTE_HMR_IMPORTS]
323+
dedupe: [...SVELTE_IMPORTS, ...SVELTE_HMR_IMPORTS],
324+
conditions: [...SVELTE_EXPORT_CONDITIONS]
319325
}
320326
// this option is still awaiting a PR in vite to be supported
321327
// see https://github.com/sveltejs/vite-plugin-svelte/issues/60
@@ -387,7 +393,17 @@ async function buildExtraConfigForDependencies(options: PreResolvedOptions, conf
387393
isBuild: options.isBuild,
388394
viteUserConfig: config,
389395
isFrameworkPkgByJson(pkgJson) {
390-
return !!pkgJson.svelte;
396+
let hasSvelteCondition = false;
397+
if (typeof pkgJson.exports === 'object') {
398+
// use replacer as a simple way to iterate over nested keys
399+
JSON.stringify(pkgJson.exports, (key, value) => {
400+
if (SVELTE_EXPORT_CONDITIONS.includes(key)) {
401+
hasSvelteCondition = true;
402+
}
403+
return value;
404+
});
405+
}
406+
return hasSvelteCondition || !!pkgJson.svelte;
391407
},
392408
isSemiFrameworkPkgByJson(pkgJson) {
393409
return !!pkgJson.dependencies?.svelte || !!pkgJson.peerDependencies?.svelte;

pnpm-lock.yaml

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)