unjs / unplugin

Unified plugin system for Vite, Rollup, Webpack, esbuild, Rolldown, and more

Home Page:https://unplugin.unjs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

A seemingly feasible solution (webpack external module)

xxXyh1908 opened this issue · comments

A seemingly feasible solution (webpack external module)

async function handleResolveId(resolveData, callback) {
  let id, external = false

  // do resolveId =============================================
  let resolveIdResult = await resolveId(
    resolveData.request,
    webpackResourceToVirtualId(resolveData.contextInfo?.issuer)
  )
  if (typeof resolveIdResult === 'string') {
    id = resolveIdResult
  } else if (resolveIdResult) {
    id = resolveIdResult.id
    external = resolveIdResult.external
  }
  // ==========================================================

  if (id) {
    if (external) {
      // Redirect the original request to the external module
      resolveData.request = id

      // Generate external modules and return
      return callback(null, new ExternalModule(id, 'commonjs2' /* module type */, id))
    }

    // Convert to the id (absolute path) recognized by webpack
    let resource = virtualIdToWebpackResource(id)

    // Redirect the original request to the resolved resource
    resolveData.request = resource

    // Write module code to `webpack-virtual-modules`
    vfs.writeModule(resource, loadedCode)
  }
}

compiler.hooks.normalModuleFactory.tap('name', (normalModuleFactory) => {
  if (normalModuleFactory.hooks.resolve) {
    // webpack5
    normalModuleFactory.hooks.resolve.tapAsync('name', async (resolveData, callback) => {
      let isCallbackCalled = false

      await handleResolveId(resolveData, (...args) => {
        isCallbackCalled = true
        callback(...args)
      })

      if (!isCallbackCalled) {
        callback(null)
      }
    })
  } else {
    // webpack4

    // Function for generating modules from resolveData
    const oldFactory = normalModuleFactory.hooks.factory.call(null)

    // Override factory
    normalModuleFactory.hooks.factory.tap('name', () => async (resolveData, callback) => {
      let isCallbackCalled = false

      await handleResolveId(resolveData, (...args) => {
        isCallbackCalled = true
        callback(...args)
      })

      if (!isCallbackCalled) {
        oldFactory(resolveData, callback)
      }
    })
  }
})