@sveltejs/vite-plugin-svelte 3.0.0-next.0 → 3.0.0-next.1
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/package.json +8 -8
- package/src/index.d.ts +15 -13
- package/src/preprocess.js +6 -7
- package/src/utils/compile.js +33 -4
- package/src/utils/error.js +76 -0
- package/src/utils/esbuild.js +6 -2
- package/src/utils/load-svelte-config.js +2 -1
- package/src/utils/options.js +3 -2
- package/src/utils/preprocess.js +51 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/vite-plugin-svelte",
|
|
3
|
-
"version": "3.0.0-next.
|
|
3
|
+
"version": "3.0.0-next.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "dominikg",
|
|
6
6
|
"files": [
|
|
@@ -34,23 +34,23 @@
|
|
|
34
34
|
},
|
|
35
35
|
"homepage": "https://github.com/sveltejs/vite-plugin-svelte#readme",
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"@sveltejs/vite-plugin-svelte-inspector": "^2.0.0-next.0 || ^2.0.0",
|
|
37
38
|
"debug": "^4.3.4",
|
|
38
39
|
"deepmerge": "^4.3.1",
|
|
39
40
|
"kleur": "^4.1.5",
|
|
40
|
-
"magic-string": "^0.30.
|
|
41
|
+
"magic-string": "^0.30.5",
|
|
41
42
|
"svelte-hmr": "^0.15.3",
|
|
42
|
-
"vitefu": "^0.2.
|
|
43
|
-
"@sveltejs/vite-plugin-svelte-inspector": "^2.0.0-next.0"
|
|
43
|
+
"vitefu": "^0.2.5"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"svelte": "^4.0.0",
|
|
47
47
|
"vite": "^5.0.0-beta.1 || ^5.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@types/debug": "^4.1.
|
|
51
|
-
"esbuild": "^0.19.
|
|
52
|
-
"svelte": "^4.2.
|
|
53
|
-
"vite": "^5.0.0-beta.
|
|
50
|
+
"@types/debug": "^4.1.9",
|
|
51
|
+
"esbuild": "^0.19.4",
|
|
52
|
+
"svelte": "^4.2.1",
|
|
53
|
+
"vite": "^5.0.0-beta.7"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"check:publint": "publint --strict",
|
package/src/index.d.ts
CHANGED
|
@@ -121,20 +121,7 @@ interface SvelteOptions {
|
|
|
121
121
|
* @see https://svelte.dev/docs#svelte_compile
|
|
122
122
|
*/
|
|
123
123
|
compilerOptions?: Omit<CompileOptions, 'filename' | 'format' | 'generate'>;
|
|
124
|
-
/**
|
|
125
|
-
* Handles warning emitted from the Svelte compiler
|
|
126
|
-
*/
|
|
127
|
-
onwarn?: (warning: Warning, defaultHandler?: (warning: Warning) => void) => void;
|
|
128
|
-
/**
|
|
129
|
-
* Options for vite-plugin-svelte
|
|
130
|
-
*/
|
|
131
|
-
vitePlugin?: PluginOptions;
|
|
132
|
-
}
|
|
133
124
|
|
|
134
|
-
/**
|
|
135
|
-
* These options are considered experimental and breaking changes to them can occur in any release
|
|
136
|
-
*/
|
|
137
|
-
interface ExperimentalOptions {
|
|
138
125
|
/**
|
|
139
126
|
* A function to update `compilerOptions` before compilation
|
|
140
127
|
*
|
|
@@ -159,6 +146,21 @@ interface ExperimentalOptions {
|
|
|
159
146
|
code: string;
|
|
160
147
|
compileOptions: Partial<CompileOptions>;
|
|
161
148
|
}) => Promise<Partial<CompileOptions> | void> | Partial<CompileOptions> | void;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Handles warning emitted from the Svelte compiler
|
|
152
|
+
*/
|
|
153
|
+
onwarn?: (warning: Warning, defaultHandler?: (warning: Warning) => void) => void;
|
|
154
|
+
/**
|
|
155
|
+
* Options for vite-plugin-svelte
|
|
156
|
+
*/
|
|
157
|
+
vitePlugin?: PluginOptions;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* These options are considered experimental and breaking changes to them can occur in any release
|
|
162
|
+
*/
|
|
163
|
+
interface ExperimentalOptions {
|
|
162
164
|
/**
|
|
163
165
|
* send a websocket message with svelte compiler warnings during dev
|
|
164
166
|
*
|
package/src/preprocess.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { preprocessCSS, resolveConfig, transformWithEsbuild } from 'vite';
|
|
1
|
+
import { isCSSRequest, preprocessCSS, resolveConfig, transformWithEsbuild } from 'vite';
|
|
2
2
|
import { mapToRelative, removeLangSuffix } from './utils/sourcemaps.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @typedef {(code: string, filename: string) => Promise<{ code: string; map?: any; deps?: Set<string> }>} CssTransform
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'postcss', 'sss'];
|
|
9
8
|
const supportedScriptLangs = ['ts'];
|
|
10
9
|
|
|
11
|
-
export const lang_sep = '.vite-preprocess
|
|
10
|
+
export const lang_sep = '.vite-preprocess';
|
|
12
11
|
|
|
13
12
|
/** @type {import('./index.d.ts').vitePreprocess} */
|
|
14
13
|
export function vitePreprocess(opts) {
|
|
15
14
|
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup} */
|
|
16
|
-
const preprocessor = {};
|
|
15
|
+
const preprocessor = { name: 'vite-preprocess' };
|
|
17
16
|
if (opts?.script !== false) {
|
|
18
17
|
preprocessor.script = viteScript().script;
|
|
19
18
|
}
|
|
@@ -63,8 +62,8 @@ function viteStyle(config = {}) {
|
|
|
63
62
|
let transform;
|
|
64
63
|
/** @type {import('svelte/types/compiler/preprocess').Preprocessor} */
|
|
65
64
|
const style = async ({ attributes, content, filename = '' }) => {
|
|
66
|
-
const
|
|
67
|
-
if (!
|
|
65
|
+
const ext = attributes.lang ? `.${attributes.lang}` : '.css';
|
|
66
|
+
if (attributes.lang && !isCSSRequest(ext)) return;
|
|
68
67
|
if (!transform) {
|
|
69
68
|
/** @type {import('vite').ResolvedConfig} */
|
|
70
69
|
let resolvedConfig;
|
|
@@ -82,7 +81,7 @@ function viteStyle(config = {}) {
|
|
|
82
81
|
}
|
|
83
82
|
transform = getCssTransformFn(resolvedConfig);
|
|
84
83
|
}
|
|
85
|
-
const suffix = `${lang_sep}${
|
|
84
|
+
const suffix = `${lang_sep}${ext}`;
|
|
86
85
|
const moduleId = `${filename}${suffix}`;
|
|
87
86
|
const { code, map, deps } = await transform(content, moduleId);
|
|
88
87
|
removeLangSuffix(map, suffix);
|
package/src/utils/compile.js
CHANGED
|
@@ -4,8 +4,12 @@ import { createMakeHot } from 'svelte-hmr';
|
|
|
4
4
|
import { safeBase64Hash } from './hash.js';
|
|
5
5
|
import { log } from './log.js';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
checkPreprocessDependencies,
|
|
9
|
+
createInjectScopeEverythingRulePreprocessorGroup
|
|
10
|
+
} from './preprocess.js';
|
|
8
11
|
import { mapToRelative } from './sourcemaps.js';
|
|
12
|
+
import { enhanceCompileError } from './error.js';
|
|
9
13
|
|
|
10
14
|
const scriptLangRE = /<script [^>]*lang=["']?([^"' >]+)["']?[^>]*>/;
|
|
11
15
|
|
|
@@ -21,7 +25,10 @@ export const _createCompileSvelte = (makeHot) => {
|
|
|
21
25
|
return async function compileSvelte(svelteRequest, code, options) {
|
|
22
26
|
const { filename, normalizedFilename, cssId, ssr, raw } = svelteRequest;
|
|
23
27
|
const { emitCss = true } = options;
|
|
28
|
+
/** @type {string[]} */
|
|
24
29
|
const dependencies = [];
|
|
30
|
+
/** @type {import('svelte/types/compiler/interfaces').Warning[]} */
|
|
31
|
+
const warnings = [];
|
|
25
32
|
|
|
26
33
|
if (options.stats) {
|
|
27
34
|
if (options.isBuild) {
|
|
@@ -86,7 +93,16 @@ export const _createCompileSvelte = (makeHot) => {
|
|
|
86
93
|
throw e;
|
|
87
94
|
}
|
|
88
95
|
|
|
89
|
-
if (preprocessed.dependencies)
|
|
96
|
+
if (preprocessed.dependencies?.length) {
|
|
97
|
+
const checked = checkPreprocessDependencies(filename, preprocessed.dependencies);
|
|
98
|
+
if (checked.warnings.length) {
|
|
99
|
+
warnings.push(...checked.warnings);
|
|
100
|
+
}
|
|
101
|
+
if (checked.dependencies.length) {
|
|
102
|
+
dependencies.push(...checked.dependencies);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
90
106
|
if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;
|
|
91
107
|
}
|
|
92
108
|
if (typeof preprocessed?.map === 'object') {
|
|
@@ -99,7 +115,7 @@ export const _createCompileSvelte = (makeHot) => {
|
|
|
99
115
|
};
|
|
100
116
|
}
|
|
101
117
|
const finalCode = preprocessed ? preprocessed.code : code;
|
|
102
|
-
const dynamicCompileOptions = await options
|
|
118
|
+
const dynamicCompileOptions = await options?.dynamicCompileOptions?.({
|
|
103
119
|
filename,
|
|
104
120
|
code: finalCode,
|
|
105
121
|
compileOptions
|
|
@@ -119,13 +135,26 @@ export const _createCompileSvelte = (makeHot) => {
|
|
|
119
135
|
: compileOptions;
|
|
120
136
|
|
|
121
137
|
const endStat = stats?.start(filename);
|
|
122
|
-
|
|
138
|
+
/** @type {import('svelte/types/compiler/interfaces').CompileResult} */
|
|
139
|
+
let compiled;
|
|
140
|
+
try {
|
|
141
|
+
compiled = compile(finalCode, finalCompileOptions);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
enhanceCompileError(e, code, preprocessors);
|
|
144
|
+
throw e;
|
|
145
|
+
}
|
|
123
146
|
|
|
124
147
|
if (endStat) {
|
|
125
148
|
endStat();
|
|
126
149
|
}
|
|
127
150
|
mapToRelative(compiled.js?.map, filename);
|
|
128
151
|
mapToRelative(compiled.css?.map, filename);
|
|
152
|
+
if (warnings.length) {
|
|
153
|
+
if (!compiled.warnings) {
|
|
154
|
+
compiled.warnings = [];
|
|
155
|
+
}
|
|
156
|
+
compiled.warnings.push(...warnings);
|
|
157
|
+
}
|
|
129
158
|
if (!raw) {
|
|
130
159
|
// wire css import and code for hmr
|
|
131
160
|
const hasCss = compiled.css?.code?.trim().length > 0;
|
package/src/utils/error.js
CHANGED
|
@@ -100,3 +100,79 @@ function formatFrameForVite(frame) {
|
|
|
100
100
|
.map((line) => (line.match(/^\s+\^/) ? ' ' + line : ' ' + line.replace(':', ' | ')))
|
|
101
101
|
.join('\n');
|
|
102
102
|
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {import('svelte/types/compiler/interfaces').Warning & Error} err a svelte compiler error, which is a mix of Warning and an error
|
|
106
|
+
* @param {string} originalCode
|
|
107
|
+
* @param {import('../index.js').Arrayable<import('svelte/types/compiler/preprocess').PreprocessorGroup>} [preprocessors]
|
|
108
|
+
*/
|
|
109
|
+
export function enhanceCompileError(err, originalCode, preprocessors) {
|
|
110
|
+
preprocessors = arraify(preprocessors ?? []);
|
|
111
|
+
|
|
112
|
+
/** @type {string[]} */
|
|
113
|
+
const additionalMessages = [];
|
|
114
|
+
|
|
115
|
+
// Handle incorrect TypeScript usage
|
|
116
|
+
if (err.code === 'parse-error') {
|
|
117
|
+
// Reference from Svelte: https://github.com/sveltejs/svelte/blob/800f6c076be5dd87dd4d2e9d66c59b973d54d84b/packages/svelte/src/compiler/preprocess/index.js#L262
|
|
118
|
+
const scriptRe = /<script(\s[^]*?)?(?:>([^]*?)<\/script>|\/>)/gi;
|
|
119
|
+
const errIndex = err.pos ?? -1;
|
|
120
|
+
|
|
121
|
+
let m;
|
|
122
|
+
while ((m = scriptRe.exec(originalCode))) {
|
|
123
|
+
const matchStart = m.index;
|
|
124
|
+
const matchEnd = matchStart + m[0].length;
|
|
125
|
+
const isErrorInScript = matchStart <= errIndex && errIndex <= matchEnd;
|
|
126
|
+
if (isErrorInScript) {
|
|
127
|
+
// Warn missing lang="ts"
|
|
128
|
+
const hasLangTs = m[1]?.includes('lang="ts"');
|
|
129
|
+
if (!hasLangTs) {
|
|
130
|
+
additionalMessages.push('Did you forget to add lang="ts" to your script tag?');
|
|
131
|
+
}
|
|
132
|
+
// Warn missing script preprocessor
|
|
133
|
+
if (preprocessors.every((p) => p.script == null)) {
|
|
134
|
+
const preprocessorType = hasLangTs ? 'TypeScript' : 'script';
|
|
135
|
+
additionalMessages.push(
|
|
136
|
+
`Did you forget to add a ${preprocessorType} preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Handle incorrect CSS preprocessor usage
|
|
144
|
+
if (err.code === 'css-syntax-error') {
|
|
145
|
+
const styleRe = /<style(\s[^]*?)?(?:>([^]*?)<\/style>|\/>)/gi;
|
|
146
|
+
|
|
147
|
+
let m;
|
|
148
|
+
while ((m = styleRe.exec(originalCode))) {
|
|
149
|
+
// Warn missing lang attribute
|
|
150
|
+
if (!m[1]?.includes('lang=')) {
|
|
151
|
+
additionalMessages.push('Did you forget to add a lang attribute to your style tag?');
|
|
152
|
+
}
|
|
153
|
+
// Warn missing style preprocessor
|
|
154
|
+
if (
|
|
155
|
+
preprocessors.every((p) => p.style == null || p.name === 'inject-scope-everything-rule')
|
|
156
|
+
) {
|
|
157
|
+
const preprocessorType = m[1]?.match(/lang="(.+?)"/)?.[1] ?? 'style';
|
|
158
|
+
additionalMessages.push(
|
|
159
|
+
`Did you forget to add a ${preprocessorType} preprocessor? See https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/preprocess.md for more information.`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (additionalMessages.length) {
|
|
166
|
+
err.message += '\n\n- ' + additionalMessages.join('\n- ');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return err;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @param {T | T[]} value
|
|
174
|
+
* @template T
|
|
175
|
+
*/
|
|
176
|
+
function arraify(value) {
|
|
177
|
+
return Array.isArray(value) ? value : [value];
|
|
178
|
+
}
|
package/src/utils/esbuild.js
CHANGED
|
@@ -81,14 +81,18 @@ async function compileSvelte(options, { filename, code }, statsCollection) {
|
|
|
81
81
|
|
|
82
82
|
const finalCode = preprocessed ? preprocessed.code : code;
|
|
83
83
|
|
|
84
|
-
const dynamicCompileOptions = await options
|
|
84
|
+
const dynamicCompileOptions = await options?.dynamicCompileOptions?.({
|
|
85
85
|
filename,
|
|
86
86
|
code: finalCode,
|
|
87
87
|
compileOptions
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
if (dynamicCompileOptions && log.debug.enabled) {
|
|
91
|
-
log.debug(
|
|
91
|
+
log.debug(
|
|
92
|
+
`dynamic compile options for ${filename}: ${JSON.stringify(dynamicCompileOptions)}`,
|
|
93
|
+
undefined,
|
|
94
|
+
'compile'
|
|
95
|
+
);
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
const finalCompileOptions = dynamicCompileOptions
|
|
@@ -59,7 +59,8 @@ export async function loadSvelteConfig(viteConfig, inlineOptions) {
|
|
|
59
59
|
// identify which require function to use (esm and cjs mode)
|
|
60
60
|
const _require = import.meta.url
|
|
61
61
|
? esmRequire ?? (esmRequire = createRequire(import.meta.url))
|
|
62
|
-
:
|
|
62
|
+
: // eslint-disable-next-line no-undef
|
|
63
|
+
require;
|
|
63
64
|
|
|
64
65
|
// avoid loading cached version on reload
|
|
65
66
|
delete _require.cache[_require.resolve(configFile)];
|
package/src/utils/options.js
CHANGED
|
@@ -36,6 +36,7 @@ const allowedPluginOptions = new Set([
|
|
|
36
36
|
'disableDependencyReinclusion',
|
|
37
37
|
'prebundleSvelteLibraries',
|
|
38
38
|
'inspector',
|
|
39
|
+
'dynamicCompileOptions',
|
|
39
40
|
'experimental'
|
|
40
41
|
]);
|
|
41
42
|
|
|
@@ -316,13 +317,13 @@ function removeIgnoredOptions(options) {
|
|
|
316
317
|
function handleDeprecatedOptions(options) {
|
|
317
318
|
const experimental = /** @type {Record<string, any>} */ (options.experimental);
|
|
318
319
|
if (experimental) {
|
|
319
|
-
for (const promoted of ['prebundleSvelteLibraries', 'inspector']) {
|
|
320
|
+
for (const promoted of ['prebundleSvelteLibraries', 'inspector', 'dynamicCompileOptions']) {
|
|
320
321
|
if (experimental[promoted]) {
|
|
321
322
|
//@ts-expect-error untyped assign
|
|
322
323
|
options[promoted] = experimental[promoted];
|
|
323
324
|
delete experimental[promoted];
|
|
324
325
|
log.warn(
|
|
325
|
-
`Option "
|
|
326
|
+
`Option "experimental.${promoted}" is no longer experimental and has moved to "${promoted}". Please update your Svelte or Vite config.`
|
|
326
327
|
);
|
|
327
328
|
}
|
|
328
329
|
}
|
package/src/utils/preprocess.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import MagicString from 'magic-string';
|
|
2
2
|
import { log } from './log.js';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { normalizePath } from 'vite';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* this appends a *{} rule to component styles to force the svelte compiler to add style classes to all nodes
|
|
@@ -12,6 +13,7 @@ import path from 'node:path';
|
|
|
12
13
|
*/
|
|
13
14
|
export function createInjectScopeEverythingRulePreprocessorGroup() {
|
|
14
15
|
return {
|
|
16
|
+
name: 'inject-scope-everything-rule',
|
|
15
17
|
style({ content, filename }) {
|
|
16
18
|
const s = new MagicString(content);
|
|
17
19
|
s.append(' *{}');
|
|
@@ -120,3 +122,52 @@ export function addExtraPreprocessors(options, config) {
|
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
*
|
|
128
|
+
* @param filename {string}
|
|
129
|
+
* @param dependencies {string[]}
|
|
130
|
+
* @returns {({dependencies: string[], warnings:import('svelte/types/compiler/interfaces').Warning[] })}
|
|
131
|
+
*/
|
|
132
|
+
export function checkPreprocessDependencies(filename, dependencies) {
|
|
133
|
+
/** @type {import('svelte/types/compiler/interfaces').Warning[]} */
|
|
134
|
+
const warnings = [];
|
|
135
|
+
|
|
136
|
+
// to find self, we have to compare normalized filenames, but must keep the original values in `dependencies`
|
|
137
|
+
// because otherwise file watching on windows doesn't work
|
|
138
|
+
// so we track idx and filter by that in the end
|
|
139
|
+
/** @type {number[]} */
|
|
140
|
+
const selfIdx = [];
|
|
141
|
+
const normalizedFullFilename = normalizePath(filename);
|
|
142
|
+
const normalizedDeps = dependencies.map(normalizePath);
|
|
143
|
+
for (let i = 0; i < normalizedDeps.length; i++) {
|
|
144
|
+
if (normalizedDeps[i] === normalizedFullFilename) {
|
|
145
|
+
selfIdx.push(i);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const hasSelfDependency = selfIdx.length > 0;
|
|
149
|
+
if (hasSelfDependency) {
|
|
150
|
+
warnings.push({
|
|
151
|
+
code: 'vite-plugin-svelte-preprocess-depends-on-self',
|
|
152
|
+
message:
|
|
153
|
+
'svelte.preprocess returned this file as a dependency of itself. This can be caused by an invalid configuration or importing generated code that depends on .svelte files (eg. tailwind base css)',
|
|
154
|
+
filename
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (dependencies.length > 10) {
|
|
159
|
+
warnings.push({
|
|
160
|
+
code: 'vite-plugin-svelte-preprocess-many-dependencies',
|
|
161
|
+
message: `svelte.preprocess depends on more than 10 external files which can cause slow builds and poor DX, try to reduce them. Found: ${dependencies.join(
|
|
162
|
+
', '
|
|
163
|
+
)}`,
|
|
164
|
+
filename
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
dependencies: hasSelfDependency
|
|
169
|
+
? dependencies.filter((_, i) => !selfIdx.includes(i)) // remove self dependency
|
|
170
|
+
: dependencies,
|
|
171
|
+
warnings
|
|
172
|
+
};
|
|
173
|
+
}
|