Skip to content

Commit 5695439

Browse files
committed
wip: watch preprocessor dependencies
1 parent a2acab9 commit 5695439

24 files changed

+423
-46
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.vscode
2+
.idea
3+
node_modules
4+
dist
5+
dist-ssr
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Svelte + TS + Vite
2+
3+
This template should help get you started developing with Svelte and TypeScript in Vite.
4+
5+
## Recommended IDE Setup
6+
7+
[VSCode](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
8+
9+
## Need an official Svelte framework?
10+
11+
Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.
12+
13+
## Technical considerations
14+
15+
**Why use this over SvelteKit?**
16+
17+
- SvelteKit is still a work-in-progress.
18+
- It currently does not support the pure-SPA use case.
19+
- It brings its own routing solution which might not be preferable for some users.
20+
- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.
21+
`vite dev` and `vite build` wouldn't work in a SvelteKit environment, for example.
22+
23+
This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-app` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.
24+
25+
Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.
26+
27+
**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**
28+
29+
Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.
30+
31+
**Why include `.vscode/extensions.json`?**
32+
33+
Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.
34+
35+
**Why enable `allowJs` in the TS template?**
36+
37+
While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.
38+
39+
**Why is HMR not preserving my local component state?**
40+
41+
HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).
42+
43+
If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.
44+
45+
```ts
46+
// store.ts
47+
// An extremely simple external store
48+
import { writable } from 'svelte/store';
49+
export default writable(0);
50+
```
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+
<link rel="icon" href="/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Svelte + TS + Vite App</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="/src/main.ts"></script>
12+
</body>
13+
</html>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "playground-svelte-preprocess",
3+
"private": true,
4+
"version": "0.0.0",
5+
"scripts": {
6+
"dev": "vite",
7+
"build": "vite build",
8+
"serve": "vite preview"
9+
},
10+
"devDependencies": {
11+
"@sveltejs/vite-plugin-svelte": "workspace:*",
12+
"svelte": "^3.37.0",
13+
"svelte-preprocess": "^4.7.1",
14+
"typescript": "^4.2.4",
15+
"vite": "^2.1.5"
16+
}
17+
}
Binary file not shown.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<script lang="ts">
2+
import logo from './assets/svelte.png';
3+
import Counter from './lib/Counter.svelte';
4+
import MultiFile from './lib/multifile/MultiFile.svelte';
5+
</script>
6+
7+
<main>
8+
<img src={logo} alt="Svelte Logo" />
9+
<h1>Hello Typescript!</h1>
10+
11+
<Counter />
12+
13+
<MultiFile />
14+
</main>
15+
16+
<style>
17+
:root {
18+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
19+
'Open Sans', 'Helvetica Neue', sans-serif;
20+
}
21+
22+
main {
23+
text-align: center;
24+
padding: 1em;
25+
margin: 0 auto;
26+
}
27+
28+
img {
29+
height: 16rem;
30+
width: 16rem;
31+
}
32+
33+
h1 {
34+
color: #ff3e00;
35+
text-transform: uppercase;
36+
font-size: 4rem;
37+
font-weight: 100;
38+
line-height: 1.1;
39+
margin: 2rem auto;
40+
max-width: 14rem;
41+
}
42+
43+
p {
44+
max-width: 14rem;
45+
margin: 1rem auto;
46+
line-height: 1.35;
47+
}
48+
49+
@media (min-width: 480px) {
50+
h1 {
51+
max-width: none;
52+
}
53+
54+
p {
55+
max-width: none;
56+
}
57+
}
58+
</style>
Loading
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: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script lang="ts">
2+
let count: number = 0;
3+
const increment = () => {
4+
count += 1;
5+
};
6+
</script>
7+
8+
<button on:click={increment}>
9+
Clicks: {count}
10+
</button>
11+
12+
<style>
13+
button {
14+
font-family: inherit;
15+
font-size: inherit;
16+
padding: 1em 2em;
17+
color: #ff3e00;
18+
background-color: rgba(255, 62, 0, 0.1);
19+
border-radius: 2em;
20+
border: 2px solid rgba(255, 62, 0, 0);
21+
outline: none;
22+
width: 200px;
23+
font-variant-numeric: tabular-nums;
24+
cursor: pointer;
25+
}
26+
27+
button:focus {
28+
border: 2px solid #ff3e00;
29+
}
30+
31+
button:active {
32+
background-color: rgba(255, 62, 0, 0.2);
33+
}
34+
</style>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<h1>i'm blue</h1>
2+
<h2>i'm red</h2>
3+
<p>i'm {foo}</p>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@import 'someImport';
2+
h1 {
3+
color: blue;
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script lang="ts" src="./MultiFile.ts"></script>
2+
3+
<template lang="html" src="./MultiFile.html" />
4+
5+
<style lang="scss" src="./MultiFile.scss"></style>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// eslint-disable-next-line prefer-const
2+
import './someother.css';
3+
export const foo: string = 'green';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
h2 {
2+
color: red;
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
p {
2+
color: green;
3+
}
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.getElementById('app')
5+
});
6+
7+
export default app;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const sveltePreprocess = require('svelte-preprocess')
2+
3+
module.exports = {
4+
// Consult https://github.com/sveltejs/svelte-preprocess
5+
// for more information about preprocessors
6+
preprocess: sveltePreprocess()
7+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"compilerOptions": {
3+
"moduleResolution": "node",
4+
"target": "esnext",
5+
"module": "esnext",
6+
/**
7+
* svelte-preprocess cannot figure out whether you have
8+
* a value or a type, so tell TypeScript to enforce using
9+
* `import type` instead of `import` for Types.
10+
*/
11+
"importsNotUsedAsValues": "error",
12+
"isolatedModules": true,
13+
/**
14+
* To have warnings / errors of the Svelte compiler at the
15+
* correct position, enable source maps by default.
16+
*/
17+
"sourceMap": true,
18+
"esModuleInterop": true,
19+
"skipLibCheck": true,
20+
"forceConsistentCasingInFileNames": true,
21+
"baseUrl": ".",
22+
/**
23+
* Typecheck JS in `.svelte` and `.js` files by default.
24+
* Disable checkJs if you'd like to use dynamic types in JS.
25+
* Note that setting allowJs false does not prevent the use
26+
* of JS in `.svelte` files.
27+
*/
28+
"allowJs": true,
29+
"checkJs": true
30+
},
31+
/**
32+
* Use global.d.ts instead of compilerOptions.types
33+
* to avoid limiting type declarations.
34+
*/
35+
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
36+
}
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()]
7+
});

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

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import * as relative from 'require-relative';
66

77
import { handleHotUpdate } from './handleHotUpdate';
88
import { log } from './utils/log';
9-
import { createCompileSvelte } from './utils/compile';
10-
import { buildIdParser, IdParser } from './utils/id';
9+
import { CompileData, createCompileSvelte } from './utils/compile';
10+
import { buildIdParser, IdParser, SvelteRequest } from './utils/id';
1111
import {
1212
validateInlineOptions,
1313
Options,
@@ -18,6 +18,7 @@ import {
1818
import { VitePluginSvelteCache } from './utils/VitePluginSvelteCache';
1919

2020
import { SVELTE_IMPORTS, SVELTE_RESOLVE_MAIN_FIELDS } from './utils/constants';
21+
import { watchPreprocessorDependencies } from './utils/preprocess';
2122

2223
export {
2324
Options,
@@ -52,7 +53,12 @@ export default function vitePluginSvelte(inlineOptions?: Partial<Options>): Plug
5253
let requestParser: IdParser;
5354
let options: ResolvedOptions;
5455

55-
let compileSvelte: Function;
56+
// eslint-disable-next-line no-unused-vars
57+
let compileSvelte: (
58+
svelteRequest: SvelteRequest,
59+
code: string,
60+
options: Partial<ResolvedOptions>
61+
) => Promise<CompileData>;
5662

5763
return {
5864
name: 'vite-plugin-svelte',
@@ -101,6 +107,7 @@ export default function vitePluginSvelte(inlineOptions?: Partial<Options>): Plug
101107
configureServer(server) {
102108
// eslint-disable-next-line no-unused-vars
103109
options.server = server;
110+
watchPreprocessorDependencies(server, cache);
104111
},
105112

106113
load(id, ssr) {
@@ -196,8 +203,11 @@ export default function vitePluginSvelte(inlineOptions?: Partial<Options>): Plug
196203
throw new Error(`failed to transform tagged svelte request for id ${id}`);
197204
}
198205
const compileData = await compileSvelte(svelteRequest, code, options);
199-
cache.update(compileData);
200206

207+
cache.update(compileData);
208+
if (compileData.dependencies?.length && options.server) {
209+
compileData.dependencies.forEach((d) => this.addWatchFile(d));
210+
}
201211
log.debug(`transform returns compiled js for ${filename}`);
202212
return compileData.compiled.js;
203213
},

0 commit comments

Comments
 (0)