@sveltejs/vite-plugin-svelte 1.0.0-next.30 → 1.0.0-next.34
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/README.md +1 -0
- package/dist/index.cjs +466 -344
- package/dist/index.cjs.map +1 -7
- package/dist/index.js +436 -323
- package/dist/index.js.map +1 -7
- package/package.json +12 -11
- package/src/index.ts +25 -15
- package/src/utils/dependencies.ts +6 -1
- package/src/utils/error.ts +92 -0
- package/src/utils/esbuild.ts +10 -2
- package/src/utils/log.ts +1 -1
- package/src/utils/optimizer.ts +43 -0
- package/src/utils/options.ts +98 -87
- package/src/utils/preprocess.ts +5 -8
- package/src/utils/resolve.ts +7 -1
- package/src/utils/watch.ts +7 -7
package/src/index.ts
CHANGED
|
@@ -9,14 +9,17 @@ import {
|
|
|
9
9
|
validateInlineOptions,
|
|
10
10
|
Options,
|
|
11
11
|
ResolvedOptions,
|
|
12
|
-
resolveOptions
|
|
12
|
+
resolveOptions,
|
|
13
|
+
patchResolvedViteConfig,
|
|
14
|
+
preResolveOptions
|
|
13
15
|
} from './utils/options';
|
|
14
16
|
import { VitePluginSvelteCache } from './utils/vite-plugin-svelte-cache';
|
|
15
17
|
|
|
16
18
|
import { ensureWatchedFile, setupWatchers } from './utils/watch';
|
|
17
19
|
import { resolveViaPackageJsonSvelte } from './utils/resolve';
|
|
18
|
-
import { addExtraPreprocessors } from './utils/preprocess';
|
|
19
20
|
import { PartialResolvedId } from 'rollup';
|
|
21
|
+
import { toRollupError } from './utils/error';
|
|
22
|
+
import { handleOptimizeDeps } from './utils/optimizer';
|
|
20
23
|
|
|
21
24
|
export function svelte(inlineOptions?: Partial<Options>): Plugin {
|
|
22
25
|
if (process.env.DEBUG != null) {
|
|
@@ -50,21 +53,27 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
|
|
|
50
53
|
} else if (config.logLevel) {
|
|
51
54
|
log.setLevel(config.logLevel);
|
|
52
55
|
}
|
|
53
|
-
options
|
|
56
|
+
// @ts-expect-error temporarily lend the options variable until fixed in configResolved
|
|
57
|
+
options = await preResolveOptions(inlineOptions, config, configEnv);
|
|
54
58
|
// extra vite config
|
|
55
59
|
const extraViteConfig = buildExtraViteConfig(options, config, configEnv);
|
|
56
60
|
log.debug('additional vite config', extraViteConfig);
|
|
57
|
-
return extraViteConfig
|
|
61
|
+
return extraViteConfig;
|
|
58
62
|
},
|
|
59
63
|
|
|
60
64
|
async configResolved(config) {
|
|
61
|
-
|
|
65
|
+
options = resolveOptions(options, config);
|
|
66
|
+
patchResolvedViteConfig(config, options);
|
|
62
67
|
requestParser = buildIdParser(options);
|
|
63
68
|
compileSvelte = createCompileSvelte(options);
|
|
64
69
|
viteConfig = config;
|
|
65
70
|
log.debug('resolved options', options);
|
|
66
71
|
},
|
|
67
72
|
|
|
73
|
+
async buildStart() {
|
|
74
|
+
await handleOptimizeDeps(options, viteConfig);
|
|
75
|
+
},
|
|
76
|
+
|
|
68
77
|
configureServer(server) {
|
|
69
78
|
// eslint-disable-next-line no-unused-vars
|
|
70
79
|
options.server = server;
|
|
@@ -94,11 +103,9 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
|
|
|
94
103
|
}
|
|
95
104
|
},
|
|
96
105
|
|
|
97
|
-
async resolveId(importee, importer, opts
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const ssr: boolean = _ssr === true || opts.ssr;
|
|
101
|
-
const svelteRequest = requestParser(importee, !!ssr);
|
|
106
|
+
async resolveId(importee, importer, opts) {
|
|
107
|
+
const ssr = !!opts?.ssr;
|
|
108
|
+
const svelteRequest = requestParser(importee, ssr);
|
|
102
109
|
if (svelteRequest?.query.svelte) {
|
|
103
110
|
if (svelteRequest.query.type === 'style') {
|
|
104
111
|
// return cssId with root prefix so postcss pipeline of vite finds the directory correctly
|
|
@@ -149,10 +156,8 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
|
|
|
149
156
|
},
|
|
150
157
|
|
|
151
158
|
async transform(code, id, opts) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const ssr: boolean = opts === true || opts?.ssr;
|
|
155
|
-
const svelteRequest = requestParser(id, !!ssr);
|
|
159
|
+
const ssr = !!opts?.ssr;
|
|
160
|
+
const svelteRequest = requestParser(id, ssr);
|
|
156
161
|
if (!svelteRequest) {
|
|
157
162
|
return;
|
|
158
163
|
}
|
|
@@ -169,7 +174,12 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin {
|
|
|
169
174
|
log.error('failed to transform tagged svelte request', svelteRequest);
|
|
170
175
|
throw new Error(`failed to transform tagged svelte request for id ${id}`);
|
|
171
176
|
}
|
|
172
|
-
|
|
177
|
+
let compileData;
|
|
178
|
+
try {
|
|
179
|
+
compileData = await compileSvelte(svelteRequest, code, options);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
throw toRollupError(e);
|
|
182
|
+
}
|
|
173
183
|
logCompilerWarnings(compileData.compiled.warnings, options);
|
|
174
184
|
cache.update(compileData);
|
|
175
185
|
if (compileData.dependencies?.length && options.server) {
|
|
@@ -184,7 +184,12 @@ export function needsOptimization(dep: string, localRequire: NodeRequire): boole
|
|
|
184
184
|
const pkg = depData.pkg;
|
|
185
185
|
// only optimize if is cjs, using the below as heuristic
|
|
186
186
|
// see https://github.com/sveltejs/vite-plugin-svelte/issues/162
|
|
187
|
-
|
|
187
|
+
const isCjs = pkg.main && !pkg.module && !pkg.exports;
|
|
188
|
+
if (!isCjs) return false;
|
|
189
|
+
// ensure entry is js so vite can prebundle it
|
|
190
|
+
// see https://github.com/sveltejs/vite-plugin-svelte/issues/233
|
|
191
|
+
const entryExt = path.extname(pkg.main);
|
|
192
|
+
return !entryExt || entryExt === '.js' || entryExt === '.cjs';
|
|
188
193
|
}
|
|
189
194
|
|
|
190
195
|
interface DependencyData {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { RollupError } from 'rollup';
|
|
2
|
+
import { Warning } from './options';
|
|
3
|
+
import { buildExtendedLogMessage } from './log';
|
|
4
|
+
import { PartialMessage } from 'esbuild';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* convert an error thrown by svelte.compile to a RollupError so that vite displays it in a user friendly way
|
|
8
|
+
* @param error a svelte compiler error, which is a mix of Warning and an error
|
|
9
|
+
* @returns {RollupError} the converted error
|
|
10
|
+
*/
|
|
11
|
+
export function toRollupError(error: Warning & Error): RollupError {
|
|
12
|
+
const { filename, frame, start, code, name } = error;
|
|
13
|
+
const rollupError: RollupError = {
|
|
14
|
+
name, // needed otherwise sveltekit coalesce_to_error turns it into a string
|
|
15
|
+
id: filename,
|
|
16
|
+
message: buildExtendedLogMessage(error), // include filename:line:column so that it's clickable
|
|
17
|
+
frame: formatFrameForVite(frame),
|
|
18
|
+
code,
|
|
19
|
+
stack: ''
|
|
20
|
+
};
|
|
21
|
+
if (start) {
|
|
22
|
+
rollupError.loc = {
|
|
23
|
+
line: start.line,
|
|
24
|
+
column: start.column,
|
|
25
|
+
file: filename
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return rollupError;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* convert an error thrown by svelte.compile to an esbuild PartialMessage
|
|
33
|
+
* @param error a svelte compiler error, which is a mix of Warning and an error
|
|
34
|
+
* @returns {PartialMessage} the converted error
|
|
35
|
+
*/
|
|
36
|
+
export function toESBuildError(error: Warning & Error): PartialMessage {
|
|
37
|
+
const { filename, frame, start } = error;
|
|
38
|
+
const partialMessage: PartialMessage = {
|
|
39
|
+
text: buildExtendedLogMessage(error)
|
|
40
|
+
};
|
|
41
|
+
if (start) {
|
|
42
|
+
partialMessage.location = {
|
|
43
|
+
line: start.line,
|
|
44
|
+
column: start.column,
|
|
45
|
+
file: filename,
|
|
46
|
+
lineText: lineFromFrame(start.line, frame) // needed to get a meaningful error message on cli
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return partialMessage;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* extract line with number from codeframe
|
|
54
|
+
*/
|
|
55
|
+
function lineFromFrame(lineNo: number, frame?: string): string {
|
|
56
|
+
if (!frame) {
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
const lines = frame.split('\n');
|
|
60
|
+
const errorLine = lines.find((line) => line.trimStart().startsWith(`${lineNo}: `));
|
|
61
|
+
return errorLine ? errorLine.substring(errorLine.indexOf(': ') + 3) : '';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* vite error overlay expects a specific format to show frames
|
|
66
|
+
* this reformats svelte frame (colon separated, less whitespace)
|
|
67
|
+
* to one that vite displays on overlay ( pipe separated, more whitespace)
|
|
68
|
+
* e.g.
|
|
69
|
+
* ```
|
|
70
|
+
* 1: foo
|
|
71
|
+
* 2: bar;
|
|
72
|
+
* ^
|
|
73
|
+
* 3: baz
|
|
74
|
+
* ```
|
|
75
|
+
* to
|
|
76
|
+
* ```
|
|
77
|
+
* 1 | foo
|
|
78
|
+
* 2 | bar;
|
|
79
|
+
* ^
|
|
80
|
+
* 3 | baz
|
|
81
|
+
* ```
|
|
82
|
+
* @see https://github.com/vitejs/vite/blob/96591bf9989529de839ba89958755eafe4c445ae/packages/vite/src/client/overlay.ts#L116
|
|
83
|
+
*/
|
|
84
|
+
function formatFrameForVite(frame?: string): string {
|
|
85
|
+
if (!frame) {
|
|
86
|
+
return '';
|
|
87
|
+
}
|
|
88
|
+
return frame
|
|
89
|
+
.split('\n')
|
|
90
|
+
.map((line) => (line.match(/^\s+\^/) ? ' ' + line : ' ' + line.replace(':', ' | ')))
|
|
91
|
+
.join('\n');
|
|
92
|
+
}
|
package/src/utils/esbuild.ts
CHANGED
|
@@ -4,11 +4,14 @@ import { DepOptimizationOptions } from 'vite';
|
|
|
4
4
|
import { Compiled } from './compile';
|
|
5
5
|
import { log } from './log';
|
|
6
6
|
import { CompileOptions, ResolvedOptions } from './options';
|
|
7
|
+
import { toESBuildError } from './error';
|
|
7
8
|
|
|
8
9
|
type EsbuildOptions = NonNullable<DepOptimizationOptions['esbuildOptions']>;
|
|
9
10
|
type EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];
|
|
10
11
|
type EsbuildPluginBuild = Parameters<EsbuildPlugin['setup']>[0];
|
|
11
12
|
|
|
13
|
+
export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade';
|
|
14
|
+
|
|
12
15
|
export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
|
|
13
16
|
return {
|
|
14
17
|
name: 'vite-plugin-svelte:optimize-svelte',
|
|
@@ -20,8 +23,12 @@ export function esbuildSveltePlugin(options: ResolvedOptions): EsbuildPlugin {
|
|
|
20
23
|
|
|
21
24
|
build.onLoad({ filter: svelteFilter }, async ({ path: filename }) => {
|
|
22
25
|
const code = await fs.readFile(filename, 'utf8');
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
try {
|
|
27
|
+
const contents = await compileSvelte(options, { filename, code });
|
|
28
|
+
return { contents };
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return { errors: [toESBuildError(e)] };
|
|
31
|
+
}
|
|
25
32
|
});
|
|
26
33
|
}
|
|
27
34
|
};
|
|
@@ -59,6 +66,7 @@ async function compileSvelte(
|
|
|
59
66
|
...options.compilerOptions,
|
|
60
67
|
css: true,
|
|
61
68
|
filename,
|
|
69
|
+
format: 'esm',
|
|
62
70
|
generate: 'dom'
|
|
63
71
|
};
|
|
64
72
|
|
package/src/utils/log.ts
CHANGED
|
@@ -155,7 +155,7 @@ function warnBuild(w: Warning) {
|
|
|
155
155
|
log.warn.enabled && log.warn(buildExtendedLogMessage(w), w.frame);
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
function buildExtendedLogMessage(w: Warning) {
|
|
158
|
+
export function buildExtendedLogMessage(w: Warning) {
|
|
159
159
|
const parts = [];
|
|
160
160
|
if (w.filename) {
|
|
161
161
|
parts.push(w.filename);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { optimizeDeps, ResolvedConfig } from 'vite';
|
|
4
|
+
import { ResolvedOptions } from './options';
|
|
5
|
+
|
|
6
|
+
// List of options that changes the prebundling result
|
|
7
|
+
const PREBUNDLE_SENSITIVE_OPTIONS: (keyof ResolvedOptions)[] = [
|
|
8
|
+
'compilerOptions',
|
|
9
|
+
'configFile',
|
|
10
|
+
'experimental',
|
|
11
|
+
'extensions',
|
|
12
|
+
'ignorePluginPreprocessors',
|
|
13
|
+
'preprocess'
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export async function handleOptimizeDeps(options: ResolvedOptions, viteConfig: ResolvedConfig) {
|
|
17
|
+
if (!options.experimental.prebundleSvelteLibraries || !viteConfig.cacheDir) return;
|
|
18
|
+
|
|
19
|
+
const viteMetadataPath = path.resolve(viteConfig.cacheDir, '_metadata.json');
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(viteMetadataPath)) return;
|
|
22
|
+
|
|
23
|
+
const svelteMetadataPath = path.resolve(viteConfig.cacheDir, '_svelte_metadata.json');
|
|
24
|
+
const currentSvelteMetadata = JSON.stringify(generateSvelteMetadata(options), (_, value) => {
|
|
25
|
+
return typeof value === 'function' ? value.toString() : value;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (fs.existsSync(svelteMetadataPath)) {
|
|
29
|
+
const existingSvelteMetadata = fs.readFileSync(svelteMetadataPath, 'utf8');
|
|
30
|
+
if (existingSvelteMetadata === currentSvelteMetadata) return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await optimizeDeps(viteConfig, true);
|
|
34
|
+
fs.writeFileSync(svelteMetadataPath, currentSvelteMetadata);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function generateSvelteMetadata(options: ResolvedOptions) {
|
|
38
|
+
const metadata: Record<string, any> = {};
|
|
39
|
+
for (const key of PREBUNDLE_SENSITIVE_OPTIONS) {
|
|
40
|
+
metadata[key] = options[key];
|
|
41
|
+
}
|
|
42
|
+
return metadata;
|
|
43
|
+
}
|
package/src/utils/options.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/* eslint-disable no-unused-vars */
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ConfigEnv,
|
|
4
|
+
DepOptimizationOptions,
|
|
5
|
+
ResolvedConfig,
|
|
6
|
+
UserConfig,
|
|
7
|
+
ViteDevServer,
|
|
8
|
+
normalizePath
|
|
9
|
+
} from 'vite';
|
|
3
10
|
import { log } from './log';
|
|
4
11
|
import { loadSvelteConfig } from './load-svelte-config';
|
|
5
12
|
import { SVELTE_HMR_IMPORTS, SVELTE_IMPORTS, SVELTE_RESOLVE_MAIN_FIELDS } from './constants';
|
|
@@ -15,7 +22,8 @@ import {
|
|
|
15
22
|
import path from 'path';
|
|
16
23
|
import { findRootSvelteDependencies, needsOptimization, SvelteDependency } from './dependencies';
|
|
17
24
|
import { createRequire } from 'module';
|
|
18
|
-
import { esbuildSveltePlugin } from './esbuild';
|
|
25
|
+
import { esbuildSveltePlugin, facadeEsbuildSveltePluginName } from './esbuild';
|
|
26
|
+
import { addExtraPreprocessors } from './preprocess';
|
|
19
27
|
|
|
20
28
|
const knownOptions = new Set([
|
|
21
29
|
'configFile',
|
|
@@ -32,33 +40,85 @@ const knownOptions = new Set([
|
|
|
32
40
|
'experimental'
|
|
33
41
|
]);
|
|
34
42
|
|
|
35
|
-
function
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
export function validateInlineOptions(inlineOptions?: Partial<Options>) {
|
|
44
|
+
const invalidKeys = Object.keys(inlineOptions || {}).filter((key) => !knownOptions.has(key));
|
|
45
|
+
if (invalidKeys.length) {
|
|
46
|
+
log.warn(`invalid plugin options "${invalidKeys.join(', ')}" in config`, inlineOptions);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// used in config phase, merges the default options, svelte config, and inline options
|
|
51
|
+
export async function preResolveOptions(
|
|
52
|
+
inlineOptions: Partial<Options> = {},
|
|
53
|
+
viteUserConfig: UserConfig,
|
|
54
|
+
viteEnv: ConfigEnv
|
|
55
|
+
): Promise<PreResolvedOptions> {
|
|
56
|
+
const viteConfigWithResolvedRoot: UserConfig = {
|
|
57
|
+
...viteUserConfig,
|
|
58
|
+
root: resolveViteRoot(viteUserConfig)
|
|
59
|
+
};
|
|
43
60
|
const defaultOptions: Partial<Options> = {
|
|
44
61
|
extensions: ['.svelte'],
|
|
45
|
-
|
|
46
|
-
emitCss,
|
|
62
|
+
emitCss: true,
|
|
47
63
|
compilerOptions: {
|
|
48
|
-
format: 'esm'
|
|
49
|
-
css: !emitCss,
|
|
50
|
-
dev: !isProduction
|
|
64
|
+
format: 'esm'
|
|
51
65
|
}
|
|
52
66
|
};
|
|
53
|
-
|
|
54
|
-
|
|
67
|
+
const svelteConfig = await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions);
|
|
68
|
+
const merged = {
|
|
69
|
+
...defaultOptions,
|
|
70
|
+
...svelteConfig,
|
|
71
|
+
...inlineOptions,
|
|
72
|
+
compilerOptions: {
|
|
73
|
+
...defaultOptions?.compilerOptions,
|
|
74
|
+
...svelteConfig?.compilerOptions,
|
|
75
|
+
...inlineOptions?.compilerOptions
|
|
76
|
+
},
|
|
77
|
+
experimental: {
|
|
78
|
+
...defaultOptions?.experimental,
|
|
79
|
+
...svelteConfig?.experimental,
|
|
80
|
+
...inlineOptions?.experimental
|
|
81
|
+
},
|
|
82
|
+
// extras
|
|
83
|
+
root: viteConfigWithResolvedRoot.root!,
|
|
84
|
+
isBuild: viteEnv.command === 'build',
|
|
85
|
+
isServe: viteEnv.command === 'serve'
|
|
86
|
+
};
|
|
87
|
+
// configFile of svelteConfig contains the absolute path it was loaded from,
|
|
88
|
+
// prefer it over the possibly relative inline path
|
|
89
|
+
if (svelteConfig?.configFile) {
|
|
90
|
+
merged.configFile = svelteConfig.configFile;
|
|
91
|
+
}
|
|
92
|
+
return merged;
|
|
55
93
|
}
|
|
56
94
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
95
|
+
// used in configResolved phase, merges a contextual default config, pre-resolved options, and some preprocessors.
|
|
96
|
+
// also validates the final config.
|
|
97
|
+
export function resolveOptions(
|
|
98
|
+
preResolveOptions: PreResolvedOptions,
|
|
99
|
+
viteConfig: ResolvedConfig
|
|
100
|
+
): ResolvedOptions {
|
|
101
|
+
const defaultOptions: Partial<Options> = {
|
|
102
|
+
hot: viteConfig.isProduction ? false : { injectCss: !preResolveOptions.emitCss },
|
|
103
|
+
compilerOptions: {
|
|
104
|
+
css: !preResolveOptions.emitCss,
|
|
105
|
+
dev: !viteConfig.isProduction
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const merged: ResolvedOptions = {
|
|
109
|
+
...defaultOptions,
|
|
110
|
+
...preResolveOptions,
|
|
111
|
+
compilerOptions: {
|
|
112
|
+
...defaultOptions.compilerOptions,
|
|
113
|
+
...preResolveOptions.compilerOptions
|
|
114
|
+
},
|
|
115
|
+
root: viteConfig.root,
|
|
116
|
+
isProduction: viteConfig.isProduction
|
|
117
|
+
};
|
|
118
|
+
addExtraPreprocessors(merged, viteConfig);
|
|
119
|
+
enforceOptionsForHmr(merged);
|
|
120
|
+
enforceOptionsForProduction(merged);
|
|
121
|
+
return merged;
|
|
62
122
|
}
|
|
63
123
|
|
|
64
124
|
function enforceOptionsForHmr(options: ResolvedOptions) {
|
|
@@ -114,66 +174,6 @@ function enforceOptionsForProduction(options: ResolvedOptions) {
|
|
|
114
174
|
}
|
|
115
175
|
}
|
|
116
176
|
|
|
117
|
-
function mergeOptions(
|
|
118
|
-
defaultOptions: Partial<Options>,
|
|
119
|
-
svelteConfig: Partial<Options>,
|
|
120
|
-
inlineOptions: Partial<Options>,
|
|
121
|
-
viteConfig: UserConfig,
|
|
122
|
-
viteEnv: ConfigEnv
|
|
123
|
-
): ResolvedOptions {
|
|
124
|
-
const merged = {
|
|
125
|
-
...defaultOptions,
|
|
126
|
-
...svelteConfig,
|
|
127
|
-
...inlineOptions,
|
|
128
|
-
compilerOptions: {
|
|
129
|
-
...defaultOptions.compilerOptions,
|
|
130
|
-
...(svelteConfig?.compilerOptions || {}),
|
|
131
|
-
...(inlineOptions?.compilerOptions || {})
|
|
132
|
-
},
|
|
133
|
-
experimental: {
|
|
134
|
-
...(svelteConfig?.experimental || {}),
|
|
135
|
-
...(inlineOptions?.experimental || {})
|
|
136
|
-
},
|
|
137
|
-
root: viteConfig.root!,
|
|
138
|
-
isProduction: viteEnv.mode === 'production',
|
|
139
|
-
isBuild: viteEnv.command === 'build',
|
|
140
|
-
isServe: viteEnv.command === 'serve'
|
|
141
|
-
};
|
|
142
|
-
// configFile of svelteConfig contains the absolute path it was loaded from,
|
|
143
|
-
// prefer it over the possibly relative inline path
|
|
144
|
-
if (svelteConfig?.configFile) {
|
|
145
|
-
merged.configFile = svelteConfig.configFile;
|
|
146
|
-
}
|
|
147
|
-
return merged;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export async function resolveOptions(
|
|
151
|
-
inlineOptions: Partial<Options> = {},
|
|
152
|
-
viteConfig: UserConfig,
|
|
153
|
-
viteEnv: ConfigEnv
|
|
154
|
-
): Promise<ResolvedOptions> {
|
|
155
|
-
const viteConfigWithResolvedRoot = {
|
|
156
|
-
...viteConfig,
|
|
157
|
-
root: resolveViteRoot(viteConfig)
|
|
158
|
-
};
|
|
159
|
-
const svelteConfig = (await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions)) || {};
|
|
160
|
-
const defaultOptions = buildDefaultOptions(
|
|
161
|
-
viteEnv.mode === 'production',
|
|
162
|
-
inlineOptions.emitCss ?? svelteConfig.emitCss
|
|
163
|
-
);
|
|
164
|
-
const resolvedOptions = mergeOptions(
|
|
165
|
-
defaultOptions,
|
|
166
|
-
svelteConfig,
|
|
167
|
-
inlineOptions,
|
|
168
|
-
viteConfigWithResolvedRoot,
|
|
169
|
-
viteEnv
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
enforceOptionsForProduction(resolvedOptions);
|
|
173
|
-
enforceOptionsForHmr(resolvedOptions);
|
|
174
|
-
return resolvedOptions;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
177
|
// vite passes unresolved `root`option to config hook but we need the resolved value, so do it here
|
|
178
178
|
// https://github.com/sveltejs/vite-plugin-svelte/issues/113
|
|
179
179
|
// https://github.com/vitejs/vite/blob/43c957de8a99bb326afd732c962f42127b0a4d1e/packages/vite/src/node/config.ts#L293
|
|
@@ -182,7 +182,7 @@ function resolveViteRoot(viteConfig: UserConfig): string | undefined {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
export function buildExtraViteConfig(
|
|
185
|
-
options:
|
|
185
|
+
options: PreResolvedOptions,
|
|
186
186
|
config: UserConfig,
|
|
187
187
|
configEnv: ConfigEnv
|
|
188
188
|
): Partial<UserConfig> {
|
|
@@ -215,7 +215,7 @@ export function buildExtraViteConfig(
|
|
|
215
215
|
|
|
216
216
|
function buildOptimizeDepsForSvelte(
|
|
217
217
|
svelteDeps: SvelteDependency[],
|
|
218
|
-
options:
|
|
218
|
+
options: PreResolvedOptions,
|
|
219
219
|
optimizeDeps?: DepOptimizationOptions
|
|
220
220
|
): DepOptimizationOptions {
|
|
221
221
|
// include svelte imports for optimization unless explicitly excluded
|
|
@@ -246,7 +246,7 @@ function buildOptimizeDepsForSvelte(
|
|
|
246
246
|
include,
|
|
247
247
|
exclude,
|
|
248
248
|
esbuildOptions: {
|
|
249
|
-
plugins: [
|
|
249
|
+
plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }]
|
|
250
250
|
}
|
|
251
251
|
};
|
|
252
252
|
}
|
|
@@ -317,6 +317,14 @@ function buildSSROptionsForSvelte(
|
|
|
317
317
|
};
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
+
export function patchResolvedViteConfig(viteConfig: ResolvedConfig, options: ResolvedOptions) {
|
|
321
|
+
const facadeEsbuildSveltePlugin = viteConfig.optimizeDeps.esbuildOptions?.plugins?.find(
|
|
322
|
+
(plugin) => plugin.name === facadeEsbuildSveltePluginName
|
|
323
|
+
);
|
|
324
|
+
if (facadeEsbuildSveltePlugin) {
|
|
325
|
+
Object.assign(facadeEsbuildSveltePlugin, esbuildSveltePlugin(options));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
320
328
|
export interface Options {
|
|
321
329
|
/**
|
|
322
330
|
* Path to a svelte config file, either absolute or relative to Vite root
|
|
@@ -475,15 +483,18 @@ export interface ExperimentalOptions {
|
|
|
475
483
|
}) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
|
|
476
484
|
}
|
|
477
485
|
|
|
478
|
-
export interface
|
|
486
|
+
export interface PreResolvedOptions extends Options {
|
|
479
487
|
// these options are non-nullable after resolve
|
|
480
488
|
compilerOptions: CompileOptions;
|
|
481
489
|
experimental: ExperimentalOptions;
|
|
482
490
|
// extra options
|
|
483
491
|
root: string;
|
|
484
|
-
isProduction: boolean;
|
|
485
492
|
isBuild: boolean;
|
|
486
493
|
isServe: boolean;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export interface ResolvedOptions extends PreResolvedOptions {
|
|
497
|
+
isProduction: boolean;
|
|
487
498
|
server?: ViteDevServer;
|
|
488
499
|
}
|
|
489
500
|
|
package/src/utils/preprocess.ts
CHANGED
|
@@ -17,7 +17,6 @@ const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'p
|
|
|
17
17
|
const supportedScriptLangs = ['ts'];
|
|
18
18
|
|
|
19
19
|
function createViteScriptPreprocessor(): Preprocessor {
|
|
20
|
-
// @ts-expect-error - allow return void
|
|
21
20
|
return async ({ attributes, content, filename = '' }) => {
|
|
22
21
|
const lang = attributes.lang as string;
|
|
23
22
|
if (!supportedScriptLangs.includes(lang)) return;
|
|
@@ -26,7 +25,8 @@ function createViteScriptPreprocessor(): Preprocessor {
|
|
|
26
25
|
tsconfigRaw: {
|
|
27
26
|
compilerOptions: {
|
|
28
27
|
// svelte typescript needs this flag to work with type imports
|
|
29
|
-
importsNotUsedAsValues: 'preserve'
|
|
28
|
+
importsNotUsedAsValues: 'preserve',
|
|
29
|
+
preserveValueImports: true
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
});
|
|
@@ -47,7 +47,6 @@ function createViteStylePreprocessor(config: ResolvedConfig): Preprocessor {
|
|
|
47
47
|
throw new Error(`plugin ${pluginName} has no transform`);
|
|
48
48
|
}
|
|
49
49
|
const pluginTransform = plugin.transform!.bind(null as unknown as TransformPluginContext);
|
|
50
|
-
// @ts-expect-error - allow return void
|
|
51
50
|
return async ({ attributes, content, filename = '' }) => {
|
|
52
51
|
const lang = attributes.lang as string;
|
|
53
52
|
if (!supportedStyleLangs.includes(lang)) return;
|
|
@@ -56,20 +55,18 @@ function createViteStylePreprocessor(config: ResolvedConfig): Preprocessor {
|
|
|
56
55
|
content,
|
|
57
56
|
moduleId
|
|
58
57
|
)) as TransformResult;
|
|
59
|
-
// vite returns empty mappings that would kill svelte compiler before 3.43.0
|
|
60
|
-
const hasMap = transformResult.map && transformResult.map.mappings !== '';
|
|
61
58
|
// patch sourcemap source to point back to original filename
|
|
62
|
-
if (
|
|
59
|
+
if (transformResult.map?.sources?.[0] === moduleId) {
|
|
63
60
|
transformResult.map.sources[0] = filename;
|
|
64
61
|
}
|
|
65
62
|
return {
|
|
66
63
|
code: transformResult.code,
|
|
67
|
-
map:
|
|
64
|
+
map: transformResult.map ?? undefined
|
|
68
65
|
};
|
|
69
66
|
};
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
|
|
69
|
+
function createVitePreprocessorGroup(config: ResolvedConfig): PreprocessorGroup {
|
|
73
70
|
return {
|
|
74
71
|
markup({ content, filename }) {
|
|
75
72
|
return preprocess(
|
package/src/utils/resolve.ts
CHANGED
|
@@ -14,7 +14,13 @@ export function resolveViaPackageJsonSvelte(importee: string, importer?: string)
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function isBareImport(importee: string): boolean {
|
|
17
|
-
if (
|
|
17
|
+
if (
|
|
18
|
+
!importee ||
|
|
19
|
+
importee[0] === '.' ||
|
|
20
|
+
importee[0] === '\0' ||
|
|
21
|
+
importee.includes(':') ||
|
|
22
|
+
path.isAbsolute(importee)
|
|
23
|
+
) {
|
|
18
24
|
return false;
|
|
19
25
|
}
|
|
20
26
|
const parts = importee.split('/');
|
package/src/utils/watch.ts
CHANGED
|
@@ -17,7 +17,7 @@ export function setupWatchers(
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
const { watcher, ws } = server;
|
|
20
|
-
const {
|
|
20
|
+
const { root, server: serverConfig } = server.config;
|
|
21
21
|
|
|
22
22
|
const emitChangeEventOnDependants = (filename: string) => {
|
|
23
23
|
const dependants = cache.getDependants(filename);
|
|
@@ -42,12 +42,9 @@ export function setupWatchers(
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
const triggerViteRestart = (filename: string) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
log.info(`svelte config changed: restarting vite server. - file: ${filename}`);
|
|
49
|
-
watcher.emit('change', viteConfigFile);
|
|
50
|
-
} else {
|
|
45
|
+
if (serverConfig.middlewareMode) {
|
|
46
|
+
// in middlewareMode we can't restart the server automatically
|
|
47
|
+
// show the user an overlay instead
|
|
51
48
|
const message =
|
|
52
49
|
'Svelte config change detected, restart your dev process to apply the changes.';
|
|
53
50
|
log.info(message, filename);
|
|
@@ -55,6 +52,9 @@ export function setupWatchers(
|
|
|
55
52
|
type: 'error',
|
|
56
53
|
err: { message, stack: '', plugin: 'vite-plugin-svelte', id: filename }
|
|
57
54
|
});
|
|
55
|
+
} else {
|
|
56
|
+
log.info(`svelte config changed: restarting vite server. - file: ${filename}`);
|
|
57
|
+
server.restart();
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
60
|
|