Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support object style hooks #9634

Merged
merged 21 commits into from Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
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",
antfu marked this conversation as resolved.
Show resolved Hide resolved
"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
Expand Up @@ -42,7 +42,7 @@
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.14",
"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
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
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 @@ -786,34 +785,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
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is worth extracting a helper for these three functions to avoid repeating the function or object handling?

}

function injectSsrFlag<T extends Record<string, any>>(
Expand Down
66 changes: 44 additions & 22 deletions packages/vite/src/node/config.ts
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)),
Copy link
Member

@csr632 csr632 Sep 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this inside the hook no loger points to the plugin object:
#10031

...resolvedConfig.worker
.getSortedPluginHooks('configResolved')
.map((hook) => hook(workerResolved))
])

// validate config

Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/index.ts
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
@@ -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