Skip to content

Commit

Permalink
feat: this.environment in buildStart, rework more internal plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
patak-dev committed Apr 29, 2024
1 parent 8231283 commit bda0dc5
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 112 deletions.
13 changes: 11 additions & 2 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ export async function resolveBuildPlugins(config: ResolvedConfig): Promise<{
...(options.minify ? [terserPlugin(config)] : []),
...(!config.isWorker
? [
...(options.manifest ? [manifestPlugin(config)] : []),
...(options.manifest ? [manifestPlugin()] : []),
...(options.ssrManifest ? [ssrManifestPlugin(config)] : []),
buildReporterPlugin(config),
]
Expand Down Expand Up @@ -1083,12 +1083,20 @@ export function injectEnvironmentToHooks(
plugin: Plugin,
environment?: BuildEnvironment,
): Plugin {
const { resolveId, load, transform, generateBundle, renderChunk } = plugin
const {
buildStart,
resolveId,
load,
transform,
generateBundle,
renderChunk,
} = plugin
return {
...plugin,
resolveId: wrapEnvironmentResolveId(resolveId, environment),
load: wrapEnvironmentLoad(load, environment),
transform: wrapEnvironmentTransform(transform, environment),
buildStart: wrapEnvironmentHook(buildStart, environment),
generateBundle: wrapEnvironmentHook(generateBundle, environment),
renderChunk: wrapEnvironmentHook(renderChunk, environment),
}
Expand Down Expand Up @@ -1303,6 +1311,7 @@ export type RenderBuiltAssetUrl = (
},
) => string | { relative?: boolean; runtime?: string } | undefined

// TODO: experimental.renderBuiltUrl => environment.build.renderBuiltUrl?
export function toOutputFilePathInJS(
filename: string,
type: 'asset' | 'public',
Expand Down
7 changes: 5 additions & 2 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,9 @@ export interface LegacyOptions {

export interface ResolvedWorkerOptions {
format: 'es' | 'iife'
plugins: (bundleChain: string[]) => Promise<Plugin[]>
plugins: (
bundleChain: string[],
) => Promise<{ plugins: Plugin[]; config: ResolvedConfig }>
rollupOptions: RollupOptions
}

Expand Down Expand Up @@ -1084,6 +1086,7 @@ export async function resolveConfig(
)
}

// TODO: Workers as environments could allow us to remove a lot of complexity
const createWorkerPlugins = async function (bundleChain: string[]) {
// Some plugins that aren't intended to work in the bundling of workers (doing post-processing at build time for example).
// And Plugins may also have cached that could be corrupted by being used in these extra rollup calls.
Expand Down Expand Up @@ -1130,7 +1133,7 @@ export async function resolveConfig(
.map((hook) => hook(workerResolved)),
)

return resolvedWorkerPlugins
return { plugins: resolvedWorkerPlugins, config: workerResolved }
}

const resolvedWorkerOptions: ResolvedWorkerOptions = {
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export interface BasePlugin<A = any> extends RollupPlugin<A> {
>

// TODO: abstract to every hook in RollupPlugin?
buildStart?: ModifyHookContext<RollupPlugin<A>['buildStart'], PluginContext>
generateBundle?: ModifyHookContext<
RollupPlugin<A>['generateBundle'],
PluginContext
Expand Down
82 changes: 43 additions & 39 deletions packages/vite/src/node/plugins/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@ import { parse as parseUrl } from 'node:url'
import fsp from 'node:fs/promises'
import { Buffer } from 'node:buffer'
import * as mrmime from 'mrmime'
import type {
NormalizedOutputOptions,
PluginContext,
RenderedChunk,
} from 'rollup'
import type { NormalizedOutputOptions, RenderedChunk } from 'rollup'
import MagicString from 'magic-string'
import colors from 'picocolors'
import {
createToImportMetaURLBasedRelativeRuntime,
toOutputFilePathInJS,
} from '../build'
import type { Plugin } from '../plugin'
import type { Plugin, PluginContext } from '../plugin'
import type { Environment } from '../environment'
import type { ResolvedConfig } from '../config'
import { checkPublicFile } from '../publicDir'
import {
Expand All @@ -36,7 +33,7 @@ export const assetUrlRE = /__VITE_ASSET__([\w$]+)__(?:\$_(.*?)__)?/g

const jsSourceMapRE = /\.[cm]?js\.map$/

const assetCache = new WeakMap<ResolvedConfig, Map<string, string>>()
const assetCache = new WeakMap<Environment, Map<string, string>>()

// chunk.name is the basename for the asset ignoring the directory structure
// For the manifest, we need to preserve the original file path and isEntry
Expand All @@ -45,8 +42,8 @@ export interface GeneratedAssetMeta {
originalName: string
isEntry?: boolean
}
export const generatedAssets = new WeakMap<
ResolvedConfig,
export const generatedAssetsMap = new WeakMap<
Environment,
Map<string, GeneratedAssetMeta>
>()

Expand All @@ -62,11 +59,13 @@ export function registerCustomMime(): void {

export function renderAssetUrlInJS(
ctx: PluginContext,
config: ResolvedConfig,
chunk: RenderedChunk,
opts: NormalizedOutputOptions,
code: string,
): MagicString | undefined {
const environment = ctx.environment!
const { config } = environment

const toRelativeRuntime = createToImportMetaURLBasedRelativeRuntime(
opts.format,
config.isWorker,
Expand Down Expand Up @@ -145,8 +144,12 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
name: 'vite:asset',

buildStart() {
assetCache.set(config, new Map())
generatedAssets.set(config, new Map())
const { environment } = this
if (!environment) {
return
}
assetCache.set(environment, new Map())
generatedAssetsMap.set(environment, new Map())
},

resolveId(id) {
Expand Down Expand Up @@ -189,7 +192,7 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
}

id = removeUrlQuery(id)
let url = await fileToUrl(id, config, this)
let url = await fileToUrl(this, id)

// Inherit HMR timestamp if this asset was invalidated
const environment = this.environment
Expand All @@ -212,12 +215,12 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
},

renderChunk(code, chunk, opts) {
const s = renderAssetUrlInJS(this, config, chunk, opts, code)
const s = renderAssetUrlInJS(this, chunk, opts, code)

if (s) {
return {
code: s.toString(),
map: config.build.sourcemap
map: this.environment?.options.build.sourcemap
? s.generateMap({ hires: 'boundary' })
: null,
}
Expand All @@ -227,6 +230,8 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
},

generateBundle(_, bundle) {
const environment = this.environment!

// Remove empty entry point file
for (const file in bundle) {
const chunk = bundle[file]
Expand All @@ -241,11 +246,7 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
}

// do not emit assets for SSR build
if (
config.command === 'build' &&
config.build.ssr &&
!config.build.emitAssets
) {
if (config.command === 'build' && !environment.options.build.emitAssets) {
for (const file in bundle) {
if (
bundle[file].type === 'asset' &&
Expand All @@ -261,14 +262,14 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
}

export async function fileToUrl(
id: string,
config: ResolvedConfig,
ctx: PluginContext,
id: string,
): Promise<string> {
if (config.command === 'serve') {
return fileToDevUrl(id, config)
const environment = ctx.environment!
if (environment.config.command === 'serve') {
return fileToDevUrl(id, environment.config)
} else {
return fileToBuiltUrl(id, config, ctx)
return fileToBuiltUrl(ctx, id)
}
}

Expand Down Expand Up @@ -336,17 +337,18 @@ function isGitLfsPlaceholder(content: Buffer): boolean {
* and returns the resolved public URL
*/
async function fileToBuiltUrl(
id: string,
config: ResolvedConfig,
pluginContext: PluginContext,
id: string,
skipPublicCheck = false,
forceInline?: boolean,
): Promise<string> {
const environment = pluginContext.environment!
const { config } = environment
if (!skipPublicCheck && checkPublicFile(id, config)) {
return publicFileToBuiltUrl(id, config)
}

const cache = assetCache.get(config)!
const cache = assetCache.get(environment)!
const cached = cache.get(id)
if (cached) {
return cached
Expand All @@ -356,7 +358,7 @@ async function fileToBuiltUrl(
const content = await fsp.readFile(file)

let url: string
if (shouldInline(config, file, id, content, pluginContext, forceInline)) {
if (shouldInline(pluginContext, file, id, content, forceInline)) {
if (config.build.lib && isGitLfsPlaceholder(content)) {
config.logger.warn(
colors.yellow(`Inlined file ${id} was not downloaded via Git LFS`),
Expand All @@ -383,7 +385,7 @@ async function fileToBuiltUrl(
})

const originalName = normalizePath(path.relative(config.root, file))
generatedAssets.get(config)!.set(referenceId, { originalName })
generatedAssetsMap.get(environment)!.set(referenceId, { originalName })

url = `__VITE_ASSET__${referenceId}__${postfix ? `$_${postfix}__` : ``}` // TODO_BASE
}
Expand All @@ -393,12 +395,13 @@ async function fileToBuiltUrl(
}

export async function urlToBuiltUrl(
pluginContext: PluginContext,
url: string,
importer: string,
config: ResolvedConfig,
pluginContext: PluginContext,
forceInline?: boolean,
): Promise<string> {
const environment = pluginContext.environment!
const { config } = environment
if (checkPublicFile(url, config)) {
return publicFileToBuiltUrl(url, config)
}
Expand All @@ -407,33 +410,34 @@ export async function urlToBuiltUrl(
? path.join(config.root, url)
: path.join(path.dirname(importer), url)
return fileToBuiltUrl(
file,
config,
pluginContext,
file,
// skip public check since we just did it above
true,
forceInline,
)
}

const shouldInline = (
config: ResolvedConfig,
pluginContext: PluginContext,
file: string,
id: string,
content: Buffer,
pluginContext: PluginContext,
forceInline: boolean | undefined,
): boolean => {
const environment = pluginContext.environment!
const { config } = environment
const { assetsInlineLimit } = environment.options.build
if (config.build.lib) return true
if (pluginContext.getModuleInfo(id)?.isEntry) return false
if (forceInline !== undefined) return forceInline
let limit: number
if (typeof config.build.assetsInlineLimit === 'function') {
const userShouldInline = config.build.assetsInlineLimit(file, content)
if (typeof assetsInlineLimit === 'function') {
const userShouldInline = assetsInlineLimit(file, content)
if (userShouldInline != null) return userShouldInline
limit = DEFAULT_ASSETS_INLINE_LIMIT
} else {
limit = Number(config.build.assetsInlineLimit)
limit = Number(assetsInlineLimit)
}
if (file.endsWith('.html')) return false
// Don't inline SVG with fragments, as they are meant to be reused
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/assetImportMetaUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
try {
if (publicDir && isParentDirectory(publicDir, file)) {
const publicPath = '/' + path.posix.relative(publicDir, file)
builtUrl = await fileToUrl(publicPath, config, this)
builtUrl = await fileToUrl(this, publicPath)
} else {
builtUrl = await fileToUrl(file, config, this)
builtUrl = await fileToUrl(this, file)
}
} catch {
// do nothing, we'll log a warning after this
Expand Down
Loading

0 comments on commit bda0dc5

Please sign in to comment.