@sveltejs/vite-plugin-svelte 1.3.1 → 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +12 -14
- package/dist/index.js +448 -339
- package/dist/index.js.map +1 -1
- package/package.json +8 -21
- package/src/handle-hot-update.ts +24 -24
- package/src/index.ts +23 -24
- package/src/preprocess.ts +114 -0
- package/src/utils/compile.ts +71 -23
- package/src/utils/id.ts +55 -3
- package/src/utils/load-raw.ts +132 -0
- package/src/utils/options.ts +16 -9
- package/src/utils/preprocess.ts +9 -150
- package/dist/index.cjs +0 -2226
- package/dist/index.cjs.map +0 -1
- package/src/utils/__tests__/sourcemap.spec.ts +0 -25
- package/src/utils/sourcemap.ts +0 -58
package/package.json
CHANGED
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/vite-plugin-svelte",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "dominikg",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
8
8
|
"src",
|
|
9
|
-
"
|
|
10
|
-
"LICENSE",
|
|
11
|
-
"package.json"
|
|
9
|
+
"*.d.ts"
|
|
12
10
|
],
|
|
13
11
|
"type": "module",
|
|
14
|
-
"main": "dist/index.cjs",
|
|
15
|
-
"module": "dist/index.js",
|
|
16
12
|
"types": "dist/index.d.ts",
|
|
17
13
|
"exports": {
|
|
18
14
|
".": {
|
|
19
15
|
"types": "./dist/index.d.ts",
|
|
20
|
-
"import": "./dist/index.js"
|
|
21
|
-
"require": "./dist/index.cjs"
|
|
16
|
+
"import": "./dist/index.js"
|
|
22
17
|
},
|
|
23
18
|
"./package.json": "./package.json",
|
|
24
19
|
"./src/ui/*": "./src/ui/*"
|
|
@@ -45,33 +40,25 @@
|
|
|
45
40
|
"debug": "^4.3.4",
|
|
46
41
|
"deepmerge": "^4.2.2",
|
|
47
42
|
"kleur": "^4.1.5",
|
|
48
|
-
"magic-string": "^0.
|
|
43
|
+
"magic-string": "^0.27.0",
|
|
49
44
|
"svelte-hmr": "^0.15.1",
|
|
50
45
|
"vitefu": "^0.2.2"
|
|
51
46
|
},
|
|
52
47
|
"peerDependencies": {
|
|
53
|
-
"diff-match-patch": "^1.0.5",
|
|
54
48
|
"svelte": "^3.44.0",
|
|
55
|
-
"vite": "^
|
|
56
|
-
},
|
|
57
|
-
"peerDependenciesMeta": {
|
|
58
|
-
"diff-match-patch": {
|
|
59
|
-
"optional": true
|
|
60
|
-
}
|
|
49
|
+
"vite": "^4.0.0-beta.1"
|
|
61
50
|
},
|
|
62
51
|
"devDependencies": {
|
|
63
52
|
"@types/debug": "^4.1.7",
|
|
64
|
-
"
|
|
65
|
-
"diff-match-patch": "^1.0.5",
|
|
66
|
-
"esbuild": "^0.15.14",
|
|
53
|
+
"esbuild": "^0.15.18",
|
|
67
54
|
"rollup": "^2.79.1",
|
|
68
55
|
"svelte": "^3.53.1",
|
|
69
56
|
"tsup": "^6.5.0",
|
|
70
|
-
"vite": "^
|
|
57
|
+
"vite": "^4.0.0-beta.1"
|
|
71
58
|
},
|
|
72
59
|
"scripts": {
|
|
73
60
|
"dev": "pnpm build:ci --sourcemap --watch src",
|
|
74
|
-
"build:ci": "rimraf dist && tsup-node src/index.ts --format esm
|
|
61
|
+
"build:ci": "rimraf dist && tsup-node src/index.ts --format esm",
|
|
75
62
|
"build": "pnpm build:ci --dts --sourcemap"
|
|
76
63
|
}
|
|
77
64
|
}
|
package/src/handle-hot-update.ts
CHANGED
|
@@ -20,7 +20,7 @@ export async function handleHotUpdate(
|
|
|
20
20
|
log.debug(`handleHotUpdate called before initial transform for ${svelteRequest.id}`);
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
-
const { read, server } = ctx;
|
|
23
|
+
const { read, server, modules } = ctx;
|
|
24
24
|
|
|
25
25
|
const cachedJS = cache.getJS(svelteRequest);
|
|
26
26
|
const cachedCss = cache.getCSS(svelteRequest);
|
|
@@ -35,41 +35,41 @@ export async function handleHotUpdate(
|
|
|
35
35
|
throw e;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const affectedModules =
|
|
38
|
+
const affectedModules = [...modules];
|
|
39
39
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
const cssIdx = modules.findIndex((m) => m.id === svelteRequest.cssId);
|
|
41
|
+
if (cssIdx > -1) {
|
|
42
|
+
const cssUpdated = cssChanged(cachedCss, compileData.compiled.css);
|
|
43
|
+
if (!cssUpdated) {
|
|
44
|
+
log.debug(`skipping unchanged css for ${svelteRequest.cssId}`);
|
|
45
|
+
affectedModules.splice(cssIdx, 1);
|
|
46
|
+
}
|
|
46
47
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
const jsIdx = modules.findIndex((m) => m.id === svelteRequest.id);
|
|
49
|
+
if (jsIdx > -1) {
|
|
50
|
+
const jsUpdated = jsChanged(cachedJS, compileData.compiled.js, svelteRequest.filename);
|
|
51
|
+
if (!jsUpdated) {
|
|
52
|
+
log.debug(`skipping unchanged js for ${svelteRequest.id}`);
|
|
53
|
+
affectedModules.splice(jsIdx, 1);
|
|
54
|
+
// transform won't be called, log warnings here
|
|
55
|
+
logCompilerWarnings(svelteRequest, compileData.compiled.warnings, options);
|
|
56
|
+
}
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
if (!jsUpdated) {
|
|
55
|
-
// transform won't be called, log warnings here
|
|
56
|
-
logCompilerWarnings(svelteRequest, compileData.compiled.warnings, options);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const result = [...affectedModules].filter(Boolean) as ModuleNode[];
|
|
60
|
-
|
|
61
59
|
// TODO is this enough? see also: https://github.com/vitejs/vite/issues/2274
|
|
62
|
-
const ssrModulesToInvalidate =
|
|
60
|
+
const ssrModulesToInvalidate = affectedModules.filter((m) => !!m.ssrTransformResult);
|
|
63
61
|
if (ssrModulesToInvalidate.length > 0) {
|
|
64
62
|
log.debug(`invalidating modules ${ssrModulesToInvalidate.map((m) => m.id).join(', ')}`);
|
|
65
63
|
ssrModulesToInvalidate.forEach((moduleNode) => server.moduleGraph.invalidateModule(moduleNode));
|
|
66
64
|
}
|
|
67
|
-
if (
|
|
65
|
+
if (affectedModules.length > 0) {
|
|
68
66
|
log.debug(
|
|
69
|
-
`handleHotUpdate for ${svelteRequest.id} result: ${
|
|
67
|
+
`handleHotUpdate for ${svelteRequest.id} result: ${affectedModules
|
|
68
|
+
.map((m) => m.id)
|
|
69
|
+
.join(', ')}`
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
|
-
return
|
|
72
|
+
return affectedModules;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
function cssChanged(prev?: Code, next?: Code): boolean {
|
package/src/index.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { HmrContext, ModuleNode, Plugin, ResolvedConfig, UserConfig } from 'vite
|
|
|
4
4
|
import { isDepExcluded } from 'vitefu';
|
|
5
5
|
import { handleHotUpdate } from './handle-hot-update';
|
|
6
6
|
import { log, logCompilerWarnings } from './utils/log';
|
|
7
|
-
import {
|
|
8
|
-
import { buildIdParser, IdParser
|
|
7
|
+
import { type CompileSvelte, createCompileSvelte } from './utils/compile';
|
|
8
|
+
import { buildIdParser, IdParser } from './utils/id';
|
|
9
9
|
import {
|
|
10
10
|
buildExtraViteConfig,
|
|
11
11
|
validateInlineOptions,
|
|
@@ -23,6 +23,7 @@ import { toRollupError } from './utils/error';
|
|
|
23
23
|
import { saveSvelteMetadata } from './utils/optimizer';
|
|
24
24
|
import { svelteInspector } from './ui/inspector/plugin';
|
|
25
25
|
import { VitePluginSvelteCache } from './utils/vite-plugin-svelte-cache';
|
|
26
|
+
import { loadRaw } from './utils/load-raw';
|
|
26
27
|
|
|
27
28
|
interface PluginAPI {
|
|
28
29
|
/**
|
|
@@ -45,11 +46,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
|
|
|
45
46
|
let options: ResolvedOptions;
|
|
46
47
|
let viteConfig: ResolvedConfig;
|
|
47
48
|
/* eslint-disable no-unused-vars */
|
|
48
|
-
let compileSvelte:
|
|
49
|
-
svelteRequest: SvelteRequest,
|
|
50
|
-
code: string,
|
|
51
|
-
options: Partial<ResolvedOptions>
|
|
52
|
-
) => Promise<CompileData>;
|
|
49
|
+
let compileSvelte: CompileSvelte;
|
|
53
50
|
/* eslint-enable no-unused-vars */
|
|
54
51
|
|
|
55
52
|
let resolvedSvelteSSR: Promise<PartialResolvedId | null>;
|
|
@@ -103,23 +100,26 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
|
|
|
103
100
|
setupWatchers(options, cache, requestParser);
|
|
104
101
|
},
|
|
105
102
|
|
|
106
|
-
load(id, opts) {
|
|
103
|
+
async load(id, opts) {
|
|
107
104
|
const ssr = !!opts?.ssr;
|
|
108
105
|
const svelteRequest = requestParser(id, !!ssr);
|
|
109
106
|
if (svelteRequest) {
|
|
110
|
-
const { filename, query } = svelteRequest;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
const { filename, query, raw } = svelteRequest;
|
|
108
|
+
if (raw) {
|
|
109
|
+
return loadRaw(svelteRequest, compileSvelte, options);
|
|
110
|
+
} else {
|
|
111
|
+
if (query.svelte && query.type === 'style') {
|
|
112
|
+
const css = cache.getCSS(svelteRequest);
|
|
113
|
+
if (css) {
|
|
114
|
+
log.debug(`load returns css for ${filename}`);
|
|
115
|
+
return css;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// prevent vite asset plugin from loading files as url that should be compiled in transform
|
|
119
|
+
if (viteConfig.assetsInclude(filename)) {
|
|
120
|
+
log.debug(`load returns raw content for ${filename}`);
|
|
121
|
+
return fs.readFileSync(filename, 'utf-8');
|
|
117
122
|
}
|
|
118
|
-
}
|
|
119
|
-
// prevent vite asset plugin from loading files as url that should be compiled in transform
|
|
120
|
-
if (viteConfig.assetsInclude(filename)) {
|
|
121
|
-
log.debug(`load returns raw content for ${filename}`);
|
|
122
|
-
return fs.readFileSync(filename, 'utf-8');
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
},
|
|
@@ -128,14 +128,12 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
|
|
|
128
128
|
const ssr = !!opts?.ssr;
|
|
129
129
|
const svelteRequest = requestParser(importee, ssr);
|
|
130
130
|
if (svelteRequest?.query.svelte) {
|
|
131
|
-
if (svelteRequest.query.type === 'style') {
|
|
131
|
+
if (svelteRequest.query.type === 'style' && !svelteRequest.raw) {
|
|
132
132
|
// return cssId with root prefix so postcss pipeline of vite finds the directory correctly
|
|
133
133
|
// see https://github.com/sveltejs/vite-plugin-svelte/issues/14
|
|
134
134
|
log.debug(`resolveId resolved virtual css module ${svelteRequest.cssId}`);
|
|
135
135
|
return svelteRequest.cssId;
|
|
136
136
|
}
|
|
137
|
-
log.debug(`resolveId resolved ${importee}`);
|
|
138
|
-
return importee; // query with svelte tag, an id we generated, no need for further analysis
|
|
139
137
|
}
|
|
140
138
|
|
|
141
139
|
if (ssr && importee === 'svelte') {
|
|
@@ -188,7 +186,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
|
|
|
188
186
|
async transform(code, id, opts) {
|
|
189
187
|
const ssr = !!opts?.ssr;
|
|
190
188
|
const svelteRequest = requestParser(id, ssr);
|
|
191
|
-
if (!svelteRequest || svelteRequest.query.
|
|
189
|
+
if (!svelteRequest || svelteRequest.query.type === 'style' || svelteRequest.raw) {
|
|
192
190
|
return;
|
|
193
191
|
}
|
|
194
192
|
let compileData;
|
|
@@ -238,6 +236,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
|
|
|
238
236
|
return plugins.filter(Boolean);
|
|
239
237
|
}
|
|
240
238
|
|
|
239
|
+
export { vitePreprocess } from './preprocess';
|
|
241
240
|
export { loadSvelteConfig } from './utils/load-svelte-config';
|
|
242
241
|
|
|
243
242
|
export {
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import * as vite from 'vite';
|
|
3
|
+
import type { ESBuildOptions, ResolvedConfig } from 'vite';
|
|
4
|
+
// eslint-disable-next-line node/no-missing-import
|
|
5
|
+
import type { Preprocessor, PreprocessorGroup } from 'svelte/types/compiler/preprocess';
|
|
6
|
+
|
|
7
|
+
const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'postcss', 'sss'];
|
|
8
|
+
const supportedScriptLangs = ['ts'];
|
|
9
|
+
|
|
10
|
+
export function vitePreprocess(opts?: {
|
|
11
|
+
script?: boolean;
|
|
12
|
+
style?: boolean | vite.InlineConfig | vite.ResolvedConfig;
|
|
13
|
+
}) {
|
|
14
|
+
const preprocessor: PreprocessorGroup = {};
|
|
15
|
+
if (opts?.script !== false) {
|
|
16
|
+
preprocessor.script = viteScript().script;
|
|
17
|
+
}
|
|
18
|
+
if (opts?.style !== false) {
|
|
19
|
+
const styleOpts = typeof opts?.style == 'object' ? opts?.style : undefined;
|
|
20
|
+
preprocessor.style = viteStyle(styleOpts).style;
|
|
21
|
+
}
|
|
22
|
+
return preprocessor;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function viteScript(): { script: Preprocessor } {
|
|
26
|
+
return {
|
|
27
|
+
async script({ attributes, content, filename = '' }) {
|
|
28
|
+
const lang = attributes.lang as string;
|
|
29
|
+
if (!supportedScriptLangs.includes(lang)) return;
|
|
30
|
+
const transformResult = await vite.transformWithEsbuild(content, filename, {
|
|
31
|
+
loader: lang as ESBuildOptions['loader'],
|
|
32
|
+
target: 'esnext',
|
|
33
|
+
tsconfigRaw: {
|
|
34
|
+
compilerOptions: {
|
|
35
|
+
// svelte typescript needs this flag to work with type imports
|
|
36
|
+
importsNotUsedAsValues: 'preserve',
|
|
37
|
+
preserveValueImports: true
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
code: transformResult.code,
|
|
43
|
+
map: transformResult.map
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function viteStyle(config: vite.InlineConfig | vite.ResolvedConfig = {}): {
|
|
50
|
+
style: Preprocessor;
|
|
51
|
+
} {
|
|
52
|
+
let transform: CssTransform;
|
|
53
|
+
const style: Preprocessor = async ({ attributes, content, filename = '' }) => {
|
|
54
|
+
const lang = attributes.lang as string;
|
|
55
|
+
if (!supportedStyleLangs.includes(lang)) return;
|
|
56
|
+
if (!transform) {
|
|
57
|
+
let resolvedConfig: vite.ResolvedConfig;
|
|
58
|
+
// @ts-expect-error special prop added if running in v-p-s
|
|
59
|
+
if (style.__resolvedConfig) {
|
|
60
|
+
// @ts-expect-error
|
|
61
|
+
resolvedConfig = style.__resolvedConfig;
|
|
62
|
+
} else if (isResolvedConfig(config)) {
|
|
63
|
+
resolvedConfig = config;
|
|
64
|
+
} else {
|
|
65
|
+
resolvedConfig = await vite.resolveConfig(
|
|
66
|
+
config,
|
|
67
|
+
process.env.NODE_ENV === 'production' ? 'build' : 'serve'
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
transform = getCssTransformFn(resolvedConfig);
|
|
71
|
+
}
|
|
72
|
+
const moduleId = `${filename}.${lang}`;
|
|
73
|
+
const result = await transform(content, moduleId);
|
|
74
|
+
// patch sourcemap source to point back to original filename
|
|
75
|
+
if (result.map?.sources?.[0] === moduleId) {
|
|
76
|
+
result.map.sources[0] = path.basename(filename);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
code: result.code,
|
|
80
|
+
map: result.map ?? undefined
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
// @ts-expect-error tag so can be found by v-p-s
|
|
84
|
+
style.__resolvedConfig = null;
|
|
85
|
+
return { style };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// eslint-disable-next-line no-unused-vars
|
|
89
|
+
type CssTransform = (code: string, filename: string) => Promise<{ code: string; map?: any }>;
|
|
90
|
+
|
|
91
|
+
function getCssTransformFn(config: ResolvedConfig): CssTransform {
|
|
92
|
+
// API is only available in Vite 3.2 and above
|
|
93
|
+
// TODO: Remove Vite plugin hack when bump peer dep to Vite 3.2
|
|
94
|
+
if (vite.preprocessCSS) {
|
|
95
|
+
return async (code, filename) => {
|
|
96
|
+
return vite.preprocessCSS(code, filename, config);
|
|
97
|
+
};
|
|
98
|
+
} else {
|
|
99
|
+
const pluginName = 'vite:css';
|
|
100
|
+
const plugin = config.plugins.find((p) => p.name === pluginName);
|
|
101
|
+
if (!plugin) {
|
|
102
|
+
throw new Error(`failed to find plugin ${pluginName}`);
|
|
103
|
+
}
|
|
104
|
+
if (!plugin.transform) {
|
|
105
|
+
throw new Error(`plugin ${pluginName} has no transform`);
|
|
106
|
+
}
|
|
107
|
+
// @ts-expect-error
|
|
108
|
+
return plugin.transform.bind(null);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isResolvedConfig(config: any): config is vite.ResolvedConfig {
|
|
113
|
+
return !!config.inlineConfig;
|
|
114
|
+
}
|
package/src/utils/compile.ts
CHANGED
|
@@ -6,17 +6,41 @@ import { SvelteRequest } from './id';
|
|
|
6
6
|
import { safeBase64Hash } from './hash';
|
|
7
7
|
import { log } from './log';
|
|
8
8
|
import { StatCollection } from './vite-plugin-svelte-stats';
|
|
9
|
+
//eslint-disable-next-line node/no-missing-import
|
|
10
|
+
import type { Processed } from 'svelte/types/compiler/preprocess';
|
|
11
|
+
import { createInjectScopeEverythingRulePreprocessorGroup } from './preprocess';
|
|
12
|
+
import path from 'path';
|
|
9
13
|
|
|
10
14
|
const scriptLangRE = /<script [^>]*lang=["']?([^"' >]+)["']?[^>]*>/;
|
|
11
15
|
|
|
16
|
+
export type CompileSvelte = ReturnType<typeof _createCompileSvelte>;
|
|
17
|
+
|
|
18
|
+
function mapSourcesToRelative(map: { sources?: string[] }, filename: string) {
|
|
19
|
+
// sourcemap sources are relative to the sourcemap itself
|
|
20
|
+
// assume the sourcemap location is the same as filename and turn absolute paths to relative
|
|
21
|
+
// to avoid leaking fs information like vite root
|
|
22
|
+
if (map?.sources) {
|
|
23
|
+
map.sources = map.sources.map((s) => {
|
|
24
|
+
if (path.isAbsolute(s)) {
|
|
25
|
+
const relative = path.relative(filename, s);
|
|
26
|
+
// empty string a source is not allowed, use simple filename
|
|
27
|
+
return relative === '' ? path.basename(filename) : relative;
|
|
28
|
+
} else {
|
|
29
|
+
return s;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
12
35
|
const _createCompileSvelte = (makeHot: Function) => {
|
|
13
36
|
let stats: StatCollection | undefined;
|
|
37
|
+
const devStylePreprocessor = createInjectScopeEverythingRulePreprocessorGroup();
|
|
14
38
|
return async function compileSvelte(
|
|
15
39
|
svelteRequest: SvelteRequest,
|
|
16
40
|
code: string,
|
|
17
41
|
options: Partial<ResolvedOptions>
|
|
18
42
|
): Promise<CompileData> {
|
|
19
|
-
const { filename, normalizedFilename, cssId, ssr } = svelteRequest;
|
|
43
|
+
const { filename, normalizedFilename, cssId, ssr, raw } = svelteRequest;
|
|
20
44
|
const { emitCss = true } = options;
|
|
21
45
|
const dependencies = [];
|
|
22
46
|
|
|
@@ -47,7 +71,7 @@ const _createCompileSvelte = (makeHot: Function) => {
|
|
|
47
71
|
|
|
48
72
|
const compileOptions: CompileOptions = {
|
|
49
73
|
...options.compilerOptions,
|
|
50
|
-
filename,
|
|
74
|
+
filename: normalizedFilename, // use normalized here to avoid bleeding absolute fs path
|
|
51
75
|
generate: ssr ? 'ssr' : 'dom',
|
|
52
76
|
format: 'esm'
|
|
53
77
|
};
|
|
@@ -65,10 +89,20 @@ const _createCompileSvelte = (makeHot: Function) => {
|
|
|
65
89
|
}
|
|
66
90
|
|
|
67
91
|
let preprocessed;
|
|
68
|
-
|
|
69
|
-
if (options.
|
|
92
|
+
let preprocessors = options.preprocess;
|
|
93
|
+
if (!options.isBuild && options.emitCss && options.hot) {
|
|
94
|
+
// inject preprocessor that ensures css hmr works better
|
|
95
|
+
if (!Array.isArray(preprocessors)) {
|
|
96
|
+
preprocessors = preprocessors
|
|
97
|
+
? [preprocessors, devStylePreprocessor]
|
|
98
|
+
: [devStylePreprocessor];
|
|
99
|
+
} else {
|
|
100
|
+
preprocessors = preprocessors.concat(devStylePreprocessor);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (preprocessors) {
|
|
70
104
|
try {
|
|
71
|
-
preprocessed = await preprocess(code,
|
|
105
|
+
preprocessed = await preprocess(code, preprocessors, { filename }); // full filename here so postcss works
|
|
72
106
|
} catch (e) {
|
|
73
107
|
e.message = `Error while preprocessing ${filename}${e.message ? ` - ${e.message}` : ''}`;
|
|
74
108
|
throw e;
|
|
@@ -77,6 +111,13 @@ const _createCompileSvelte = (makeHot: Function) => {
|
|
|
77
111
|
if (preprocessed.dependencies) dependencies.push(...preprocessed.dependencies);
|
|
78
112
|
if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;
|
|
79
113
|
}
|
|
114
|
+
if (typeof preprocessed?.map === 'object') {
|
|
115
|
+
mapSourcesToRelative(preprocessed?.map, filename);
|
|
116
|
+
}
|
|
117
|
+
if (raw && svelteRequest.query.type === 'preprocessed') {
|
|
118
|
+
// shortcut
|
|
119
|
+
return { preprocessed: preprocessed ?? { code } } as CompileData;
|
|
120
|
+
}
|
|
80
121
|
const finalCode = preprocessed ? preprocessed.code : code;
|
|
81
122
|
const dynamicCompileOptions = await options.experimental?.dynamicCompileOptions?.({
|
|
82
123
|
filename,
|
|
@@ -100,24 +141,29 @@ const _createCompileSvelte = (makeHot: Function) => {
|
|
|
100
141
|
if (endStat) {
|
|
101
142
|
endStat();
|
|
102
143
|
}
|
|
144
|
+
mapSourcesToRelative(compiled.js?.map, filename);
|
|
145
|
+
mapSourcesToRelative(compiled.css?.map, filename);
|
|
146
|
+
if (!raw) {
|
|
147
|
+
// wire css import and code for hmr
|
|
148
|
+
const hasCss = compiled.css?.code?.trim().length > 0;
|
|
149
|
+
// compiler might not emit css with mode none or it may be empty
|
|
150
|
+
if (emitCss && hasCss) {
|
|
151
|
+
// TODO properly update sourcemap?
|
|
152
|
+
compiled.js.code += `\nimport ${JSON.stringify(cssId)};\n`;
|
|
153
|
+
}
|
|
103
154
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
hotOptions: { ...options.hot, injectCss: options.hot?.injectCss === true && hasCss },
|
|
117
|
-
compiled,
|
|
118
|
-
originalCode: code,
|
|
119
|
-
compileOptions: finalCompileOptions
|
|
120
|
-
});
|
|
155
|
+
// only apply hmr when not in ssr context and hot options are set
|
|
156
|
+
if (!ssr && makeHot) {
|
|
157
|
+
compiled.js.code = makeHot({
|
|
158
|
+
id: filename,
|
|
159
|
+
compiledCode: compiled.js.code,
|
|
160
|
+
//@ts-expect-error hot isn't a boolean at this point
|
|
161
|
+
hotOptions: { ...options.hot, injectCss: options.hot?.injectCss === true && hasCss },
|
|
162
|
+
compiled,
|
|
163
|
+
originalCode: code,
|
|
164
|
+
compileOptions: finalCompileOptions
|
|
165
|
+
});
|
|
166
|
+
}
|
|
121
167
|
}
|
|
122
168
|
|
|
123
169
|
compiled.js.dependencies = dependencies;
|
|
@@ -129,7 +175,8 @@ const _createCompileSvelte = (makeHot: Function) => {
|
|
|
129
175
|
// @ts-ignore
|
|
130
176
|
compiled,
|
|
131
177
|
ssr,
|
|
132
|
-
dependencies
|
|
178
|
+
dependencies,
|
|
179
|
+
preprocessed: preprocessed ?? { code }
|
|
133
180
|
};
|
|
134
181
|
};
|
|
135
182
|
};
|
|
@@ -190,4 +237,5 @@ export interface CompileData {
|
|
|
190
237
|
compiled: Compiled;
|
|
191
238
|
ssr: boolean | undefined;
|
|
192
239
|
dependencies: string[];
|
|
240
|
+
preprocessed: Processed;
|
|
193
241
|
}
|
package/src/utils/id.ts
CHANGED
|
@@ -3,19 +3,39 @@ import { createFilter } from 'vite';
|
|
|
3
3
|
import { Arrayable, ResolvedOptions } from './options';
|
|
4
4
|
import { normalizePath } from 'vite';
|
|
5
5
|
import * as fs from 'fs';
|
|
6
|
+
//eslint-disable-next-line node/no-missing-import
|
|
7
|
+
import { CompileOptions } from 'svelte/types/compiler/interfaces';
|
|
8
|
+
import { log } from './log';
|
|
6
9
|
|
|
7
10
|
const VITE_FS_PREFIX = '/@fs/';
|
|
8
11
|
const IS_WINDOWS = process.platform === 'win32';
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
const SUPPORTED_COMPILER_OPTIONS = [
|
|
14
|
+
'generate',
|
|
15
|
+
'dev',
|
|
16
|
+
'css',
|
|
17
|
+
'hydratable',
|
|
18
|
+
'customElement',
|
|
19
|
+
'immutable',
|
|
20
|
+
'enableSourcemap'
|
|
21
|
+
];
|
|
22
|
+
const TYPES_WITH_COMPILER_OPTIONS = ['style', 'script', 'all'];
|
|
23
|
+
|
|
24
|
+
export type SvelteQueryTypes = 'style' | 'script' | 'preprocessed' | 'all';
|
|
11
25
|
|
|
12
26
|
export interface RequestQuery {
|
|
13
27
|
// our own
|
|
14
28
|
svelte?: boolean;
|
|
15
29
|
type?: SvelteQueryTypes;
|
|
30
|
+
sourcemap?: boolean;
|
|
31
|
+
compilerOptions?: Pick<
|
|
32
|
+
CompileOptions,
|
|
33
|
+
'generate' | 'dev' | 'css' | 'hydratable' | 'customElement' | 'immutable' | 'enableSourcemap'
|
|
34
|
+
>;
|
|
16
35
|
// vite specific
|
|
17
36
|
url?: boolean;
|
|
18
37
|
raw?: boolean;
|
|
38
|
+
direct?: boolean;
|
|
19
39
|
}
|
|
20
40
|
|
|
21
41
|
export interface SvelteRequest {
|
|
@@ -26,6 +46,7 @@ export interface SvelteRequest {
|
|
|
26
46
|
query: RequestQuery;
|
|
27
47
|
timestamp: number;
|
|
28
48
|
ssr: boolean;
|
|
49
|
+
raw: boolean;
|
|
29
50
|
}
|
|
30
51
|
|
|
31
52
|
function splitId(id: string) {
|
|
@@ -44,10 +65,12 @@ function parseToSvelteRequest(
|
|
|
44
65
|
ssr: boolean
|
|
45
66
|
): SvelteRequest | undefined {
|
|
46
67
|
const query = parseRequestQuery(rawQuery);
|
|
47
|
-
|
|
68
|
+
const rawOrDirect = !!(query.raw || query.direct);
|
|
69
|
+
if (query.url || (!query.svelte && rawOrDirect)) {
|
|
48
70
|
// skip requests with special vite tags
|
|
49
71
|
return;
|
|
50
72
|
}
|
|
73
|
+
const raw = rawOrDirect;
|
|
51
74
|
const normalizedFilename = normalize(filename, root);
|
|
52
75
|
const cssId = createVirtualImportId(filename, root, 'style');
|
|
53
76
|
|
|
@@ -58,7 +81,8 @@ function parseToSvelteRequest(
|
|
|
58
81
|
cssId,
|
|
59
82
|
query,
|
|
60
83
|
timestamp,
|
|
61
|
-
ssr
|
|
84
|
+
ssr,
|
|
85
|
+
raw
|
|
62
86
|
};
|
|
63
87
|
}
|
|
64
88
|
|
|
@@ -86,6 +110,34 @@ function parseRequestQuery(rawQuery: string): RequestQuery {
|
|
|
86
110
|
query[key] = true;
|
|
87
111
|
}
|
|
88
112
|
}
|
|
113
|
+
const compilerOptions = query.compilerOptions;
|
|
114
|
+
if (compilerOptions) {
|
|
115
|
+
if (!((query.raw || query.direct) && TYPES_WITH_COMPILER_OPTIONS.includes(query.type))) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Invalid compilerOptions in query ${rawQuery}. CompilerOptions are only supported for raw or direct queries with type in "${TYPES_WITH_COMPILER_OPTIONS.join(
|
|
118
|
+
', '
|
|
119
|
+
)}" e.g. '?svelte&raw&type=script&compilerOptions={"generate":"ssr","dev":false}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const parsed = JSON.parse(compilerOptions);
|
|
124
|
+
const invalid = Object.keys(parsed).filter(
|
|
125
|
+
(key) => !SUPPORTED_COMPILER_OPTIONS.includes(key)
|
|
126
|
+
);
|
|
127
|
+
if (invalid.length) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`Invalid compilerOptions in query ${rawQuery}: ${invalid.join(
|
|
130
|
+
', '
|
|
131
|
+
)}. Supported: ${SUPPORTED_COMPILER_OPTIONS.join(', ')}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
query.compilerOptions = parsed;
|
|
135
|
+
} catch (e) {
|
|
136
|
+
log.error('failed to parse request query compilerOptions', e);
|
|
137
|
+
throw e;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
89
141
|
return query as RequestQuery;
|
|
90
142
|
}
|
|
91
143
|
|