diff --git a/.changeset/loud-cameras-double.md b/.changeset/loud-cameras-double.md new file mode 100644 index 000000000..99c960172 --- /dev/null +++ b/.changeset/loud-cameras-double.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/vite-plugin-svelte': patch +--- + +Refactor Svelte libraries config handling diff --git a/packages/vite-plugin-svelte/package.json b/packages/vite-plugin-svelte/package.json index ded11dbab..187f49069 100644 --- a/packages/vite-plugin-svelte/package.json +++ b/packages/vite-plugin-svelte/package.json @@ -51,7 +51,8 @@ "deepmerge": "^4.2.2", "kleur": "^4.1.5", "magic-string": "^0.26.7", - "svelte-hmr": "^0.15.0" + "svelte-hmr": "^0.15.0", + "vitefu": "^0.2.0" }, "peerDependencies": { "diff-match-patch": "^1.0.5", diff --git a/packages/vite-plugin-svelte/src/index.ts b/packages/vite-plugin-svelte/src/index.ts index 38aa79ab2..b3f034920 100644 --- a/packages/vite-plugin-svelte/src/index.ts +++ b/packages/vite-plugin-svelte/src/index.ts @@ -1,5 +1,7 @@ import fs from 'fs'; import { HmrContext, ModuleNode, Plugin, ResolvedConfig, UserConfig } from 'vite'; +// eslint-disable-next-line node/no-missing-import +import { isDepExcluded } from 'vitefu'; import { handleHotUpdate } from './handle-hot-update'; import { log, logCompilerWarnings } from './utils/log'; import { CompileData, createCompileSvelte } from './utils/compile'; @@ -19,7 +21,7 @@ import { ensureWatchedFile, setupWatchers } from './utils/watch'; import { resolveViaPackageJsonSvelte } from './utils/resolve'; import { PartialResolvedId } from 'rollup'; import { toRollupError } from './utils/error'; -import { isOptimizeExcluded, saveSvelteMetadata } from './utils/optimizer'; +import { saveSvelteMetadata } from './utils/optimizer'; import { svelteInspector } from './ui/inspector/plugin'; interface PluginAPI { @@ -68,7 +70,7 @@ export function svelte(inlineOptions?: Partial): Plugin[] { // @ts-expect-error temporarily lend the options variable until fixed in configResolved options = await preResolveOptions(inlineOptions, config, configEnv); // extra vite config - const extraViteConfig = buildExtraViteConfig(options, config); + const extraViteConfig = await buildExtraViteConfig(options, config); log.debug('additional vite config', extraViteConfig); return extraViteConfig; }, @@ -160,12 +162,12 @@ export function svelte(inlineOptions?: Partial): Plugin[] { options.prebundleSvelteLibraries && viteConfig.optimizeDeps?.disabled !== true && viteConfig.optimizeDeps?.disabled !== (options.isBuild ? 'build' : 'dev') && - !isOptimizeExcluded(importee, viteConfig.optimizeDeps?.exclude); + !isDepExcluded(importee, viteConfig.optimizeDeps?.exclude ?? []); // for prebundled libraries we let vite resolve the prebundling result // for ssr, during scanning and non-prebundled, we do it if (ssr || scan || !isPrebundled) { try { - const resolved = resolveViaPackageJsonSvelte(importee, importer, cache); + const resolved = await resolveViaPackageJsonSvelte(importee, importer, cache); if (resolved) { log.debug( `resolveId resolved ${resolved} via package.json svelte field of ${importee}` diff --git a/packages/vite-plugin-svelte/src/utils/__tests__/dependencies.spec.ts b/packages/vite-plugin-svelte/src/utils/__tests__/dependencies.spec.ts deleted file mode 100644 index baca99176..000000000 --- a/packages/vite-plugin-svelte/src/utils/__tests__/dependencies.spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { findRootSvelteDependencies, needsOptimization } from '../dependencies'; -import * as path from 'path'; -import { createRequire } from 'module'; -import { fileURLToPath } from 'url'; -const __dir = path.dirname(fileURLToPath(import.meta.url)); -const e2eTestRoot = path.resolve(__dir, '../../../../../packages/e2e-tests'); - -describe('dependencies', () => { - describe('findRootSvelteDependencies', () => { - it('should find svelte dependencies in packages/e2e-test/hmr', () => { - const deps = findRootSvelteDependencies(path.resolve('packages/e2e-tests/hmr')); - expect(deps).toHaveLength(1); - expect(deps[0].name).toBe('e2e-test-dep-svelte-simple'); - expect(deps[0].path).toEqual([]); - }); - it('should find nested svelte dependencies in packages/e2e-test/package-json-svelte-field', () => { - const deps = findRootSvelteDependencies(path.join(e2eTestRoot, 'package-json-svelte-field')); - expect(deps).toHaveLength(3); - const hybrid = deps.find((dep) => dep.name === 'e2e-test-dep-svelte-hybrid'); - expect(hybrid).toBeTruthy(); - expect(hybrid.path).toHaveLength(0); - const nested = deps.find((dep) => dep.name === 'e2e-test-dep-svelte-nested'); - expect(nested).toBeTruthy(); - expect(nested.path).toHaveLength(0); - const simple = deps.find((dep) => dep.name === 'e2e-test-dep-svelte-simple'); - expect(simple).toBeTruthy(); - expect(simple.path).toHaveLength(1); - expect(simple.path[0]).toBe('e2e-test-dep-svelte-nested'); - }); - }); - describe('needsOptimization', () => { - it('should optimize cjs deps only', () => { - const testDepsPath = path.join(e2eTestRoot, 'dependencies/package.json'); - const localRequire = createRequire(testDepsPath); - expect(needsOptimization('e2e-test-dep-cjs-and-esm', localRequire)).toBe(false); - expect(needsOptimization('e2e-test-dep-cjs-only', localRequire)).toBe(true); - expect(needsOptimization('e2e-test-dep-esm-only', localRequire)).toBe(false); - expect(needsOptimization('e2e-test-dep-index-only', localRequire)).toBe(true); - expect(needsOptimization('e2e-test-dep-types-only', localRequire)).toBe(false); - }); - }); -}); diff --git a/packages/vite-plugin-svelte/src/utils/dependencies.ts b/packages/vite-plugin-svelte/src/utils/dependencies.ts index 9061d4442..428c8c6a5 100644 --- a/packages/vite-plugin-svelte/src/utils/dependencies.ts +++ b/packages/vite-plugin-svelte/src/utils/dependencies.ts @@ -1,130 +1,29 @@ -import { log } from './log'; import path from 'path'; -import fs from 'fs'; -import { createRequire } from 'module'; +import fs from 'fs/promises'; +// eslint-disable-next-line node/no-missing-import +import { findDepPkgJsonPath } from 'vitefu'; -export function findRootSvelteDependencies(root: string, cwdFallback = true): SvelteDependency[] { - log.debug(`findSvelteDependencies: searching svelte dependencies in ${root}`); - const pkgFile = path.join(root, 'package.json'); - if (!fs.existsSync(pkgFile)) { - if (cwdFallback) { - const cwd = process.cwd(); - if (root !== cwd) { - log.debug(`no package.json found in vite root ${root}`); - return findRootSvelteDependencies(cwd, false); - } - } - log.warn(`no package.json found, findRootSvelteDependencies failed`); - return []; - } - - const pkg = parsePkg(root); - if (!pkg) { - return []; - } - - const deps = [ - ...Object.keys(pkg.dependencies || {}), - ...Object.keys(pkg.devDependencies || {}) - ].filter((dep) => !is_common_without_svelte_field(dep)); - - return getSvelteDependencies(deps, root); -} - -function getSvelteDependencies( - deps: string[], - pkgDir: string, - path: string[] = [] -): SvelteDependency[] { - const result = []; - const localRequire = createRequire(`${pkgDir}/package.json`); - const resolvedDeps = deps - .map((dep) => resolveDependencyData(dep, localRequire)) - .filter(Boolean) as DependencyData[]; - for (const { pkg, dir } of resolvedDeps) { - const type = getSvelteDependencyType(pkg); - if (!type) continue; - result.push({ name: pkg.name, type, pkg, dir, path }); - // continue crawling for component libraries so we can optimize them, js libraries are fine - if (type === 'component-library' && pkg.dependencies) { - let dependencyNames = Object.keys(pkg.dependencies); - const circular = dependencyNames.filter((name) => path.includes(name)); - if (circular.length > 0) { - log.warn.enabled && - log.warn( - `skipping circular svelte dependencies in automated vite optimizeDeps handling`, - circular.map((x) => path.concat(x).join('>')) - ); - dependencyNames = dependencyNames.filter((name) => !path.includes(name)); - } - if (path.length === 3) { - log.debug.once(`encountered deep svelte dependency tree: ${path.join('>')}`); - } - result.push(...getSvelteDependencies(dependencyNames, dir, path.concat(pkg.name))); - } - } - return result; +interface DependencyData { + dir: string; + pkg: Record; } -export function resolveDependencyData( +export async function resolveDependencyData( dep: string, - localRequire: NodeRequire -): DependencyData | void { - try { - const pkgJson = `${dep}/package.json`; - const pkg = localRequire(pkgJson); - const dir = path.dirname(localRequire.resolve(pkgJson)); - return { dir, pkg }; - } catch (e) { - log.debug.once(`dependency ${dep} does not export package.json`, e); - // walk up from default export until we find package.json with name=dep - try { - let dir = path.dirname(localRequire.resolve(dep)); - while (dir) { - const pkg = parsePkg(dir, true); - if (pkg && pkg.name === dep) { - return { dir, pkg }; - } - const parent = path.dirname(dir); - if (parent === dir) { - break; - } - dir = parent; - } - } catch (e) { - log.debug.once(`error while trying to find package.json of ${dep}`, e); - } - } - log.debug.once(`failed to resolve ${dep}`); -} - -function parsePkg(dir: string, silent = false): Pkg | void { - const pkgFile = path.join(dir, 'package.json'); + parent: string +): Promise { + const depDataPath = await findDepPkgJsonPath(dep, parent); + if (!depDataPath) return undefined; try { - return JSON.parse(fs.readFileSync(pkgFile, 'utf-8')); - } catch (e) { - !silent && log.warn.enabled && log.warn(`failed to parse ${pkgFile}`, e); - } -} - -function getSvelteDependencyType(pkg: Pkg): SvelteDependencyType | undefined { - if (isSvelteComponentLib(pkg)) { - return 'component-library'; - } else if (isSvelteLib(pkg)) { - return 'js-library'; - } else { + return { + dir: path.dirname(depDataPath), + pkg: JSON.parse(await fs.readFile(depDataPath, 'utf-8')) + }; + } catch { return undefined; } } -function isSvelteComponentLib(pkg: Pkg) { - return !!pkg.svelte; -} - -function isSvelteLib(pkg: Pkg) { - return !!pkg.dependencies?.svelte || !!pkg.peerDependencies?.svelte; -} - const COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD = [ '@lukeed/uuid', '@playwright/test', @@ -173,7 +72,7 @@ const COMMON_PREFIXES_WITHOUT_SVELTE_FIELD = [ * @param dependency {string} * @returns {boolean} true if it is a dependency without a svelte field */ -export function is_common_without_svelte_field(dependency: string): boolean { +export function isCommonDepWithoutSvelteField(dependency: string): boolean { return ( COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD.includes(dependency) || COMMON_PREFIXES_WITHOUT_SVELTE_FIELD.some( @@ -184,58 +83,3 @@ export function is_common_without_svelte_field(dependency: string): boolean { ) ); } - -export function needsOptimization(dep: string, localRequire: NodeRequire): boolean { - const depData = resolveDependencyData(dep, localRequire); - if (!depData) return false; - const pkg = depData.pkg; - // only optimize if is cjs, using the below as heuristic - // see https://github.com/sveltejs/vite-plugin-svelte/issues/162 - const hasEsmFields = pkg.module || pkg.exports; - if (hasEsmFields) return false; - if (pkg.main) { - // ensure entry is js so vite can prebundle it - // see https://github.com/sveltejs/vite-plugin-svelte/issues/233 - const entryExt = path.extname(pkg.main); - return !entryExt || entryExt === '.js' || entryExt === '.cjs'; - } else { - // check if has implicit index.js entrypoint - // https://github.com/sveltejs/vite-plugin-svelte/issues/281 - try { - localRequire.resolve(`${dep}/index.js`); - return true; - } catch { - return false; - } - } -} - -interface DependencyData { - dir: string; - pkg: Pkg; -} - -export interface SvelteDependency { - name: string; - type: SvelteDependencyType; - dir: string; - pkg: Pkg; - path: string[]; -} - -// component-library => exports svelte components -// js-library => only uses svelte api, no components -export type SvelteDependencyType = 'component-library' | 'js-library'; - -export interface Pkg { - name: string; - svelte?: string; - dependencies?: DependencyList; - devDependencies?: DependencyList; - peerDependencies?: DependencyList; - [key: string]: any; -} - -export interface DependencyList { - [key: string]: string; -} diff --git a/packages/vite-plugin-svelte/src/utils/optimizer.ts b/packages/vite-plugin-svelte/src/utils/optimizer.ts index 6b1cb2ee7..34e97bcfc 100644 --- a/packages/vite-plugin-svelte/src/utils/optimizer.ts +++ b/packages/vite-plugin-svelte/src/utils/optimizer.ts @@ -43,20 +43,3 @@ function generateSvelteMetadata(options: ResolvedOptions) { } return metadata; } - -// vite optimizeDeps.exclude works for subpackages too -// see https://github.com/vitejs/vite/blob/c87763c1418d1ba876eae13d139eba83ac6f28b2/packages/vite/src/node/optimizer/scan.ts#L293 -export function isOptimizeExcluded(dep: string, exclude?: string[]): boolean { - return !!exclude?.some((e) => dep === e || dep.startsWith(`${e}/`)); -} - -// include can contain `a > b` entries, so we have to test the last segment too -export function isOptimizeIncluded(dep: string, include?: string[]): boolean { - return !!include?.some((e) => { - if (e === dep) { - return true; - } - const lastArrow = e.lastIndexOf('>'); - return lastArrow > -1 && e.slice(lastArrow + 1).trim() === dep; - }); -} diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index 832ce97c7..34f43ffb3 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -1,12 +1,5 @@ /* eslint-disable no-unused-vars */ -import { - ConfigEnv, - DepOptimizationOptions, - ResolvedConfig, - UserConfig, - ViteDevServer, - normalizePath -} from 'vite'; +import { ConfigEnv, ResolvedConfig, UserConfig, ViteDevServer, normalizePath } from 'vite'; import { log } from './log'; import { loadSvelteConfig } from './load-svelte-config'; import { SVELTE_HMR_IMPORTS, SVELTE_IMPORTS, SVELTE_RESOLVE_MAIN_FIELDS } from './constants'; @@ -21,13 +14,19 @@ import type { } from 'svelte/types/compiler/preprocess'; import path from 'path'; -import { findRootSvelteDependencies, needsOptimization, SvelteDependency } from './dependencies'; -import { createRequire } from 'module'; import { esbuildSveltePlugin, facadeEsbuildSveltePluginName } from './esbuild'; import { addExtraPreprocessors } from './preprocess'; import deepmerge from 'deepmerge'; +import { + crawlFrameworkPkgs, + isDepExcluded, + isDepExternaled, + isDepIncluded, + isDepNoExternaled + // eslint-disable-next-line node/no-missing-import +} from 'vitefu'; import { atLeastSvelte } from './svelte-version'; -import { isOptimizeExcluded, isOptimizeIncluded } from './optimizer'; +import { isCommonDepWithoutSvelteField } from './dependencies'; // svelte 3.53.0 changed compilerOptions.css from boolean to string | boolen, use string when available const cssAsString = atLeastSvelte('3.53.0'); @@ -320,12 +319,10 @@ function resolveViteRoot(viteConfig: UserConfig): string | undefined { return normalizePath(viteConfig.root ? path.resolve(viteConfig.root) : process.cwd()); } -export function buildExtraViteConfig( +export async function buildExtraViteConfig( options: PreResolvedOptions, config: UserConfig -): Partial { - // extra handling for svelte dependencies in the project - const svelteDeps = findRootSvelteDependencies(options.root); +): Promise> { const extraViteConfig: Partial = { resolve: { mainFields: [...SVELTE_RESOLVE_MAIN_FIELDS], @@ -337,12 +334,37 @@ export function buildExtraViteConfig( // knownJsSrcExtensions: options.extensions }; - extraViteConfig.optimizeDeps = buildOptimizeDepsForSvelte( - svelteDeps, - options, - config.optimizeDeps - ); + const optimizeDepsConfig = buildOptimizeDepsForSvelte(config); + const ssrConfig = buildSSROptionsForSvelte(config); + const crawlConfig = await getCrawlPkgsConfig(options, config); + + extraViteConfig.optimizeDeps = { + include: [ + ...optimizeDepsConfig.include, + ...crawlConfig.optimizeDeps.include.filter( + (dep) => !isDepExcluded(dep, optimizeDepsConfig.exclude) + ) + ], + exclude: [ + ...optimizeDepsConfig.exclude, + ...crawlConfig.optimizeDeps.exclude.filter( + (dep) => !isDepIncluded(dep, optimizeDepsConfig.include) + ) + ] + }; + extraViteConfig.ssr = { + noExternal: [ + ...ssrConfig.noExternal, + ...crawlConfig.ssr.noExternal.filter((dep) => !isDepExternaled(dep, ssrConfig.external)) + ], + external: [ + ...ssrConfig.external, + ...crawlConfig.ssr.external.filter((dep) => !isDepNoExternaled(dep, ssrConfig.noExternal)) + ] + }; + + // handle prebundling for svelte files if (options.prebundleSvelteLibraries) { extraViteConfig.optimizeDeps = { ...extraViteConfig.optimizeDeps, @@ -358,9 +380,6 @@ export function buildExtraViteConfig( }; } - // @ts-ignore - extraViteConfig.ssr = buildSSROptionsForSvelte(svelteDeps, options, config, extraViteConfig); - // enable hmrPartialAccept if not explicitly disabled if ( (options.hot == null || @@ -374,103 +393,75 @@ export function buildExtraViteConfig( return extraViteConfig; } -function buildOptimizeDepsForSvelte( - svelteDeps: SvelteDependency[], - options: PreResolvedOptions, - optimizeDeps?: DepOptimizationOptions -): DepOptimizationOptions { +async function getCrawlPkgsConfig(options: PreResolvedOptions, config: UserConfig) { + // extra handling for svelte dependencies in the project + const depsConfig = await crawlFrameworkPkgs({ + root: options.root, + isBuild: options.isBuild, + viteUserConfig: config, + isFrameworkPkgByJson(pkgJson) { + return !!pkgJson.svelte; + }, + isSemiFrameworkPkgByJson(pkgJson) { + return !!pkgJson.dependencies?.svelte || !!pkgJson.peerDependencies?.svelte; + }, + isFrameworkPkgByName(pkgName) { + const isNotSveltePackage = isCommonDepWithoutSvelteField(pkgName); + if (isNotSveltePackage) { + return false; + } else { + return undefined; + } + } + }); + + log.debug('crawl svelte packages result', depsConfig); + + if (options.prebundleSvelteLibraries) { + depsConfig.optimizeDeps = { include: [], exclude: [] }; + } else if (options.disableDependencyReinclusion === true) { + depsConfig.optimizeDeps.include = depsConfig.optimizeDeps.include.filter( + (dep) => !dep.includes('>') + ); + } else if (Array.isArray(options.disableDependencyReinclusion)) { + const disabledDeps = options.disableDependencyReinclusion; + depsConfig.optimizeDeps.include = depsConfig.optimizeDeps.include.filter((dep) => { + if (!dep.includes('>')) return true; + const trimDep = dep.replace(/\s+/g, ''); + return disabledDeps.some((disabled) => trimDep.includes(`${disabled}>`)); + }); + } + + log.debug('processed crawl svelte packages result', depsConfig); + + return depsConfig; +} + +function buildOptimizeDepsForSvelte(config: UserConfig) { // include svelte imports for optimization unless explicitly excluded const include: string[] = []; const exclude: string[] = ['svelte-hmr']; - const isIncluded = (dep: string) => - isOptimizeIncluded(dep, include) || isOptimizeIncluded(dep, optimizeDeps?.include); - const isExcluded = (dep: string) => - isOptimizeExcluded(dep, exclude) || isOptimizeExcluded(dep, optimizeDeps?.exclude); - if (!isExcluded('svelte')) { + if (!isDepExcluded('svelte', config.optimizeDeps?.exclude ?? [])) { const svelteImportsToInclude = SVELTE_IMPORTS.filter((x) => x !== 'svelte/ssr'); // not used on clientside log.debug( `adding bare svelte packages to optimizeDeps.include: ${svelteImportsToInclude.join(', ')} ` ); - include.push(...svelteImportsToInclude.filter((x) => !isIncluded(x))); + include.push(...svelteImportsToInclude); } else { log.debug('"svelte" is excluded in optimizeDeps.exclude, skipped adding it to include.'); } - - // If we prebundle svelte libraries, we can skip the whole prebundling dance below - if (options.prebundleSvelteLibraries) { - return { include, exclude }; - } - - // only svelte component libraries needs to be processed for optimizeDeps, js libraries work fine - svelteDeps = svelteDeps.filter((dep) => dep.type === 'component-library'); - - const svelteDepsToExclude = Array.from(new Set(svelteDeps.map((dep) => dep.name))).filter( - (dep) => !isIncluded(dep) - ); - log.debug(`automatically excluding found svelte dependencies: ${svelteDepsToExclude.join(', ')}`); - exclude.push(...svelteDepsToExclude.filter((x) => !isExcluded(x))); - - if (options.disableDependencyReinclusion !== true) { - const disabledReinclusions = options.disableDependencyReinclusion || []; - if (disabledReinclusions.length > 0) { - log.debug(`not reincluding transitive dependencies of`, disabledReinclusions); - } - const transitiveDepsToInclude = svelteDeps - .filter((dep) => !disabledReinclusions.includes(dep.name) && isExcluded(dep.name)) - .flatMap((dep) => { - const localRequire = createRequire(`${dep.dir}/package.json`); - return Object.keys(dep.pkg.dependencies || {}) - .filter((depOfDep) => !isExcluded(depOfDep) && needsOptimization(depOfDep, localRequire)) - .map((depOfDep) => dep.path.concat(dep.name, depOfDep).join(' > ')); - }); - log.debug( - `reincluding transitive dependencies of excluded svelte dependencies`, - transitiveDepsToInclude - ); - include.push(...transitiveDepsToInclude); - } - return { include, exclude }; } -function buildSSROptionsForSvelte( - svelteDeps: SvelteDependency[], - options: ResolvedOptions, - config: UserConfig -): any { +function buildSSROptionsForSvelte(config: UserConfig) { const noExternal: (string | RegExp)[] = []; - + const external: string[] = []; // add svelte to ssr.noExternal unless it is present in ssr.external // so we can resolve it with svelte/ssr - if (!config.ssr?.external?.includes('svelte')) { + if (!isDepExternaled('svelte', config.ssr?.external ?? [])) { noExternal.push('svelte', /^svelte\//); } - - // add svelte dependencies to ssr.noExternal unless present in ssr.external - noExternal.push( - ...Array.from(new Set(svelteDeps.map((s) => s.name))).filter( - (x) => !config.ssr?.external?.includes(x) - ) - ); - const ssr = { - noExternal, - external: [] as string[] - }; - - if (options.isServe) { - // during dev, we have to externalize transitive dependencies, see https://github.com/sveltejs/vite-plugin-svelte/issues/281 - ssr.external = Array.from( - new Set(svelteDeps.flatMap((dep) => Object.keys(dep.pkg.dependencies || {}))) - ).filter( - (dep) => - !ssr.noExternal.includes(dep) && - // TODO noExternal can be something different than a string array - //!config.ssr?.noExternal?.includes(dep) && - !config.ssr?.external?.includes(dep) - ); - } - - return ssr; + return { noExternal, external }; } export function patchResolvedViteConfig(viteConfig: ResolvedConfig, options: ResolvedOptions) { diff --git a/packages/vite-plugin-svelte/src/utils/resolve.ts b/packages/vite-plugin-svelte/src/utils/resolve.ts index 2e03e2297..8fdb55390 100644 --- a/packages/vite-plugin-svelte/src/utils/resolve.ts +++ b/packages/vite-plugin-svelte/src/utils/resolve.ts @@ -1,25 +1,24 @@ import path from 'path'; -import { builtinModules, createRequire } from 'module'; -import { is_common_without_svelte_field, resolveDependencyData } from './dependencies'; +import { builtinModules } from 'module'; +import { resolveDependencyData, isCommonDepWithoutSvelteField } from './dependencies'; import { VitePluginSvelteCache } from './vite-plugin-svelte-cache'; -export function resolveViaPackageJsonSvelte( +export async function resolveViaPackageJsonSvelte( importee: string, importer: string | undefined, cache: VitePluginSvelteCache -): string | void { +): Promise { if ( importer && isBareImport(importee) && !isNodeInternal(importee) && - !is_common_without_svelte_field(importee) + !isCommonDepWithoutSvelteField(importee) ) { const cached = cache.getResolvedSvelteField(importee, importer); if (cached) { return cached; } - const localRequire = createRequire(importer); - const pkgData = resolveDependencyData(importee, localRequire); + const pkgData = await resolveDependencyData(importee, importer); if (pkgData) { const { pkg, dir } = pkgData; if (pkg.svelte) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 61193509e..13cfae049 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -508,12 +508,14 @@ importers: svelte-hmr: ^0.15.0 tsup: ^6.4.0 vite: ^3.2.3 + vitefu: ^0.2.0 dependencies: debug: 4.3.4 deepmerge: 4.2.2 kleur: 4.1.5 magic-string: 0.26.7 svelte-hmr: 0.15.0_svelte@3.53.1 + vitefu: 0.2.0_vite@3.2.3 devDependencies: '@types/debug': 4.1.7 '@types/diff-match-patch': 1.0.32 @@ -764,7 +766,6 @@ packages: cpu: [arm] os: [android] requiresBuild: true - dev: true optional: true /@esbuild/linux-loong64/0.15.13: @@ -773,7 +774,6 @@ packages: cpu: [loong64] os: [linux] requiresBuild: true - dev: true optional: true /@eslint/eslintrc/1.3.3: @@ -2237,7 +2237,6 @@ packages: cpu: [x64] os: [android] requiresBuild: true - dev: true optional: true /esbuild-android-arm64/0.15.13: @@ -2246,7 +2245,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: true optional: true /esbuild-darwin-64/0.15.13: @@ -2255,7 +2253,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: true optional: true /esbuild-darwin-arm64/0.15.13: @@ -2264,7 +2261,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: true optional: true /esbuild-freebsd-64/0.15.13: @@ -2273,7 +2269,6 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true - dev: true optional: true /esbuild-freebsd-arm64/0.15.13: @@ -2282,7 +2277,6 @@ packages: cpu: [arm64] os: [freebsd] requiresBuild: true - dev: true optional: true /esbuild-linux-32/0.15.13: @@ -2291,7 +2285,6 @@ packages: cpu: [ia32] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-linux-64/0.15.13: @@ -2300,7 +2293,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-linux-arm/0.15.13: @@ -2309,7 +2301,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-linux-arm64/0.15.13: @@ -2318,7 +2309,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-linux-mips64le/0.15.13: @@ -2327,7 +2317,6 @@ packages: cpu: [mips64el] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-linux-ppc64le/0.15.13: @@ -2336,7 +2325,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-linux-riscv64/0.15.13: @@ -2345,7 +2333,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-linux-s390x/0.15.13: @@ -2354,7 +2341,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: true optional: true /esbuild-netbsd-64/0.15.13: @@ -2363,7 +2349,6 @@ packages: cpu: [x64] os: [netbsd] requiresBuild: true - dev: true optional: true /esbuild-openbsd-64/0.15.13: @@ -2372,7 +2357,6 @@ packages: cpu: [x64] os: [openbsd] requiresBuild: true - dev: true optional: true /esbuild-sunos-64/0.15.13: @@ -2381,7 +2365,6 @@ packages: cpu: [x64] os: [sunos] requiresBuild: true - dev: true optional: true /esbuild-windows-32/0.15.13: @@ -2390,7 +2373,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: true optional: true /esbuild-windows-64/0.15.13: @@ -2399,7 +2381,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: true optional: true /esbuild-windows-arm64/0.15.13: @@ -2408,7 +2389,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: true optional: true /esbuild/0.15.13: @@ -2439,7 +2419,6 @@ packages: esbuild-windows-32: 0.15.13 esbuild-windows-64: 0.15.13 esbuild-windows-arm64: 0.15.13 - dev: true /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -2952,12 +2931,10 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: true /function.prototype.name/1.1.5: resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} @@ -3146,7 +3123,6 @@ packages: engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 - dev: true /hosted-git-info/2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -3329,7 +3305,6 @@ packages: resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} dependencies: has: 1.0.3 - dev: true /is-date-object/1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -3928,7 +3903,6 @@ packages: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true /natural-compare-lite/1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -4245,7 +4219,6 @@ packages: /path-parse/1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true /path-to-regexp/0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -4269,7 +4242,6 @@ packages: /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -4360,7 +4332,6 @@ packages: nanoid: 3.3.4 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /preferred-pm/3.0.3: resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==} @@ -4568,7 +4539,6 @@ packages: is-core-module: 2.10.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: true /restore-cursor/3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} @@ -4613,7 +4583,6 @@ packages: hasBin: true optionalDependencies: fsevents: 2.3.2 - dev: true /rollup/3.2.5: resolution: {integrity: sha512-/Ha7HhVVofduy+RKWOQJrxe4Qb3xyZo+chcpYiD8SoQa4AG7llhupUtyfKSSrdBM2mWJjhM8wZwmbY23NmlIYw==} @@ -4846,7 +4815,6 @@ packages: /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true /source-map/0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} @@ -5061,7 +5029,6 @@ packages: /supports-preserve-symlinks-flag/1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - dev: true /svelte-check/2.9.2_svelte@3.53.1: resolution: {integrity: sha512-DRi8HhnCiqiGR2YF9ervPGvtoYrheE09cXieCTEqeTPOTJzfoa54Py8rovIBv4bH4n5HgZYIyTQ3DDLHQLl2uQ==} @@ -5754,7 +5721,6 @@ packages: rollup: 2.79.1 optionalDependencies: fsevents: 2.3.2 - dev: true /vite/3.2.3_@types+node@18.11.9: resolution: {integrity: sha512-h8jl1TZ76eGs3o2dIBSsvXDLb1m/Ec1iej8ZMdz+PsaFUsftZeWe2CZOI3qogEsMNaywc17gu0q6cQDzh/weCQ==} @@ -5859,6 +5825,17 @@ packages: fsevents: 2.3.2 dev: true + /vitefu/0.2.0_vite@3.2.3: + resolution: {integrity: sha512-58946QxFCr0OnNbF73JPA3nyzfI65G82bWwKV8zxAcQfTeAyGU99ejSFIG7RBUDBUr1RonXI/VEMzIrNl/euXA==} + peerDependencies: + vite: ^3.0.0 || ^3.2.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 3.2.3 + dev: false + /vitest/0.25.0: resolution: {integrity: sha512-CVgBdKSeA27mowKC/C31Tx7ZBjRoyasq/yW7zoqUaCdKaOsjdzRUH5KgSL3eG36DzaaUsbnwWPUbAOtFz5k6tQ==} engines: {node: '>=v14.16.0'}