From 3b3d2893c58115de65606ffc508fdc7a9cf96f79 Mon Sep 17 00:00:00 2001 From: meteorlxy Date: Mon, 10 May 2021 00:58:25 +0800 Subject: [PATCH] feat(core): allow alias and define hook to return a promise simplify plugin api: - only support processing hooks asynchronously - only support processing hooks in serial --- .../bundler-vite/src/plugin/createPlugin.ts | 6 +- .../bundler-vite/src/plugin/resolveAlias.ts | 8 ++- .../bundler-vite/src/plugin/resolveDefine.ts | 6 +- .../bundler-webpack/src/build/createBuild.ts | 4 +- .../src/build/createClientConfig.ts | 6 +- .../src/build/createServerConfig.ts | 6 +- .../src/config/createBaseConfig.ts | 8 +-- .../src/config/createClientBaseConfig.ts | 6 +- .../src/config/handlePluginDefine.ts | 6 +- .../src/config/handleResolve.ts | 6 +- .../bundler-webpack/src/dev/createDev.ts | 2 +- .../src/dev/createDevConfig.ts | 6 +- .../normalizeReturnObjectHook.spec.ts | 8 +-- .../core/src/pluginApi/createHookQueue.ts | 69 ++----------------- .../src/pluginApi/createPluginApiHooks.ts | 9 +-- .../pluginApi/normalizeReturnObjectHook.ts | 2 +- .../core/src/types/pluginApi/hooks.ts | 5 +- 17 files changed, 51 insertions(+), 112 deletions(-) diff --git a/packages/@vuepress/bundler-vite/src/plugin/createPlugin.ts b/packages/@vuepress/bundler-vite/src/plugin/createPlugin.ts index 891ed19c2d..52cf68279a 100644 --- a/packages/@vuepress/bundler-vite/src/plugin/createPlugin.ts +++ b/packages/@vuepress/bundler-vite/src/plugin/createPlugin.ts @@ -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, diff --git a/packages/@vuepress/bundler-vite/src/plugin/resolveAlias.ts b/packages/@vuepress/bundler-vite/src/plugin/resolveAlias.ts index 25221129b2..92a5cfbf11 100644 --- a/packages/@vuepress/bundler-vite/src/plugin/resolveAlias.ts +++ b/packages/@vuepress/bundler-vite/src/plugin/resolveAlias.ts @@ -1,7 +1,11 @@ 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 => { const alias: AliasOptions = { '@internal': app.dir.temp('internal'), '@temp': app.dir.temp(), @@ -9,7 +13,7 @@ export const resolveAlias = ({ app }: { app: App }): AliasOptions => { } // 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]) => { diff --git a/packages/@vuepress/bundler-vite/src/plugin/resolveDefine.ts b/packages/@vuepress/bundler-vite/src/plugin/resolveDefine.ts index 585119f493..9411a45120 100644 --- a/packages/@vuepress/bundler-vite/src/plugin/resolveDefine.ts +++ b/packages/@vuepress/bundler-vite/src/plugin/resolveDefine.ts @@ -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 => { const define: UserConfig['define'] = { __VERSION__: JSON.stringify(app.version), __DEV__: JSON.stringify(app.env.isDev), @@ -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]) => { diff --git a/packages/@vuepress/bundler-webpack/src/build/createBuild.ts b/packages/@vuepress/bundler-webpack/src/build/createBuild.ts index 844dc259e7..264178a603 100644 --- a/packages/@vuepress/bundler-webpack/src/build/createBuild.ts +++ b/packages/@vuepress/bundler-webpack/src/build/createBuild.ts @@ -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, diff --git a/packages/@vuepress/bundler-webpack/src/build/createClientConfig.ts b/packages/@vuepress/bundler-webpack/src/build/createClientConfig.ts index 98d99262c7..130d13daaa 100644 --- a/packages/@vuepress/bundler-webpack/src/build/createClientConfig.ts +++ b/packages/@vuepress/bundler-webpack/src/build/createClientConfig.ts @@ -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 => { + const config = await createClientBaseConfig({ app, options, isBuild: true, diff --git a/packages/@vuepress/bundler-webpack/src/build/createServerConfig.ts b/packages/@vuepress/bundler-webpack/src/build/createServerConfig.ts index 1e3eadaf06..b72897c0e2 100644 --- a/packages/@vuepress/bundler-webpack/src/build/createServerConfig.ts +++ b/packages/@vuepress/bundler-webpack/src/build/createServerConfig.ts @@ -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 => { const isServer = true const isBuild = true - const config = createBaseConfig({ + const config = await createBaseConfig({ app, options, isServer, diff --git a/packages/@vuepress/bundler-webpack/src/config/createBaseConfig.ts b/packages/@vuepress/bundler-webpack/src/config/createBaseConfig.ts index 57dd734569..18cd24a5b6 100644 --- a/packages/@vuepress/bundler-webpack/src/config/createBaseConfig.ts +++ b/packages/@vuepress/bundler-webpack/src/config/createBaseConfig.ts @@ -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, @@ -20,7 +20,7 @@ export const createBaseConfig = ({ options: WebpackBundlerOptions isServer: boolean isBuild: boolean -}): Config => { +}): Promise => { // create new webpack-chain config const config = new Config() @@ -47,7 +47,7 @@ export const createBaseConfig = ({ /** * resolve */ - handleResolve({ app, config }) + await handleResolve({ app, config }) /** * module @@ -57,7 +57,7 @@ export const createBaseConfig = ({ /** * plugins */ - handlePluginDefine({ app, config, isServer }) + await handlePluginDefine({ app, config, isServer }) /** * other options diff --git a/packages/@vuepress/bundler-webpack/src/config/createClientBaseConfig.ts b/packages/@vuepress/bundler-webpack/src/config/createClientBaseConfig.ts index 6d67e4ae1e..25c6de72ae 100644 --- a/packages/@vuepress/bundler-webpack/src/config/createClientBaseConfig.ts +++ b/packages/@vuepress/bundler-webpack/src/config/createClientBaseConfig.ts @@ -3,7 +3,7 @@ import { App } from '@vuepress/core' import type { WebpackBundlerOptions } from '../types' import { createBaseConfig } from './createBaseConfig' -export const createClientBaseConfig = ({ +export const createClientBaseConfig = async ({ app, options, isBuild, @@ -11,8 +11,8 @@ export const createClientBaseConfig = ({ app: App options: WebpackBundlerOptions isBuild: boolean -}): Config => { - const config = createBaseConfig({ +}): Promise => { + const config = await createBaseConfig({ app, options, isServer: false, diff --git a/packages/@vuepress/bundler-webpack/src/config/handlePluginDefine.ts b/packages/@vuepress/bundler-webpack/src/config/handlePluginDefine.ts index 1a6a280ad8..3118b0d37a 100644 --- a/packages/@vuepress/bundler-webpack/src/config/handlePluginDefine.ts +++ b/packages/@vuepress/bundler-webpack/src/config/handlePluginDefine.ts @@ -5,7 +5,7 @@ import type { App } from '@vuepress/core' /** * Set webpack DefinePlugin */ -export const handlePluginDefine = ({ +export const handlePluginDefine = async ({ app, config, isServer, @@ -13,7 +13,7 @@ export const handlePluginDefine = ({ app: App config: Config isServer: boolean -}): void => { +}): Promise => { // define plugin config.plugin('define').use(DefinePlugin, [ { @@ -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]) => { diff --git a/packages/@vuepress/bundler-webpack/src/config/handleResolve.ts b/packages/@vuepress/bundler-webpack/src/config/handleResolve.ts index 0a4503bc72..316c9b5c33 100644 --- a/packages/@vuepress/bundler-webpack/src/config/handleResolve.ts +++ b/packages/@vuepress/bundler-webpack/src/config/handleResolve.ts @@ -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 => { // aliases config.resolve.alias .set('@source', app.dir.source()) @@ -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) => diff --git a/packages/@vuepress/bundler-webpack/src/dev/createDev.ts b/packages/@vuepress/bundler-webpack/src/dev/createDev.ts index c8674e7010..83d134dc5f 100644 --- a/packages/@vuepress/bundler-webpack/src/dev/createDev.ts +++ b/packages/@vuepress/bundler-webpack/src/dev/createDev.ts @@ -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, diff --git a/packages/@vuepress/bundler-webpack/src/dev/createDevConfig.ts b/packages/@vuepress/bundler-webpack/src/dev/createDevConfig.ts index 892f36d27b..7f749e17dc 100644 --- a/packages/@vuepress/bundler-webpack/src/dev/createDevConfig.ts +++ b/packages/@vuepress/bundler-webpack/src/dev/createDevConfig.ts @@ -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 => { + const config = await createClientBaseConfig({ app, options, isBuild: false, diff --git a/packages/@vuepress/core/__tests__/pluginApi/normalizeReturnObjectHook.spec.ts b/packages/@vuepress/core/__tests__/pluginApi/normalizeReturnObjectHook.spec.ts index d6f7cdab04..c35257c66d 100644 --- a/packages/@vuepress/core/__tests__/pluginApi/normalizeReturnObjectHook.spec.ts +++ b/packages/@vuepress/core/__tests__/pluginApi/normalizeReturnObjectHook.spec.ts @@ -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' }) }) }) diff --git a/packages/@vuepress/core/src/pluginApi/createHookQueue.ts b/packages/@vuepress/core/src/pluginApi/createHookQueue.ts index d75758d363..62810a0f95 100644 --- a/packages/@vuepress/core/src/pluginApi/createHookQueue.ts +++ b/packages/@vuepress/core/src/pluginApi/createHookQueue.ts @@ -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 = ( - name: T, - parallel = false -): HookQueue => { +export const createHookQueue = (name: T): HookQueue => { const items: HookItem[] = [] const hookQueue: HookQueue = { - // 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, - ...args: Parameters - ): Promise => { + // process all hook items + for (const item of items) { log( `process ${chalk.magenta(name)} from ${chalk.magenta( item.pluginName @@ -63,50 +46,6 @@ export const createHookQueue = ( } } - // 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 }, } diff --git a/packages/@vuepress/core/src/pluginApi/createPluginApiHooks.ts b/packages/@vuepress/core/src/pluginApi/createPluginApiHooks.ts index 1422ff4a70..ff0f8db8cb 100644 --- a/packages/@vuepress/core/src/pluginApi/createPluginApiHooks.ts +++ b/packages/@vuepress/core/src/pluginApi/createPluginApiHooks.ts @@ -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'), diff --git a/packages/@vuepress/core/src/pluginApi/normalizeReturnObjectHook.ts b/packages/@vuepress/core/src/pluginApi/normalizeReturnObjectHook.ts index 6a90f04459..e3f4f70147 100644 --- a/packages/@vuepress/core/src/pluginApi/normalizeReturnObjectHook.ts +++ b/packages/@vuepress/core/src/pluginApi/normalizeReturnObjectHook.ts @@ -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 diff --git a/packages/@vuepress/core/src/types/pluginApi/hooks.ts b/packages/@vuepress/core/src/types/pluginApi/hooks.ts index 003a1605bf..89105d36fd 100644 --- a/packages/@vuepress/core/src/types/pluginApi/hooks.ts +++ b/packages/@vuepress/core/src/types/pluginApi/hooks.ts @@ -34,8 +34,8 @@ export type ClientFilesHook = Hook< // hook that returns an object export type ReturnObjectHook = Hook< - Record | ((app: App) => Record), - (app: App) => Record + Record | ((app: App) => PromiseOrNot>), + (app: App) => Promise> > // markdown hook @@ -115,5 +115,4 @@ export interface HookQueue { process: ( ...args: Parameters ) => Promise - processSync: (...args: Parameters) => HooksResult[T][] }