@@ -10,8 +10,7 @@ import colors from 'picocolors'
1010import type { Alias , AliasOptions } from 'dep-types/alias'
1111import type { RollupOptions } from 'rollup'
1212import picomatch from 'picomatch'
13- import { build } from 'esbuild'
14- import type { RolldownOptions } from 'rolldown'
13+ import { type OutputChunk , type RolldownOptions , rolldown } from 'rolldown'
1514import type { AnymatchFn } from '../types/anymatch'
1615import { withTrailingSlash } from '../shared/utils'
1716import {
@@ -2007,76 +2006,68 @@ async function bundleConfigFile(
20072006 const dirnameVarName = '__vite_injected_original_dirname'
20082007 const filenameVarName = '__vite_injected_original_filename'
20092008 const importMetaUrlVarName = '__vite_injected_original_import_meta_url'
2010- const result = await build ( {
2011- absWorkingDir : process . cwd ( ) ,
2012- entryPoints : [ fileName ] ,
2013- write : false ,
2014- target : [ `node${ process . versions . node } ` ] ,
2009+
2010+ const bundle = await rolldown ( {
2011+ input : fileName ,
2012+ // target: [`node${process.versions.node}`],
20152013 platform : 'node' ,
2016- bundle : true ,
2017- format : isESM ? 'esm' : 'cjs' ,
2018- mainFields : [ 'main' ] ,
2019- sourcemap : 'inline' ,
2020- // the last slash is needed to make the path correct
2021- sourceRoot : path . dirname ( fileName ) + path . sep ,
2022- metafile : true ,
2014+ resolve : {
2015+ mainFields : [ 'main' ] ,
2016+ } ,
20232017 define : {
20242018 __dirname : dirnameVarName ,
20252019 __filename : filenameVarName ,
20262020 'import.meta.url' : importMetaUrlVarName ,
20272021 'import.meta.dirname' : dirnameVarName ,
20282022 'import.meta.filename' : filenameVarName ,
20292023 } ,
2024+ // disable treeshake to include files that is not sideeffectful to `moduleIds`
2025+ treeshake : false ,
20302026 plugins : [
2031- {
2032- name : 'externalize-deps' ,
2033- setup ( build ) {
2034- const packageCache = new Map ( )
2035- const resolveByViteResolver = (
2036- id : string ,
2037- importer : string ,
2038- isRequire : boolean ,
2039- ) => {
2040- return tryNodeResolve ( id , importer , {
2041- root : path . dirname ( fileName ) ,
2042- isBuild : true ,
2043- isProduction : true ,
2044- preferRelative : false ,
2045- tryIndex : true ,
2046- mainFields : [ ] ,
2047- conditions : [
2048- 'node' ,
2049- ...( isModuleSyncConditionEnabled ? [ 'module-sync' ] : [ ] ) ,
2050- ] ,
2051- externalConditions : [ ] ,
2052- external : [ ] ,
2053- noExternal : [ ] ,
2054- dedupe : [ ] ,
2055- extensions : configDefaults . resolve . extensions ,
2056- preserveSymlinks : false ,
2057- packageCache,
2058- isRequire,
2059- builtins : nodeLikeBuiltins ,
2060- } ) ?. id
2061- }
2062-
2063- // externalize bare imports
2064- build . onResolve (
2065- { filter : / ^ [ ^ . # ] .* / } ,
2066- async ( { path : id , importer, kind } ) => {
2067- if (
2068- kind === 'entry-point' ||
2069- path . isAbsolute ( id ) ||
2070- isNodeBuiltin ( id )
2071- ) {
2027+ ( ( ) => {
2028+ const packageCache = new Map ( )
2029+ const resolveByViteResolver = (
2030+ id : string ,
2031+ importer : string ,
2032+ isRequire : boolean ,
2033+ ) => {
2034+ return tryNodeResolve ( id , importer , {
2035+ root : path . dirname ( fileName ) ,
2036+ isBuild : true ,
2037+ isProduction : true ,
2038+ preferRelative : false ,
2039+ tryIndex : true ,
2040+ mainFields : [ ] ,
2041+ conditions : [
2042+ 'node' ,
2043+ ...( isModuleSyncConditionEnabled ? [ 'module-sync' ] : [ ] ) ,
2044+ ] ,
2045+ externalConditions : [ ] ,
2046+ external : [ ] ,
2047+ noExternal : [ ] ,
2048+ dedupe : [ ] ,
2049+ extensions : configDefaults . resolve . extensions ,
2050+ preserveSymlinks : false ,
2051+ packageCache,
2052+ isRequire,
2053+ builtins : nodeLikeBuiltins ,
2054+ } ) ?. id
2055+ }
2056+
2057+ return {
2058+ name : 'externalize-deps' ,
2059+ resolveId : {
2060+ filter : { id : / ^ [ ^ . # ] .* / } ,
2061+ async handler ( id , importer , { kind } ) {
2062+ if ( ! importer || path . isAbsolute ( id ) || isNodeBuiltin ( id ) ) {
20722063 return
20732064 }
20742065
20752066 // With the `isNodeBuiltin` check above, this check captures if the builtin is a
20762067 // non-node built-in, which esbuild doesn't know how to handle. In that case, we
20772068 // externalize it so the non-node runtime handles it instead.
20782069 if ( isNodeLikeBuiltin ( id ) ) {
2079- return { external : true }
2070+ return { id , external : true }
20802071 }
20812072
20822073 const isImport = isESM || kind === 'dynamic-import'
@@ -2103,44 +2094,83 @@ async function bundleConfigFile(
21032094 }
21042095 throw e
21052096 }
2097+ if ( ! idFsPath ) return
2098+ // always no-externalize json files as rolldown does not support import attributes
2099+ if ( idFsPath . endsWith ( '.json' ) ) {
2100+ return idFsPath
2101+ }
2102+
21062103 if ( idFsPath && isImport ) {
21072104 idFsPath = pathToFileURL ( idFsPath ) . href
21082105 }
2109- return {
2110- path : idFsPath ,
2111- external : true ,
2112- }
2106+ return { id : idFsPath , external : true }
21132107 } ,
2114- )
2115- } ,
2116- } ,
2108+ } ,
2109+ }
2110+ } ) ( ) ,
21172111 {
21182112 name : 'inject-file-scope-variables' ,
2119- setup ( build ) {
2120- build . onLoad ( { filter : / \. [ c m ] ? [ j t ] s $ / } , async ( args ) => {
2121- const contents = await fsp . readFile ( args . path , 'utf-8' )
2113+ transform : {
2114+ filter : { id : / \. [ c m ] ? [ j t ] s $ / } ,
2115+ async handler ( code , id ) {
21222116 const injectValues =
2123- `const ${ dirnameVarName } = ${ JSON . stringify (
2124- path . dirname ( args . path ) ,
2125- ) } ;` +
2126- `const ${ filenameVarName } = ${ JSON . stringify ( args . path ) } ;` +
2117+ `const ${ dirnameVarName } = ${ JSON . stringify ( path . dirname ( id ) ) } ;` +
2118+ `const ${ filenameVarName } = ${ JSON . stringify ( id ) } ;` +
21272119 `const ${ importMetaUrlVarName } = ${ JSON . stringify (
2128- pathToFileURL ( args . path ) . href ,
2120+ pathToFileURL ( id ) . href ,
21292121 ) } ;`
2130-
2131- return {
2132- loader : args . path . endsWith ( 'ts' ) ? 'ts' : 'js' ,
2133- contents : injectValues + contents ,
2134- }
2135- } )
2122+ return { code : injectValues + code , map : null }
2123+ } ,
21362124 } ,
21372125 } ,
21382126 ] ,
21392127 } )
2140- const { text } = result . outputFiles [ 0 ]
2128+ const result = await bundle . generate ( {
2129+ format : isESM ? 'esm' : 'cjs' ,
2130+ sourcemap : 'inline' ,
2131+ sourcemapPathTransform ( relative ) {
2132+ return path . resolve ( fileName , relative )
2133+ } ,
2134+ } )
2135+ await bundle . close ( )
2136+
2137+ const entryChunk = result . output . find (
2138+ ( chunk ) : chunk is OutputChunk => chunk . type === 'chunk' && chunk . isEntry ,
2139+ ) !
2140+ const bundleChunks = Object . fromEntries (
2141+ result . output . flatMap ( ( c ) => ( c . type === 'chunk' ? [ [ c . fileName , c ] ] : [ ] ) ) ,
2142+ )
2143+
2144+ const allModules = new Set < string > ( )
2145+ collectAllModules ( bundleChunks , entryChunk . fileName , allModules )
2146+ allModules . delete ( fileName )
2147+
21412148 return {
2142- code : text ,
2143- dependencies : Object . keys ( result . metafile . inputs ) ,
2149+ code : entryChunk . code ,
2150+ dependencies : [ ...allModules ] ,
2151+ }
2152+ }
2153+
2154+ function collectAllModules (
2155+ bundle : Record < string , OutputChunk > ,
2156+ fileName : string ,
2157+ allModules : Set < string > ,
2158+ analyzedModules = new Set < string > ( ) ,
2159+ ) {
2160+ if ( analyzedModules . has ( fileName ) ) return
2161+ analyzedModules . add ( fileName )
2162+
2163+ const chunk = bundle [ fileName ] !
2164+ for ( const mod of chunk . moduleIds ) {
2165+ allModules . add ( mod )
2166+ }
2167+ for ( const i of chunk . imports ) {
2168+ analyzedModules . add ( i )
2169+ collectAllModules ( bundle , i , allModules , analyzedModules )
2170+ }
2171+ for ( const i of chunk . dynamicImports ) {
2172+ analyzedModules . add ( i )
2173+ collectAllModules ( bundle , i , allModules , analyzedModules )
21442174 }
21452175}
21462176
0 commit comments