1- import { log } from './log' ;
21import path from 'path' ;
3- import fs from 'fs' ;
4- import { createRequire } from 'module' ;
2+ import fs from 'fs/promises' ;
3+ // eslint-disable-next-line node/no-missing-import
4+ import { findDepPkgJsonPath } from 'vitefu' ;
55
6- export function findRootSvelteDependencies ( root : string , cwdFallback = true ) : SvelteDependency [ ] {
7- log . debug ( `findSvelteDependencies: searching svelte dependencies in ${ root } ` ) ;
8- const pkgFile = path . join ( root , 'package.json' ) ;
9- if ( ! fs . existsSync ( pkgFile ) ) {
10- if ( cwdFallback ) {
11- const cwd = process . cwd ( ) ;
12- if ( root !== cwd ) {
13- log . debug ( `no package.json found in vite root ${ root } ` ) ;
14- return findRootSvelteDependencies ( cwd , false ) ;
15- }
16- }
17- log . warn ( `no package.json found, findRootSvelteDependencies failed` ) ;
18- return [ ] ;
19- }
20-
21- const pkg = parsePkg ( root ) ;
22- if ( ! pkg ) {
23- return [ ] ;
24- }
25-
26- const deps = [
27- ...Object . keys ( pkg . dependencies || { } ) ,
28- ...Object . keys ( pkg . devDependencies || { } )
29- ] . filter ( ( dep ) => ! is_common_without_svelte_field ( dep ) ) ;
30-
31- return getSvelteDependencies ( deps , root ) ;
32- }
33-
34- function getSvelteDependencies (
35- deps : string [ ] ,
36- pkgDir : string ,
37- path : string [ ] = [ ]
38- ) : SvelteDependency [ ] {
39- const result = [ ] ;
40- const localRequire = createRequire ( `${ pkgDir } /package.json` ) ;
41- const resolvedDeps = deps
42- . map ( ( dep ) => resolveDependencyData ( dep , localRequire ) )
43- . filter ( Boolean ) as DependencyData [ ] ;
44- for ( const { pkg, dir } of resolvedDeps ) {
45- const type = getSvelteDependencyType ( pkg ) ;
46- if ( ! type ) continue ;
47- result . push ( { name : pkg . name , type, pkg, dir, path } ) ;
48- // continue crawling for component libraries so we can optimize them, js libraries are fine
49- if ( type === 'component-library' && pkg . dependencies ) {
50- let dependencyNames = Object . keys ( pkg . dependencies ) ;
51- const circular = dependencyNames . filter ( ( name ) => path . includes ( name ) ) ;
52- if ( circular . length > 0 ) {
53- log . warn . enabled &&
54- log . warn (
55- `skipping circular svelte dependencies in automated vite optimizeDeps handling` ,
56- circular . map ( ( x ) => path . concat ( x ) . join ( '>' ) )
57- ) ;
58- dependencyNames = dependencyNames . filter ( ( name ) => ! path . includes ( name ) ) ;
59- }
60- if ( path . length === 3 ) {
61- log . debug . once ( `encountered deep svelte dependency tree: ${ path . join ( '>' ) } ` ) ;
62- }
63- result . push ( ...getSvelteDependencies ( dependencyNames , dir , path . concat ( pkg . name ) ) ) ;
64- }
65- }
66- return result ;
6+ interface DependencyData {
7+ dir : string ;
8+ pkg : Record < string , any > ;
679}
6810
69- export function resolveDependencyData (
11+ export async function resolveDependencyData (
7012 dep : string ,
71- localRequire : NodeRequire
72- ) : DependencyData | void {
73- try {
74- const pkgJson = `${ dep } /package.json` ;
75- const pkg = localRequire ( pkgJson ) ;
76- const dir = path . dirname ( localRequire . resolve ( pkgJson ) ) ;
77- return { dir, pkg } ;
78- } catch ( e ) {
79- log . debug . once ( `dependency ${ dep } does not export package.json` , e ) ;
80- // walk up from default export until we find package.json with name=dep
81- try {
82- let dir = path . dirname ( localRequire . resolve ( dep ) ) ;
83- while ( dir ) {
84- const pkg = parsePkg ( dir , true ) ;
85- if ( pkg && pkg . name === dep ) {
86- return { dir, pkg } ;
87- }
88- const parent = path . dirname ( dir ) ;
89- if ( parent === dir ) {
90- break ;
91- }
92- dir = parent ;
93- }
94- } catch ( e ) {
95- log . debug . once ( `error while trying to find package.json of ${ dep } ` , e ) ;
96- }
97- }
98- log . debug . once ( `failed to resolve ${ dep } ` ) ;
99- }
100-
101- function parsePkg ( dir : string , silent = false ) : Pkg | void {
102- const pkgFile = path . join ( dir , 'package.json' ) ;
13+ parent : string
14+ ) : Promise < DependencyData | undefined > {
15+ const depDataPath = await findDepPkgJsonPath ( dep , parent ) ;
16+ if ( ! depDataPath ) return undefined ;
10317 try {
104- return JSON . parse ( fs . readFileSync ( pkgFile , 'utf-8' ) ) ;
105- } catch ( e ) {
106- ! silent && log . warn . enabled && log . warn ( `failed to parse ${ pkgFile } ` , e ) ;
107- }
108- }
109-
110- function getSvelteDependencyType ( pkg : Pkg ) : SvelteDependencyType | undefined {
111- if ( isSvelteComponentLib ( pkg ) ) {
112- return 'component-library' ;
113- } else if ( isSvelteLib ( pkg ) ) {
114- return 'js-library' ;
115- } else {
18+ return {
19+ dir : path . dirname ( depDataPath ) ,
20+ pkg : JSON . parse ( await fs . readFile ( depDataPath , 'utf-8' ) )
21+ } ;
22+ } catch {
11623 return undefined ;
11724 }
11825}
11926
120- function isSvelteComponentLib ( pkg : Pkg ) {
121- return ! ! pkg . svelte ;
122- }
123-
124- function isSvelteLib ( pkg : Pkg ) {
125- return ! ! pkg . dependencies ?. svelte || ! ! pkg . peerDependencies ?. svelte ;
126- }
127-
12827const COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD = [
12928 '@lukeed/uuid' ,
13029 '@playwright/test' ,
@@ -173,7 +72,7 @@ const COMMON_PREFIXES_WITHOUT_SVELTE_FIELD = [
17372 * @param dependency {string}
17473 * @returns {boolean } true if it is a dependency without a svelte field
17574 */
176- export function is_common_without_svelte_field ( dependency : string ) : boolean {
75+ export function isCommonDepWithoutSvelteField ( dependency : string ) : boolean {
17776 return (
17877 COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD . includes ( dependency ) ||
17978 COMMON_PREFIXES_WITHOUT_SVELTE_FIELD . some (
@@ -184,58 +83,3 @@ export function is_common_without_svelte_field(dependency: string): boolean {
18483 )
18584 ) ;
18685}
187-
188- export function needsOptimization ( dep : string , localRequire : NodeRequire ) : boolean {
189- const depData = resolveDependencyData ( dep , localRequire ) ;
190- if ( ! depData ) return false ;
191- const pkg = depData . pkg ;
192- // only optimize if is cjs, using the below as heuristic
193- // see https://github.com/sveltejs/vite-plugin-svelte/issues/162
194- const hasEsmFields = pkg . module || pkg . exports ;
195- if ( hasEsmFields ) return false ;
196- if ( pkg . main ) {
197- // ensure entry is js so vite can prebundle it
198- // see https://github.com/sveltejs/vite-plugin-svelte/issues/233
199- const entryExt = path . extname ( pkg . main ) ;
200- return ! entryExt || entryExt === '.js' || entryExt === '.cjs' ;
201- } else {
202- // check if has implicit index.js entrypoint
203- // https://github.com/sveltejs/vite-plugin-svelte/issues/281
204- try {
205- localRequire . resolve ( `${ dep } /index.js` ) ;
206- return true ;
207- } catch {
208- return false ;
209- }
210- }
211- }
212-
213- interface DependencyData {
214- dir : string ;
215- pkg : Pkg ;
216- }
217-
218- export interface SvelteDependency {
219- name : string ;
220- type : SvelteDependencyType ;
221- dir : string ;
222- pkg : Pkg ;
223- path : string [ ] ;
224- }
225-
226- // component-library => exports svelte components
227- // js-library => only uses svelte api, no components
228- export type SvelteDependencyType = 'component-library' | 'js-library' ;
229-
230- export interface Pkg {
231- name : string ;
232- svelte ?: string ;
233- dependencies ?: DependencyList ;
234- devDependencies ?: DependencyList ;
235- peerDependencies ?: DependencyList ;
236- [ key : string ] : any ;
237- }
238-
239- export interface DependencyList {
240- [ key : string ] : string ;
241- }
0 commit comments