@@ -6,6 +6,7 @@ import type {
66} from 'es-module-lexer'
77import { init , parse as parseImports } from 'es-module-lexer'
88import type { SourceMap } from 'rolldown'
9+ import { buildImportAnalysisPlugin as nativeBuildImportAnalysisPlugin } from 'rolldown/experimental'
910import type { RawSourceMap } from '@ampproject/remapping'
1011import convertSourceMap from 'convert-source-map'
1112import {
@@ -14,11 +15,11 @@ import {
1415 isInNodeModules ,
1516 numberToPos ,
1617} from '../utils'
17- import type { Plugin } from '../plugin'
18+ import { type Plugin , perEnvironmentPlugin } from '../plugin'
1819import type { ResolvedConfig } from '../config'
1920import { toOutputFilePathInJS } from '../build'
2021import { genSourceMapUrl } from '../server/sourcemap'
21- import type { Environment } from '../environment '
22+ import type { PartialEnvironment } from '../baseEnvironment '
2223import { removedPureCssFilesCache } from './css'
2324import { createParseErrorInfo } from './importAnalysis'
2425
@@ -166,19 +167,51 @@ function preload(
166167 } )
167168}
168169
170+ function getPreloadCode (
171+ environment : PartialEnvironment ,
172+ renderBuiltUrlBoolean : boolean ,
173+ isRelativeBase : boolean ,
174+ ) {
175+ const { modulePreload } = environment . config . build
176+
177+ const scriptRel =
178+ modulePreload && modulePreload . polyfill
179+ ? `'modulepreload'`
180+ : `/* @__PURE__ */ (${ detectScriptRel . toString ( ) } )()`
181+
182+ // There are two different cases for the preload list format in __vitePreload
183+ //
184+ // __vitePreload(() => import(asyncChunk), [ ...deps... ])
185+ //
186+ // This is maintained to keep backwards compatibility as some users developed plugins
187+ // using regex over this list to workaround the fact that module preload wasn't
188+ // configurable.
189+ const assetsURL =
190+ renderBuiltUrlBoolean || isRelativeBase
191+ ? // If `experimental.renderBuiltUrl` is used, the dependencies might be relative to the current chunk.
192+ // If relative base is used, the dependencies are relative to the current chunk.
193+ // The importerUrl is passed as third parameter to __vitePreload in this case
194+ `function(dep, importerUrl) { return new URL(dep, importerUrl).href }`
195+ : // If the base isn't relative, then the deps are relative to the projects `outDir` and the base
196+ // is appended inside __vitePreload too.
197+ `function(dep) { return ${ JSON . stringify ( environment . config . base ) } +dep }`
198+ const preloadCode = `const scriptRel = ${ scriptRel } ;const assetsURL = ${ assetsURL } ;const seen = {};export const ${ preloadMethod } = ${ preload . toString ( ) } `
199+ return preloadCode
200+ }
201+
169202/**
170203 * Build only. During serve this is performed as part of ./importAnalysis.
171204 */
172205export function buildImportAnalysisPlugin ( config : ResolvedConfig ) : Plugin {
173- const getInsertPreload = ( environment : Environment ) =>
206+ const getInsertPreload = ( environment : PartialEnvironment ) =>
174207 environment . config . consumer === 'client' &&
175208 ! config . isWorker &&
176209 ! config . build . lib
177210
178211 const renderBuiltUrl = config . experimental . renderBuiltUrl
179212 const isRelativeBase = config . base === './' || config . base === ''
180213
181- return {
214+ const plugin : Plugin = {
182215 name : 'vite:build-import-analysis' ,
183216 resolveId : {
184217 filter : {
@@ -194,30 +227,11 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
194227 id : preloadHelperId ,
195228 } ,
196229 handler ( _id ) {
197- const { modulePreload } = this . environment . config . build
198-
199- const scriptRel =
200- modulePreload && modulePreload . polyfill
201- ? `'modulepreload'`
202- : `/* @__PURE__ */ (${ detectScriptRel . toString ( ) } )()`
203-
204- // There are two different cases for the preload list format in __vitePreload
205- //
206- // __vitePreload(() => import(asyncChunk), [ ...deps... ])
207- //
208- // This is maintained to keep backwards compatibility as some users developed plugins
209- // using regex over this list to workaround the fact that module preload wasn't
210- // configurable.
211- const assetsURL =
212- renderBuiltUrl || isRelativeBase
213- ? // If `experimental.renderBuiltUrl` is used, the dependencies might be relative to the current chunk.
214- // If relative base is used, the dependencies are relative to the current chunk.
215- // The importerUrl is passed as third parameter to __vitePreload in this case
216- `function(dep, importerUrl) { return new URL(dep, importerUrl).href }`
217- : // If the base isn't relative, then the deps are relative to the projects `outDir` and the base
218- // is appended inside __vitePreload too.
219- `function(dep) { return ${ JSON . stringify ( config . base ) } +dep }`
220- const preloadCode = `const scriptRel = ${ scriptRel } ;const assetsURL = ${ assetsURL } ;const seen = {};export const ${ preloadMethod } = ${ preload . toString ( ) } `
230+ const preloadCode = getPreloadCode (
231+ this . environment ,
232+ ! ! renderBuiltUrl ,
233+ isRelativeBase ,
234+ )
221235 return { code : preloadCode , moduleSideEffects : false }
222236 } ,
223237 } ,
@@ -738,4 +752,29 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
738752 }
739753 } ,
740754 }
755+
756+ if ( config . experimental . enableNativePlugin === true ) {
757+ delete plugin . transform
758+ delete plugin . resolveId
759+ delete plugin . load
760+ return perEnvironmentPlugin (
761+ 'native:import-analysis-build' ,
762+ ( environment ) => {
763+ const preloadCode = getPreloadCode (
764+ environment ,
765+ ! ! renderBuiltUrl ,
766+ isRelativeBase ,
767+ )
768+ return nativeBuildImportAnalysisPlugin ( {
769+ preloadCode,
770+ insertPreload : getInsertPreload ( environment ) ,
771+ // this field looks redundant, put a dummy value for now
772+ optimizeModulePreloadRelativePaths : false ,
773+ renderBuiltUrl : ! ! renderBuiltUrl ,
774+ isRelativeBase,
775+ } )
776+ } ,
777+ )
778+ }
779+ return plugin
741780}
0 commit comments