Skip to content

Commit

Permalink
feat: support object style hooks (#9634)
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu authored Aug 22, 2022
1 parent aca6ac2 commit 757a92f
Show file tree
Hide file tree
Showing 20 changed files with 398 additions and 223 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"prettier": "2.7.1",
"prompts": "^2.4.2",
"rimraf": "^3.0.2",
"rollup": ">=2.75.6 <2.77.0 || ~2.77.0",
"rollup": "~2.78.0",
"semver": "^7.3.7",
"simple-git-hooks": "^2.8.0",
"tslib": "^2.4.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.15",
"debug": "^4.3.4",
"rollup": ">=2.75.6 <2.77.0 || ~2.77.0",
"rollup": "~2.78.0",
"slash": "^4.0.0",
"source-map": "^0.6.1",
"vite": "workspace:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"esbuild": "^0.14.47",
"postcss": "^8.4.16",
"resolve": "^1.22.1",
"rollup": ">=2.75.6 <2.77.0 || ~2.77.0"
"rollup": "~2.78.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
Expand Down
53 changes: 39 additions & 14 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import type {
WarningHandler,
WatcherOptions
} from 'rollup'
import type Rollup from 'rollup'
import type { Terser } from 'types/terser'
import commonjsPlugin from '@rollup/plugin-commonjs'
import type { RollupCommonJSOptions } from 'types/commonjs'
Expand Down Expand Up @@ -788,34 +787,60 @@ function injectSsrFlagToHooks(plugin: Plugin): Plugin {
}
}

function wrapSsrResolveId(
fn?: Rollup.ResolveIdHook
): Rollup.ResolveIdHook | undefined {
if (!fn) return
function wrapSsrResolveId(hook?: Plugin['resolveId']): Plugin['resolveId'] {
if (!hook) return

return function (id, importer, options) {
const fn = 'handler' in hook ? hook.handler : hook
const handler: Plugin['resolveId'] = function (id, importer, options) {
return fn.call(this, id, importer, injectSsrFlag(options))
}

if ('handler' in hook) {
return {
...hook,
handler
} as Plugin['resolveId']
} else {
return handler
}
}

function wrapSsrLoad(fn?: Rollup.LoadHook): Rollup.LoadHook | undefined {
if (!fn) return
function wrapSsrLoad(hook?: Plugin['load']): Plugin['load'] {
if (!hook) return

return function (id, ...args) {
const fn = 'handler' in hook ? hook.handler : hook
const handler: Plugin['load'] = function (id, ...args) {
// @ts-expect-error: Receiving options param to be future-proof if Rollup adds it
return fn.call(this, id, injectSsrFlag(args[0]))
}

if ('handler' in hook) {
return {
...hook,
handler
} as Plugin['load']
} else {
return handler
}
}

function wrapSsrTransform(
fn?: Rollup.TransformHook
): Rollup.TransformHook | undefined {
if (!fn) return
function wrapSsrTransform(hook?: Plugin['transform']): Plugin['transform'] {
if (!hook) return

return function (code, importer, ...args) {
const fn = 'handler' in hook ? hook.handler : hook
const handler: Plugin['transform'] = function (code, importer, ...args) {
// @ts-expect-error: Receiving options param to be future-proof if Rollup adds it
return fn.call(this, code, importer, injectSsrFlag(args[0]))
}

if ('handler' in hook) {
return {
...hook,
handler
} as Plugin['transform']
} else {
return handler
}
}

function injectSsrFlag<T extends Record<string, any>>(
Expand Down
66 changes: 44 additions & 22 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { Alias, AliasOptions } from 'types/alias'
import aliasPlugin from '@rollup/plugin-alias'
import { build } from 'esbuild'
import type { RollupOptions } from 'rollup'
import type { Plugin } from './plugin'
import type { HookHandler, Plugin } from './plugin'
import type {
BuildOptions,
RenderBuiltAssetUrl,
Expand All @@ -33,7 +33,11 @@ import {
normalizeAlias,
normalizePath
} from './utils'
import { resolvePlugins } from './plugins'
import {
createPluginHookUtils,
getSortedPluginsByHook,
resolvePlugins
} from './plugins'
import type { ESBuildOptions } from './plugins/esbuild'
import {
CLIENT_ENTRY,
Expand Down Expand Up @@ -289,7 +293,7 @@ export interface LegacyOptions {
buildSsrCjsExternalHeuristics?: boolean
}

export interface ResolveWorkerOptions {
export interface ResolveWorkerOptions extends PluginHookUtils {
format: 'es' | 'iife'
plugins: Plugin[]
rollupOptions: RollupOptions
Expand Down Expand Up @@ -334,9 +338,16 @@ export type ResolvedConfig = Readonly<
worker: ResolveWorkerOptions
appType: AppType
experimental: ExperimentalOptions
}
} & PluginHookUtils
>

export interface PluginHookUtils {
getSortedPlugins: (hookName: keyof Plugin) => Plugin[]
getSortedPluginHooks: <K extends keyof Plugin>(
hookName: K
) => NonNullable<HookHandler<Plugin[K]>>[]
}

export type ResolveFn = (
id: string,
importer?: string,
Expand Down Expand Up @@ -431,9 +442,11 @@ export async function resolveConfig(

// run config hooks
const userPlugins = [...prePlugins, ...normalPlugins, ...postPlugins]
for (const p of userPlugins) {
if (p.config) {
const res = await p.config(config, configEnv)
for (const p of getSortedPluginsByHook('config', userPlugins)) {
const hook = p.config
const handler = hook && 'handler' in hook ? hook.handler : hook
if (handler) {
const res = await handler(config, configEnv)
if (res) {
config = mergeConfig(config, res)
}
Expand Down Expand Up @@ -598,9 +611,11 @@ export async function resolveConfig(
...workerNormalPlugins,
...workerPostPlugins
]
for (const p of workerUserPlugins) {
if (p.config) {
const res = await p.config(workerConfig, configEnv)
for (const p of getSortedPluginsByHook('config', workerUserPlugins)) {
const hook = p.config
const handler = hook && 'handler' in hook ? hook.handler : hook
if (handler) {
const res = await handler(workerConfig, configEnv)
if (res) {
workerConfig = mergeConfig(workerConfig, res)
}
Expand All @@ -609,7 +624,9 @@ export async function resolveConfig(
const resolvedWorkerOptions: ResolveWorkerOptions = {
format: workerConfig.worker?.format || 'iife',
plugins: [],
rollupOptions: workerConfig.worker?.rollupOptions || {}
rollupOptions: workerConfig.worker?.rollupOptions || {},
getSortedPlugins: undefined!,
getSortedPluginHooks: undefined!
}

const resolvedConfig: ResolvedConfig = {
Expand Down Expand Up @@ -660,7 +677,9 @@ export async function resolveConfig(
importGlobRestoreExtension: false,
hmrPartialAccept: false,
...config.experimental
}
},
getSortedPlugins: undefined!,
getSortedPluginHooks: undefined!
}
const resolved: ResolvedConfig = {
...config,
Expand All @@ -673,31 +692,34 @@ export async function resolveConfig(
normalPlugins,
postPlugins
)
Object.assign(resolved, createPluginHookUtils(resolved.plugins))

const workerResolved: ResolvedConfig = {
...workerConfig,
...resolvedConfig,
isWorker: true,
mainConfig: resolved
}

resolvedConfig.worker.plugins = await resolvePlugins(
workerResolved,
workerPrePlugins,
workerNormalPlugins,
workerPostPlugins
)
Object.assign(
resolvedConfig.worker,
createPluginHookUtils(resolvedConfig.worker.plugins)
)

// call configResolved hooks
await Promise.all(
userPlugins
.map((p) => p.configResolved?.(resolved))
.concat(
resolvedConfig.worker.plugins.map((p) =>
p.configResolved?.(workerResolved)
)
)
)
await Promise.all([
...resolved
.getSortedPluginHooks('configResolved')
.map((hook) => hook(resolved)),
...resolvedConfig.worker
.getSortedPluginHooks('configResolved')
.map((hook) => hook(workerResolved))
])

// validate config

Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export type {
SSRFormat,
SSRTarget
} from './ssr'
export type { Plugin } from './plugin'
export type { Plugin, HookHandler } from './plugin'
export type { PackageCache, PackageData } from './packages'
export type {
Logger,
Expand Down
83 changes: 48 additions & 35 deletions packages/vite/src/node/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
CustomPluginOptions,
LoadResult,
ObjectHook,
PluginContext,
ResolveIdResult,
Plugin as RollupPlugin,
Expand Down Expand Up @@ -63,14 +64,16 @@ export interface Plugin extends RollupPlugin {
* Note: User plugins are resolved before running this hook so injecting other
* plugins inside the `config` hook will have no effect.
*/
config?: (
config: UserConfig,
env: ConfigEnv
) => UserConfig | null | void | Promise<UserConfig | null | void>
config?: ObjectHook<
(
config: UserConfig,
env: ConfigEnv
) => UserConfig | null | void | Promise<UserConfig | null | void>
>
/**
* Use this hook to read and store the final resolved vite config.
*/
configResolved?: (config: ResolvedConfig) => void | Promise<void>
configResolved?: ObjectHook<(config: ResolvedConfig) => void | Promise<void>>
/**
* Configure the vite server. The hook receives the {@link ViteDevServer}
* instance. This can also be used to store a reference to the server
Expand All @@ -80,7 +83,7 @@ export interface Plugin extends RollupPlugin {
* can return a post hook that will be called after internal middlewares
* are applied. Hook can be async functions and will be called in series.
*/
configureServer?: ServerHook
configureServer?: ObjectHook<ServerHook>
/**
* Configure the preview server. The hook receives the connect server and
* its underlying http server.
Expand All @@ -89,7 +92,7 @@ export interface Plugin extends RollupPlugin {
* return a post hook that will be called after other middlewares are
* applied. Hooks can be async functions and will be called in series.
*/
configurePreviewServer?: PreviewServerHook
configurePreviewServer?: ObjectHook<PreviewServerHook>
/**
* Transform index.html.
* The hook receives the following arguments:
Expand Down Expand Up @@ -121,36 +124,46 @@ export interface Plugin extends RollupPlugin {
* - If the hook doesn't return a value, the hmr update will be performed as
* normal.
*/
handleHotUpdate?(
ctx: HmrContext
): Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>
handleHotUpdate?: ObjectHook<
(
ctx: HmrContext
) => Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>
>

/**
* extend hooks with ssr flag
*/
resolveId?: (
this: PluginContext,
source: string,
importer: string | undefined,
options: {
custom?: CustomPluginOptions
ssr?: boolean
/**
* @internal
*/
scan?: boolean
isEntry: boolean
}
) => Promise<ResolveIdResult> | ResolveIdResult
load?: (
this: PluginContext,
id: string,
options?: { ssr?: boolean }
) => Promise<LoadResult> | LoadResult
transform?: (
this: TransformPluginContext,
code: string,
id: string,
options?: { ssr?: boolean }
) => Promise<TransformResult> | TransformResult
resolveId?: ObjectHook<
(
this: PluginContext,
source: string,
importer: string | undefined,
options: {
custom?: CustomPluginOptions
ssr?: boolean
/**
* @internal
*/
scan?: boolean
isEntry: boolean
}
) => Promise<ResolveIdResult> | ResolveIdResult
>
load?: ObjectHook<
(
this: PluginContext,
id: string,
options?: { ssr?: boolean }
) => Promise<LoadResult> | LoadResult
>
transform?: ObjectHook<
(
this: TransformPluginContext,
code: string,
id: string,
options?: { ssr?: boolean }
) => Promise<TransformResult> | TransformResult
>
}

export type HookHandler<T> = T extends ObjectHook<infer H> ? H : T
Loading

0 comments on commit 757a92f

Please sign in to comment.