Skip to content

Commit 2eb09cf

Browse files
bluwydominikg
andauthored
support .svg in svelte extensions (#78)
* feat: svg import * add changeset * chore: rename asset-import to custom-extensions * fix(custom-extensions): update vite config * chore(custom-extensions): rename spec file * fix(custom-extensions): add pnpm preview * more generic prevention of asset plugin interference for custom extensions Co-authored-by: dominikg <[email protected]>
1 parent 5100376 commit 2eb09cf

File tree

11 files changed

+150
-25
lines changed

11 files changed

+150
-25
lines changed

.changeset/clever-trains-drum.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+
Support svg extension
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { getText } from '../../testUtils';
2+
3+
test('should render svg', async () => {
4+
expect(await getText('#test-svg')).toBe('Foo bar=bar');
5+
});
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: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "e2e-tests-custom-extensions",
3+
"private": true,
4+
"version": "1.0.0",
5+
"scripts": {
6+
"build": "vite build",
7+
"dev": "vite",
8+
"preview": "vite preview"
9+
},
10+
"devDependencies": {
11+
"@sveltejs/vite-plugin-svelte": "workspace:*",
12+
"svelte": "^3.38.3",
13+
"svelte-hmr": "^0.14.4",
14+
"vite": "^2.3.8"
15+
}
16+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<script>
2+
import TestSvg from './components/TestSvg.svg';
3+
</script>
4+
5+
<main>
6+
<p>
7+
Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte
8+
apps.
9+
</p>
10+
<TestSvg />
11+
</main>
12+
13+
<style>
14+
main {
15+
text-align: center;
16+
padding: 1em;
17+
max-width: 240px;
18+
margin: 0 auto;
19+
}
20+
21+
@media (min-width: 640px) {
22+
main {
23+
max-width: none;
24+
}
25+
}
26+
</style>
Lines changed: 11 additions & 0 deletions
Loading
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: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const { svelte } = require('@sveltejs/vite-plugin-svelte');
2+
const { defineConfig } = require('vite');
3+
4+
module.exports = defineConfig(() => {
5+
return {
6+
plugins: [svelte({ extensions: ['.svelte', '.svg'] })],
7+
build: {
8+
// make build faster by skipping transforms and minification
9+
target: 'esnext',
10+
minify: false
11+
},
12+
server: {
13+
watch: {
14+
// During tests we edit the files too fast and sometimes chokidar
15+
// misses change events, so enforce polling for consistency
16+
usePolling: true,
17+
interval: 100
18+
}
19+
}
20+
};
21+
});

packages/vite-plugin-svelte/src/index.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { HmrContext, IndexHtmlTransformContext, ModuleNode, Plugin, UserConfig } from 'vite';
1+
import fs from 'fs';
2+
import {
3+
HmrContext,
4+
IndexHtmlTransformContext,
5+
ModuleNode,
6+
Plugin,
7+
ResolvedConfig,
8+
UserConfig
9+
} from 'vite';
210
import { handleHotUpdate } from './handle-hot-update';
311
import { log, logCompilerWarnings } from './utils/log';
412
import { CompileData, createCompileSvelte } from './utils/compile';
@@ -35,6 +43,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
3543
// updated in configResolved hook
3644
let requestParser: IdParser;
3745
let options: ResolvedOptions;
46+
let viteConfig: ResolvedConfig;
3847
/* eslint-disable no-unused-vars */
3948
let compileSvelte: (
4049
svelteRequest: SvelteRequest,
@@ -65,6 +74,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
6574
addExtraPreprocessors(options, config);
6675
requestParser = buildIdParser(options);
6776
compileSvelte = createCompileSvelte(options);
77+
viteConfig = config;
6878
log.debug('resolved options', options);
6979
},
7080

@@ -76,22 +86,21 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
7686

7787
load(id, ssr) {
7888
const svelteRequest = requestParser(id, !!ssr);
79-
if (!svelteRequest) {
80-
return;
81-
}
82-
83-
log.debug('load', svelteRequest);
84-
const { filename, query } = svelteRequest;
85-
86-
//
87-
if (query.svelte) {
88-
if (query.type === 'style') {
89+
if (svelteRequest) {
90+
const { filename, query } = svelteRequest;
91+
// virtual css module
92+
if (query.svelte && query.type === 'style') {
8993
const css = cache.getCSS(svelteRequest);
9094
if (css) {
9195
log.debug(`load returns css for ${filename}`);
9296
return css;
9397
}
9498
}
99+
// prevent vite asset plugin from loading files as url that should be compiled in transform
100+
if (!query.url && !query.raw && viteConfig.assetsInclude(filename)) {
101+
log.debug(`load returns raw content for ${filename}`);
102+
return fs.readFileSync(filename, 'utf-8');
103+
}
95104
}
96105
},
97106

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,24 @@ import * as fs from 'fs';
77

88
const VITE_FS_PREFIX = '/@fs/';
99
const IS_WINDOWS = process.platform === 'win32';
10+
1011
export type SvelteQueryTypes = 'style' | 'script';
1112

12-
export interface SvelteQuery {
13+
export interface RequestQuery {
14+
// our own
1315
svelte?: boolean;
1416
type?: SvelteQueryTypes;
17+
// vite specific
18+
url?: boolean;
19+
raw?: boolean;
1520
}
1621

1722
export interface SvelteRequest {
1823
id: string;
1924
cssId: string;
2025
filename: string;
2126
normalizedFilename: string;
22-
query: SvelteQuery;
27+
query: RequestQuery;
2328
timestamp: number;
2429
ssr: boolean;
2530
}
@@ -39,9 +44,12 @@ function parseToSvelteRequest(
3944
timestamp: number,
4045
ssr: boolean
4146
): SvelteRequest {
42-
const query = qs.parse(rawQuery) as SvelteQuery;
43-
if (query.svelte != null) {
44-
query.svelte = true;
47+
const query: RequestQuery = qs.parse(rawQuery) as RequestQuery;
48+
for (const p of ['svelte', 'url', 'raw'] as Array<keyof RequestQuery>) {
49+
if (query[p] != null) {
50+
// @ts-ignore
51+
query[p] = true;
52+
}
4553
}
4654

4755
const normalizedFilename = normalize(filename, root);

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)