Skip to content

Commit

Permalink
feat(core): allow alias and define hook to return a promise
Browse files Browse the repository at this point in the history
simplify plugin api:
- only support processing hooks asynchronously
- only support processing hooks in serial
  • Loading branch information
meteorlxy committed May 9, 2021
1 parent fd9d29d commit 3b3d289
Show file tree
Hide file tree
Showing 17 changed files with 51 additions and 112 deletions.
6 changes: 3 additions & 3 deletions packages/@vuepress/bundler-vite/src/plugin/createPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ export const createPlugin = ({
{
name: 'vuepress',

config: () => ({
config: async () => ({
root: app.dir.source(),
base: app.options.base,
mode: isBuild ? 'production' : 'development',
define: resolveDefine({ app, isServer }),
define: await resolveDefine({ app, isServer }),
publicDir: app.dir.public(),
cacheDir: app.dir.cache(),
resolve: {
alias: resolveAlias({ app }),
alias: await resolveAlias({ app }),
},
server: {
host: app.options.host,
Expand Down
8 changes: 6 additions & 2 deletions packages/@vuepress/bundler-vite/src/plugin/resolveAlias.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import type { AliasOptions } from 'vite'
import type { App } from '@vuepress/core'

export const resolveAlias = ({ app }: { app: App }): AliasOptions => {
export const resolveAlias = async ({
app,
}: {
app: App
}): Promise<AliasOptions> => {
const alias: AliasOptions = {
'@internal': app.dir.temp('internal'),
'@temp': app.dir.temp(),
'@source': app.dir.source(),
}

// plugin hook: alias
const aliasResult = app.pluginApi.hooks.alias.processSync(app)
const aliasResult = await app.pluginApi.hooks.alias.process(app)

aliasResult.forEach((aliasObject) =>
Object.entries(aliasObject).forEach(([key, value]) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/@vuepress/bundler-vite/src/plugin/resolveDefine.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { UserConfig } from 'vite'
import type { App } from '@vuepress/core'

export const resolveDefine = ({
export const resolveDefine = async ({
app,
isServer,
}: {
app: App
isServer: boolean
}): UserConfig['define'] => {
}): Promise<UserConfig['define']> => {
const define: UserConfig['define'] = {
__VERSION__: JSON.stringify(app.version),
__DEV__: JSON.stringify(app.env.isDev),
Expand All @@ -19,7 +19,7 @@ export const resolveDefine = ({
}

// plugin hook: define
const defineResult = app.pluginApi.hooks.define.processSync(app)
const defineResult = await app.pluginApi.hooks.define.process(app)

defineResult.forEach((defineObject) =>
Object.entries(defineObject).forEach(([key, value]) => {
Expand Down
4 changes: 2 additions & 2 deletions packages/@vuepress/bundler-webpack/src/build/createBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ export const createBuild = (
await withSpinner('Compiling with webpack')(async () => {
// create webpack config
const clientConfig = resolveWebpackConfig({
config: createClientConfig(app, options),
config: await createClientConfig(app, options),
options,
isServer: false,
isBuild: true,
})
const serverConfig = resolveWebpackConfig({
config: createServerConfig(app, options),
config: await createServerConfig(app, options),
options,
isServer: true,
isBuild: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import { createClientPlugin } from './ssr'
*/
export const clientManifestFilename = '.server/client-manifest.json'

export const createClientConfig = (
export const createClientConfig = async (
app: App,
options: WebpackBundlerOptions
): Config => {
const config = createClientBaseConfig({
): Promise<Config> => {
const config = await createClientBaseConfig({
app,
options,
isBuild: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import type { App } from '@vuepress/core'
import { createBaseConfig } from '../config'
import type { WebpackBundlerOptions } from '../types'

export const createServerConfig = (
export const createServerConfig = async (
app: App,
options: WebpackBundlerOptions
): Config => {
): Promise<Config> => {
const isServer = true
const isBuild = true

const config = createBaseConfig({
const config = await createBaseConfig({
app,
options,
isServer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { handleOtherOptions } from './handleOtherOptions'
import { handlePluginDefine } from './handlePluginDefine'
import { handleResolve } from './handleResolve'

export const createBaseConfig = ({
export const createBaseConfig = async ({
app,
options,
isServer,
Expand All @@ -20,7 +20,7 @@ export const createBaseConfig = ({
options: WebpackBundlerOptions
isServer: boolean
isBuild: boolean
}): Config => {
}): Promise<Config> => {
// create new webpack-chain config
const config = new Config()

Expand All @@ -47,7 +47,7 @@ export const createBaseConfig = ({
/**
* resolve
*/
handleResolve({ app, config })
await handleResolve({ app, config })

/**
* module
Expand All @@ -57,7 +57,7 @@ export const createBaseConfig = ({
/**
* plugins
*/
handlePluginDefine({ app, config, isServer })
await handlePluginDefine({ app, config, isServer })

/**
* other options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import { App } from '@vuepress/core'
import type { WebpackBundlerOptions } from '../types'
import { createBaseConfig } from './createBaseConfig'

export const createClientBaseConfig = ({
export const createClientBaseConfig = async ({
app,
options,
isBuild,
}: {
app: App
options: WebpackBundlerOptions
isBuild: boolean
}): Config => {
const config = createBaseConfig({
}): Promise<Config> => {
const config = await createBaseConfig({
app,
options,
isServer: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import type { App } from '@vuepress/core'
/**
* Set webpack DefinePlugin
*/
export const handlePluginDefine = ({
export const handlePluginDefine = async ({
app,
config,
isServer,
}: {
app: App
config: Config
isServer: boolean
}): void => {
}): Promise<void> => {
// define plugin
config.plugin('define').use(DefinePlugin, [
{
Expand All @@ -29,7 +29,7 @@ export const handlePluginDefine = ({
])

// plugin hook: define
const defineResult = app.pluginApi.hooks.define.processSync(app)
const defineResult = await app.pluginApi.hooks.define.process(app)

// tap the arguments of DefinePlugin
config.plugin('define').tap(([options]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import type { App } from '@vuepress/core'
/**
* Set webpack resolve
*/
export const handleResolve = ({
export const handleResolve = async ({
app,
config,
}: {
app: App
config: Config
}): void => {
}): Promise<void> => {
// aliases
config.resolve.alias
.set('@source', app.dir.source())
Expand All @@ -28,7 +28,7 @@ export const handleResolve = ({
])

// plugin hook: alias
const aliasResult = app.pluginApi.hooks.alias.processSync(app)
const aliasResult = await app.pluginApi.hooks.alias.process(app)

// set aliases
aliasResult.forEach((aliasObject) =>
Expand Down
2 changes: 1 addition & 1 deletion packages/@vuepress/bundler-webpack/src/dev/createDev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const createDev = (options: WebpackBundlerOptions): BundlerDev => async (
const port = await resolvePort(app.options.port)

// create webpack config
const config = createDevConfig(app, options)
const config = await createDevConfig(app, options)
const webpackConfig = resolveWebpackConfig({
config,
options,
Expand Down
6 changes: 3 additions & 3 deletions packages/@vuepress/bundler-webpack/src/dev/createDevConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { App } from '@vuepress/core'
import { createClientBaseConfig } from '../config'
import type { WebpackBundlerOptions } from '../types'

export const createDevConfig = (
export const createDevConfig = async (
app: App,
options: WebpackBundlerOptions
): Config => {
const config = createClientBaseConfig({
): Promise<Config> => {
const config = await createClientBaseConfig({
app,
options,
isBuild: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ const app = createApp({
})

describe('core > pluginApi > normalizeReturnObjectHook', () => {
it('should keep function as is', () => {
it('should keep function as is', async () => {
const rawHook: ReturnObjectHook['exposed'] = jest.fn((app) => ({
foo: 'bar',
}))
const normalizedHook = normalizeReturnObjectHook(rawHook)
expect(normalizedHook(app)).toEqual({ foo: 'bar' })
expect(await normalizedHook(app)).toEqual({ foo: 'bar' })
expect(rawHook).toHaveBeenCalledTimes(1)
expect(rawHook).toHaveBeenCalledWith(app)
})

it('should wrap object with a function', () => {
it('should wrap object with a function', async () => {
const rawHook: ReturnObjectHook['exposed'] = {
foo: 'bar',
}
const normalizedHook = normalizeReturnObjectHook(rawHook)
expect(normalizedHook(app)).toEqual({ foo: 'bar' })
expect(await normalizedHook(app)).toEqual({ foo: 'bar' })
})
})
69 changes: 4 additions & 65 deletions packages/@vuepress/core/src/pluginApi/createHookQueue.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,26 @@
import { isPromise } from '@vuepress/shared'
import { chalk, debug, logger } from '@vuepress/utils'
import type {
HookQueue,
HookItem,
HooksName,
HooksNormalized,
HooksResult,
} from '../types'
import type { HookQueue, HookItem, HooksName, HooksResult } from '../types'

const log = debug('vuepress:core/plugin-api')

/**
* Create hook queue for plugin system
*/
export const createHookQueue = <T extends HooksName>(
name: T,
parallel = false
): HookQueue<T> => {
export const createHookQueue = <T extends HooksName>(name: T): HookQueue<T> => {
const items: HookItem<T>[] = []

const hookQueue: HookQueue<T> = {
// hook name
name,
// hook items array
items,
// add hook item to queue
add: (item) => {
items.push(item)
},
// process the hook queue and get the results
process: async (...args) => {
// store the results of all hook items
const results: HooksResult[T][] = []

// process a hook item and store the result
const processItem = async (
item: HookItem<T>,
...args: Parameters<HooksNormalized[T]>
): Promise<void> => {
// process all hook items
for (const item of items) {
log(
`process ${chalk.magenta(name)} from ${chalk.magenta(
item.pluginName
Expand All @@ -63,50 +46,6 @@ export const createHookQueue = <T extends HooksName>(
}
}

// process all hook items in current queue
if (parallel) {
// process in parallel
await Promise.all(items.map((item) => processItem(item, ...args)))
} else {
// process in serial
for (const item of items) {
await processItem(item, ...args)
}
}

return results
},
// process the hook queue and get the results
processSync: (...args) => {
// store the results of all hook items
const results: HooksResult[T][] = []

// process all hook items
for (const item of items) {
log(
`processSync ${chalk.magenta(name)} from ${chalk.magenta(
item.pluginName
)}`
)

try {
// @ts-ignore
// process and get the result of the the hook item
const result = item.hook(...args) as HooksResult[T]

// push the result to results array
if (result !== undefined && !isPromise(result)) {
results.push(result)
}
} catch (error) {
logger.error(
`error in hook ${chalk.magenta(name)} from ${chalk.magenta(
item.pluginName
)}`
)
throw error
}
}
return results
},
}
Expand Down
9 changes: 3 additions & 6 deletions packages/@vuepress/core/src/pluginApi/createPluginApiHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@ export const createPluginApiHooks = (): PluginApi['hooks'] => ({
extendsMarkdown: createHookQueue('extendsMarkdown'),

// client files hooks
clientAppEnhanceFiles: createHookQueue('clientAppEnhanceFiles', true),
clientAppRootComponentFiles: createHookQueue(
'clientAppRootComponentFiles',
true
),
clientAppSetupFiles: createHookQueue('clientAppSetupFiles', true),
clientAppEnhanceFiles: createHookQueue('clientAppEnhanceFiles'),
clientAppRootComponentFiles: createHookQueue('clientAppRootComponentFiles'),
clientAppSetupFiles: createHookQueue('clientAppSetupFiles'),

// bundler hooks
alias: createHookQueue('alias'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import type { ReturnObjectHook } from '../types'
*/
export const normalizeReturnObjectHook = (
hook: ReturnObjectHook['exposed']
): ReturnObjectHook['normalized'] => (app) =>
): ReturnObjectHook['normalized'] => async (app) =>
isFunction(hook) ? hook(app) : hook
Loading

0 comments on commit 3b3d289

Please sign in to comment.