From 636de4a629aaed4b19626f7b11019595eba4d682 Mon Sep 17 00:00:00 2001 From: Gengkun Date: Wed, 11 Sep 2024 09:46:51 +0800 Subject: [PATCH] fix(rspack): match resource for virtual module (#416) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: match resource for virtual module * fix cr * lint * Delete .virtual/external-module --------- Co-authored-by: Kevin Deng 三咲智子 --- src/rspack/index.ts | 40 +++++++++++++++++----------------------- src/rspack/utils.ts | 34 ++++++++++++++++++++++++++++++---- src/rspack/virtual.js | 2 -- tsup.config.ts | 9 --------- 4 files changed, 47 insertions(+), 38 deletions(-) delete mode 100644 src/rspack/virtual.js diff --git a/src/rspack/index.ts b/src/rspack/index.ts index b4043f9e..6be133f6 100644 --- a/src/rspack/index.ts +++ b/src/rspack/index.ts @@ -10,7 +10,7 @@ import type { UnpluginInstance, } from '../types' import { createBuildContext, normalizeMessage } from './context' -import { decodeVirtualModuleId, encodeVirtualModuleId } from './utils' +import { FakeVirtualModulesPlugin, decodeVirtualModuleId, encodeVirtualModuleId, isVirtualModuleId } from './utils' const TRANSFORM_LOADER = resolve( __dirname, @@ -22,16 +22,16 @@ const LOAD_LOADER = resolve( __DEV__ ? '../../dist/rspack/loaders/load.js' : 'rspack/loaders/load', ) -const VIRTUAL_MODULE_PATH = resolve(__dirname, __DEV__ ? '../../dist/rspack/virtual.js' : 'rspack/virtual.js') -const VIRTUAL_MODULE_QUERY_PREFIX = '?unplugin_rspack_virtual=' -const VIRTUAL_MODULE_PREFIX = VIRTUAL_MODULE_PATH + VIRTUAL_MODULE_QUERY_PREFIX - export function getRspackPlugin>( factory: UnpluginFactory, ): UnpluginInstance['rspack'] { return (userOptions?: UserOptions): RspackPluginInstance => { return { apply(compiler) { + // We need the prefix of virtual modules to be an absolute path so rspack let's us load them (even if it's made up) + // In the loader we strip the made up prefix path again + const VIRTUAL_MODULE_PREFIX = resolve(compiler.options.context ?? process.cwd(), 'node_modules/.virtual') + const injected = compiler.$unpluginContext || {} compiler.$unpluginContext = injected @@ -66,6 +66,10 @@ export function getRspackPlugin>( // resolveId hook if (plugin.resolveId) { + const vfs = new FakeVirtualModulesPlugin(plugin) + vfs.apply(compiler) + plugin.__vfsModules = new Set() + compiler.hooks.compilation.tap(plugin.name, (compilation, { normalModuleFactory }) => { normalModuleFactory.hooks.resolve.tapPromise(plugin.name, async (resolveData) => { const id = normalizeAbsolutePath(resolveData.request) @@ -102,8 +106,13 @@ export function getRspackPlugin>( // If the resolved module does not exist, // we treat it as a virtual module - if (!fs.existsSync(resolved)) + if (!fs.existsSync(resolved)) { + if (!plugin.__vfsModules!.has(resolved)) { + plugin.__vfsModules!.add(resolved) + await vfs.writeModule(resolved) + } resolved = encodeVirtualModuleId(resolved, plugin) + } resolveData.request = resolved }) @@ -115,23 +124,8 @@ export function getRspackPlugin>( compiler.options.module.rules.unshift({ enforce: plugin.enforce, include(id) { - // always return true for virtual module, filter it in resourceQuery - if (id === VIRTUAL_MODULE_PATH) - return true - - // load include filter - if (plugin.loadInclude && !plugin.loadInclude(id)) - return false - - // Don't run load hook for external modules - return !externalModules.has(id) - }, - resourceQuery(query) { - if (!query.startsWith(VIRTUAL_MODULE_QUERY_PREFIX)) - return true - - // filter the decoded virtual module id - const id = decodeVirtualModuleId(VIRTUAL_MODULE_PATH + query, plugin) + if (isVirtualModuleId(id, plugin)) + id = decodeVirtualModuleId(id, plugin) // load include filter if (plugin.loadInclude && !plugin.loadInclude(id)) diff --git a/src/rspack/utils.ts b/src/rspack/utils.ts index 69a560f5..96c89dd1 100644 --- a/src/rspack/utils.ts +++ b/src/rspack/utils.ts @@ -1,13 +1,39 @@ +import fs from 'fs' +import { basename, dirname, resolve } from 'path' +import type { Compiler } from '@rspack/core' import type { ResolvedUnpluginOptions } from '../types' export function encodeVirtualModuleId(id: string, plugin: ResolvedUnpluginOptions): string { - return plugin.__virtualModulePrefix + encodeURIComponent(id) + return resolve(plugin.__virtualModulePrefix, encodeURIComponent(id)) } -export function decodeVirtualModuleId(encoded: string, plugin: ResolvedUnpluginOptions): string { - return decodeURIComponent(encoded.slice(plugin.__virtualModulePrefix.length)) +export function decodeVirtualModuleId(encoded: string, _plugin: ResolvedUnpluginOptions): string { + return decodeURIComponent(basename(encoded)) } export function isVirtualModuleId(encoded: string, plugin: ResolvedUnpluginOptions): boolean { - return encoded.startsWith(plugin.__virtualModulePrefix) + return dirname(encoded) === plugin.__virtualModulePrefix +} + +export class FakeVirtualModulesPlugin { + name = 'FakeVirtualModulesPlugin' + constructor(private plugin: ResolvedUnpluginOptions) {} + + apply(compiler: Compiler) { + const dir = this.plugin.__virtualModulePrefix + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }) + } + compiler.hooks.shutdown.tap(this.name, () => { + if (fs.existsSync(dir)) { + fs.rmdirSync(dir, { recursive: true }) + } + }) + } + + async writeModule(file: string) { + const path = encodeVirtualModuleId(file, this.plugin) + await fs.promises.writeFile(path, '') + return path + } } diff --git a/src/rspack/virtual.js b/src/rspack/virtual.js deleted file mode 100644 index 34b34c72..00000000 --- a/src/rspack/virtual.js +++ /dev/null @@ -1,2 +0,0 @@ -// The placeholder module for the virtual module. -// The resourceQuery of this module contains the id of the virtual module. diff --git a/tsup.config.ts b/tsup.config.ts index a1cff855..5e6185ed 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,5 +1,4 @@ import type { Options } from 'tsup' -import { copy } from 'esbuild-plugin-copy' import Unused from 'unplugin-unused/esbuild' export const tsup: Options = { @@ -26,14 +25,6 @@ export const tsup: Options = { __DEV__: 'false', }, esbuildPlugins: [ - copy({ - assets: [ - { - from: ['./src/rspack/virtual.js'], - to: ['./rspack/virtual.js'], - }, - ], - }), Unused({ level: 'error' }), ], }