Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/funny-waves-poke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/vite-plugin-svelte': minor
---

feat(preprocess): add warnings in case preprocess dependencies contain anomalies
25 changes: 23 additions & 2 deletions packages/vite-plugin-svelte/src/utils/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { createMakeHot } from 'svelte-hmr';
import { safeBase64Hash } from './hash.js';
import { log } from './log.js';

import { createInjectScopeEverythingRulePreprocessorGroup } from './preprocess.js';
import {
checkPreprocessDependencies,
createInjectScopeEverythingRulePreprocessorGroup
} from './preprocess.js';
import { mapToRelative } from './sourcemaps.js';
import { enhanceCompileError } from './error.js';

Expand All @@ -22,7 +25,10 @@ export const _createCompileSvelte = (makeHot) => {
return async function compileSvelte(svelteRequest, code, options) {
const { filename, normalizedFilename, cssId, ssr, raw } = svelteRequest;
const { emitCss = true } = options;
/** @type {string[]} */
const dependencies = [];
/** @type {import('svelte/types/compiler/interfaces').Warning[]} */
const warnings = [];

if (options.stats) {
if (options.isBuild) {
Expand Down Expand Up @@ -87,7 +93,16 @@ export const _createCompileSvelte = (makeHot) => {
throw e;
}

if (preprocessed.dependencies) dependencies.push(...preprocessed.dependencies);
if (preprocessed.dependencies?.length) {
const checked = checkPreprocessDependencies(filename, preprocessed.dependencies);
if (checked.warnings.length) {
warnings.push(...checked.warnings);
}
if (checked.dependencies.length) {
dependencies.push(...checked.dependencies);
}
}

if (preprocessed.map) compileOptions.sourcemap = preprocessed.map;
}
if (typeof preprocessed?.map === 'object') {
Expand Down Expand Up @@ -134,6 +149,12 @@ export const _createCompileSvelte = (makeHot) => {
}
mapToRelative(compiled.js?.map, filename);
mapToRelative(compiled.css?.map, filename);
if (warnings.length) {
if (!compiled.warnings) {
compiled.warnings = [];
}
compiled.warnings.push(...warnings);
}
if (!raw) {
// wire css import and code for hmr
const hasCss = compiled.css?.code?.trim().length > 0;
Expand Down
50 changes: 50 additions & 0 deletions packages/vite-plugin-svelte/src/utils/preprocess.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import MagicString from 'magic-string';
import { log } from './log.js';
import path from 'node:path';
import { normalizePath } from 'vite';

/**
* this appends a *{} rule to component styles to force the svelte compiler to add style classes to all nodes
Expand Down Expand Up @@ -121,3 +122,52 @@ export function addExtraPreprocessors(options, config) {
}
}
}

/**
*
* @param filename {string}
* @param dependencies {string[]}
* @returns {({dependencies: string[], warnings:import('svelte/types/compiler/interfaces').Warning[] })}
*/
export function checkPreprocessDependencies(filename, dependencies) {
/** @type {import('svelte/types/compiler/interfaces').Warning[]} */
const warnings = [];

// to find self, we have to compare normalized filenames, but must keep the original values in `dependencies`
// because otherwise file watching on windows doesn't work
// so we track idx and filter by that in the end
/** @type {number[]} */
const selfIdx = [];
const normalizedFullFilename = normalizePath(filename);
const normalizedDeps = dependencies.map(normalizePath);
for (let i = 0; i < normalizedDeps.length; i++) {
if (normalizedDeps[i] === normalizedFullFilename) {
selfIdx.push(i);
}
}
const hasSelfDependency = selfIdx.length > 0;
if (hasSelfDependency) {
warnings.push({
code: 'vite-plugin-svelte-preprocess-depends-on-self',
message:
'svelte.preprocess returned this file as a dependency of itself. This can be caused by invalid configuration or importing generated code that depends on .svelte files (eg. tailwind base css)',
filename
});
}

if (dependencies.length > 10) {
warnings.push({
code: 'vite-plugin-svelte-preprocess-many-dependencies',
message: `preprocess depends on more than 10 external files which can cause slow builds and poor DX, try to reduce them. Found: ${dependencies.join(
', '
)}`,
filename
});
}
return {
dependencies: hasSelfDependency
? dependencies.filter((_, i) => !selfIdx.includes(i)) // remove self dependency
: dependencies,
warnings
};
}