Skip to content

Commit

Permalink
feat: expose native build context (#404)
Browse files Browse the repository at this point in the history
* Allow access to rspack and webpack LoaderContext in the UnpluginBuildContext that is available in the load and transform hooks

* refactor

* fix: no native context for vite and roll{up,down}

---------

Co-authored-by: 三咲智子 Kevin Deng <[email protected]>
  • Loading branch information
urbnjamesmi1 and sxzz authored Sep 9, 2024
1 parent 15c1882 commit 1d1e064
Show file tree
Hide file tree
Showing 14 changed files with 77 additions and 71 deletions.
9 changes: 4 additions & 5 deletions src/esbuild/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,15 @@ export function getEsbuildPlugin<UserOptions = Record<string, never>>(

function buildSetup(meta: UnpluginContextMeta & { framework: 'esbuild' }) {
return (plugin: UnpluginOptions): EsbuildPlugin['setup'] => {
return (build) => {
meta.build = build as EsbuildPluginBuild
const { onStart, onEnd, onResolve, onLoad, onTransform, initialOptions }
= build as EsbuildPluginBuild
return (_build) => {
const build = meta.build = _build as EsbuildPluginBuild
const context = createBuildContext(build)
const { onStart, onEnd, onResolve, onLoad, onTransform, initialOptions } = build

const onResolveFilter = plugin.esbuild?.onResolveFilter ?? /.*/
const onLoadFilter = plugin.esbuild?.onLoadFilter ?? /.*/

const loader = plugin.esbuild?.loader ?? guessLoader
const context = createBuildContext(initialOptions)

if (plugin.esbuild?.config)
plugin.esbuild.config.call(context, initialOptions)
Expand Down
10 changes: 7 additions & 3 deletions src/esbuild/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { Buffer } from 'buffer'
import remapping from '@ampproject/remapping'
import { Parser } from 'acorn'
import type { DecodedSourceMap, EncodedSourceMap } from '@ampproject/remapping'
import type { BuildOptions, Loader, Location, Message, PartialMessage } from 'esbuild'
import type { Loader, Location, Message, PartialMessage } from 'esbuild'
import type { SourceMap } from 'rollup'
import type { UnpluginBuildContext, UnpluginContext, UnpluginMessage } from '../types'
import type { EsbuildPluginBuild } from '.'

export * from '../utils'

Expand Down Expand Up @@ -111,9 +112,9 @@ export function combineSourcemaps(
return map as EncodedSourceMap
}

export function createBuildContext(initialOptions: BuildOptions): UnpluginBuildContext {
export function createBuildContext(build: EsbuildPluginBuild): UnpluginBuildContext {
const watchFiles: string[] = []

const { initialOptions } = build
return {
parse(code: string, opts: any = {}) {
return Parser.parse(code, {
Expand All @@ -140,6 +141,9 @@ export function createBuildContext(initialOptions: BuildOptions): UnpluginBuildC
getWatchFiles() {
return watchFiles
},
getNativeBuildContext() {
return { framework: 'esbuild', build }
},
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/farm/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export function createFarmContext(
getWatchFiles() {
return context.getWatchFiles()
},
getNativeBuildContext() {
return { framework: 'farm', context }
},
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/farm/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import path from 'path'

import type {
CompilationContext,
JsPlugin,
PluginLoadHookParam,
PluginLoadHookResult,
PluginResolveHookParam,
PluginTransformHookParam,
PluginTransformHookResult,
} from '@farmfe/core/binding'
import type { CompilationContext, JsPlugin } from '@farmfe/core'
} from '@farmfe/core'
import { toArray } from '../utils'
import type {
JsPluginExtended,
Expand Down
30 changes: 11 additions & 19 deletions src/rspack/context.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import { resolve } from 'path'
import { Buffer } from 'buffer'
import type { Compilation, LoaderContext } from '@rspack/core'
import type { Compilation, Compiler, LoaderContext } from '@rspack/core'
import { Parser } from 'acorn'
import type { UnpluginBuildContext, UnpluginContext, UnpluginMessage } from '../types'

interface ContextOptions {
addWatchFile: (file: string) => void
getWatchFiles: () => string[]
}

export function contextOptionsFromCompilation(compilation: Compilation): ContextOptions {
export function createBuildContext(compiler: Compiler, compilation: Compilation, loaderContext?: LoaderContext): UnpluginBuildContext {
return {
getNativeBuildContext() {
return {
framework: 'rspack',
compiler,
compilation,
loaderContext,
}
},
addWatchFile(file) {
compilation.fileDependencies.add(file)
compilation.fileDependencies.add(resolve(process.cwd(), file))
},
getWatchFiles() {
return Array.from(compilation.fileDependencies)
},
}
}

export function createBuildContext(options: ContextOptions, compilation: Compilation): UnpluginBuildContext {
return {
parse(code: string, opts: any = {}) {
return Parser.parse(code, {
sourceType: 'module',
Expand All @@ -30,9 +28,6 @@ export function createBuildContext(options: ContextOptions, compilation: Compila
...opts,
})
},
addWatchFile(id) {
options.addWatchFile(resolve(process.cwd(), id))
},
emitFile(emittedFile) {
const outFileName = emittedFile.fileName || emittedFile.name
if (emittedFile.source && outFileName) {
Expand All @@ -47,9 +42,6 @@ export function createBuildContext(options: ContextOptions, compilation: Compila
)
}
},
getWatchFiles() {
return options.getWatchFiles()
},
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/rspack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
UnpluginFactory,
UnpluginInstance,
} from '../types'
import { contextOptionsFromCompilation, createBuildContext, normalizeMessage } from './context'
import { createBuildContext, normalizeMessage } from './context'
import { decodeVirtualModuleId, encodeVirtualModuleId } from './utils'

const TRANSFORM_LOADER = resolve(
Expand Down Expand Up @@ -74,7 +74,7 @@ export function getRspackPlugin<UserOptions = Record<string, never>>(
const importer = requestContext.issuer !== '' ? requestContext.issuer : undefined
const isEntry = requestContext.issuer === ''

const context = createBuildContext(contextOptionsFromCompilation(compilation), compilation)
const context = createBuildContext(compiler, compilation)
let error: Error | undefined
const pluginContext: UnpluginContext = {
error(msg) {
Expand Down Expand Up @@ -165,7 +165,7 @@ export function getRspackPlugin<UserOptions = Record<string, never>>(

if (plugin.watchChange || plugin.buildStart) {
compiler.hooks.make.tapPromise(plugin.name, async (compilation) => {
const context = createBuildContext(contextOptionsFromCompilation(compilation), compilation)
const context = createBuildContext(compiler, compilation)
if (plugin.watchChange && (compiler.modifiedFiles || compiler.removedFiles)) {
const promises: Promise<void>[] = []
if (compiler.modifiedFiles) {
Expand All @@ -188,7 +188,7 @@ export function getRspackPlugin<UserOptions = Record<string, never>>(

if (plugin.buildEnd) {
compiler.hooks.emit.tapPromise(plugin.name, async (compilation) => {
await plugin.buildEnd!.call(createBuildContext(contextOptionsFromCompilation(compilation), compilation))
await plugin.buildEnd!.call(createBuildContext(compiler, compilation))
})
}

Expand Down
4 changes: 2 additions & 2 deletions src/rspack/loaders/load.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { LoaderContext } from '@rspack/core'
import { contextOptionsFromCompilation, createBuildContext, createContext } from '../context'
import { createBuildContext, createContext } from '../context'
import { normalizeAbsolutePath } from '../../utils'
import { decodeVirtualModuleId, isVirtualModuleId } from '../utils'

Expand All @@ -19,7 +19,7 @@ export default async function load(this: LoaderContext, source: string, map: any
const res = await plugin.load.call(
Object.assign(
{},
this._compilation && createBuildContext(contextOptionsFromCompilation(this._compilation), this._compilation),
this._compilation && createBuildContext(this._compiler, this._compilation, this),
context,
),
normalizeAbsolutePath(id),
Expand Down
4 changes: 2 additions & 2 deletions src/rspack/loaders/transform.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { LoaderContext } from '@rspack/core'
import { contextOptionsFromCompilation, createBuildContext, createContext } from '../context'
import { createBuildContext, createContext } from '../context'

export default async function transform(
this: LoaderContext,
Expand Down Expand Up @@ -27,7 +27,7 @@ export default async function transform(
const res = await plugin.transform.call(
Object.assign(
{},
this._compilation && createBuildContext(contextOptionsFromCompilation(this._compilation), this._compilation),
this._compilation && createBuildContext(this._compiler, this._compilation, this),
context,
),
source,
Expand Down
26 changes: 14 additions & 12 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { AstNode, EmittedAsset, PluginContextMeta as RollupContextMeta, Plugin as RollupPlugin, SourceMapInput } from 'rollup'
import type { Compiler as WebpackCompiler, WebpackPluginInstance } from 'webpack'
import type { Compilation as WebpackCompilation, Compiler as WebpackCompiler, LoaderContext as WebpackLoaderContext, WebpackPluginInstance } from 'webpack'
import type { Plugin as VitePlugin } from 'vite'
import type { Plugin as RolldownPlugin } from 'rolldown'
import type { BuildOptions, Plugin as EsbuildPlugin, Loader } from 'esbuild'
import type { Compiler as RspackCompiler, RspackPluginInstance } from '@rspack/core'
import type { Compilation as RspackCompilation, Compiler as RspackCompiler, LoaderContext as RspackLoaderContext, RspackPluginInstance } from '@rspack/core'
import type VirtualModulesPlugin from 'webpack-virtual-modules'
import type { JsPlugin as FarmPlugin } from '@farmfe/core'
import type { CompilationContext as FarmCompilationContext, JsPlugin as FarmPlugin } from '@farmfe/core'
import type { EsbuildPluginBuild } from './esbuild'

export {
Expand Down Expand Up @@ -40,11 +40,18 @@ export type TransformResult = string | { code: string, map?: SourceMapInput | So

export interface ExternalIdResult { id: string, external?: boolean }

export type NativeBuildContext =
{ framework: 'webpack', compiler: WebpackCompiler, compilation?: WebpackCompilation, loaderContext?: WebpackLoaderContext<{ unpluginName: string }> } |
{ framework: 'esbuild', build: EsbuildPluginBuild } |
{ framework: 'rspack', compiler: RspackCompiler, compilation: RspackCompilation, loaderContext?: RspackLoaderContext } |
{ framework: 'farm', context: FarmCompilationContext }

export interface UnpluginBuildContext {
addWatchFile: (id: string) => void
emitFile: (emittedFile: EmittedAsset) => void
getWatchFiles: () => string[]
parse: (input: string, options?: any) => AstNode
getNativeBuildContext?: () => NativeBuildContext
}

export interface UnpluginOptions {
Expand Down Expand Up @@ -117,24 +124,19 @@ export interface UnpluginInstance<UserOptions, Nested extends boolean = boolean>
}

export type UnpluginContextMeta = Partial<RollupContextMeta> & ({
framework: 'rollup' | 'vite' | 'rolldown'
framework: 'rollup' | 'vite' | 'rolldown' | 'farm'
} | {
framework: 'webpack'
webpack: {
compiler: WebpackCompiler
}
webpack: { compiler: WebpackCompiler }
} | {
framework: 'esbuild'
/** @deprecated {getNativeBuildContext} */
build?: EsbuildPluginBuild
/** Set the host plugin name of esbuild when returning multiple plugins */
esbuildHostName?: string
} | {
framework: 'rspack'
rspack: {
compiler: RspackCompiler
}
} | {
framework: 'farm'
rspack: { compiler: RspackCompiler }
})

export interface UnpluginMessage {
Expand Down
9 changes: 9 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,12 @@ export function transformUse(
}
return []
}

export function resolveQuery(query: string | { unpluginName: string }) {
if (typeof query === 'string') {
return new URLSearchParams(query).get('unpluginName')!
}
else {
return query.unpluginName
}
}
7 changes: 5 additions & 2 deletions src/webpack/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { resolve } from 'path'
import { Buffer } from 'buffer'
import process from 'process'
import { createRequire } from 'module'
import type { Compilation, LoaderContext } from 'webpack'
import type { Compilation, Compiler, LoaderContext } from 'webpack'
import { Parser } from 'acorn'
import type { UnpluginBuildContext, UnpluginContext, UnpluginMessage } from '../types'

Expand All @@ -22,7 +22,7 @@ export function contextOptionsFromCompilation(compilation: Compilation): Context
}
}

export function createBuildContext(options: ContextOptions, compilation?: Compilation): UnpluginBuildContext {
export function createBuildContext(options: ContextOptions, compiler: Compiler, compilation?: Compilation, loaderContext?: LoaderContext<{ unpluginName: string }>): UnpluginBuildContext {
const require = createRequire(import.meta.url)
const sources = require('webpack-sources') as typeof import('webpack-sources')

Expand Down Expand Up @@ -62,6 +62,9 @@ export function createBuildContext(options: ContextOptions, compilation?: Compil
getWatchFiles() {
return options.getWatchFiles()
},
getNativeBuildContext() {
return { framework: 'webpack', compiler, compilation, loaderContext }
},
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/webpack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export function getWebpackPlugin<UserOptions = Record<string, never>>(
getWatchFiles() {
return Array.from(fileDependencies)
},
})
}, compiler)
let error: Error | undefined
const pluginContext: UnpluginContext = {
error(msg) {
Expand Down Expand Up @@ -189,7 +189,7 @@ export function getWebpackPlugin<UserOptions = Record<string, never>>(

if (plugin.watchChange || plugin.buildStart) {
compiler.hooks.make.tapPromise(plugin.name, async (compilation) => {
const context = createBuildContext(contextOptionsFromCompilation(compilation), compilation)
const context = createBuildContext(contextOptionsFromCompilation(compilation), compiler, compilation)
if (plugin.watchChange && (compiler.modifiedFiles || compiler.removedFiles)) {
const promises: Promise<void>[] = []
if (compiler.modifiedFiles) {
Expand All @@ -212,7 +212,7 @@ export function getWebpackPlugin<UserOptions = Record<string, never>>(

if (plugin.buildEnd) {
compiler.hooks.emit.tapPromise(plugin.name, async (compilation) => {
await plugin.buildEnd!.call(createBuildContext(contextOptionsFromCompilation(compilation), compilation))
await plugin.buildEnd!.call(createBuildContext(contextOptionsFromCompilation(compilation), compiler, compilation))
})
}

Expand Down
11 changes: 6 additions & 5 deletions src/webpack/loaders/load.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { LoaderContext } from 'webpack'
import { createBuildContext, createContext } from '../context'
import { normalizeAbsolutePath } from '../../utils'
import { normalizeAbsolutePath, resolveQuery } from '../../utils'

export default async function load(this: LoaderContext<any>, source: string, map: any) {
export default async function load(this: LoaderContext<{ unpluginName: string }>, source: string, map: any) {
const callback = this.async()
const { unpluginName } = this.query

const unpluginName = resolveQuery(this.query)
const plugin = this._compiler?.$unpluginContext[unpluginName]
let id = this.resource

Expand All @@ -16,14 +17,14 @@ export default async function load(this: LoaderContext<any>, source: string, map

const context = createContext(this)
const res = await plugin.load.call(
{ ...createBuildContext({
Object.assign({}, createBuildContext({
addWatchFile: (file) => {
this.addDependency(file)
},
getWatchFiles: () => {
return this.getDependencies()
},
}, this._compilation), ...context },
}, this._compiler!, this._compilation, this), context),
normalizeAbsolutePath(id),
)

Expand Down
Loading

0 comments on commit 1d1e064

Please sign in to comment.