微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Webpack 5 文件阴影加载器

如何解决Webpack 5 文件阴影加载器

我们目前正在使用类似于 gatsby 文件阴影的文件阴影机制: https://www.gatsbyjs.com/docs/conceptual/how-shadowing-works/ 借助此解决方案,我们能够拥有一个 next.js 存储库,并为不同的客户及其自定义进行构建。

当我们尝试更新到 webpack 5 时,我们遇到了 2 个问题:

  1. 由于某些原因不再提供对影子文件文件监视
  2. 似乎必须提供序列化程序来正确缓存结果
[webpack.cache.PackFileCacheStrategy] Skipped not serializable cache item 'Compilation/modules|/Users/michaelkuczera/Projects/lyska/core-shop/node_modules/next/dist/build/babel/loader/index.js??ruleSet[1].rules[2].use!/Users/michaelkuczera/Projects/lyska/core-shop/src/core/config/config.helper.ts': No serializer registered for WebpackFileShadowPlugin

我尝试了不同的方法解决这个问题,但无法解决问题,我不知道这两个问题是否相关,我真的被卡住了。

我尝试制作自定义加载器,因为它看起来更准确。乍一看它运行良好,但由于它结束了以下文件结构:

  • 代码
  • 核心
    • 组件
  • 客户 1
    • 组件
    • 帮手

在这种情况下,客户端的被覆盖组件正在请求一个仅在其自己的客户端文件夹中可用的文件。加载程序实际上无法解析 ./helper

的导入

使用了以下加载器:

const path = require('path')
const fs = require('fs')
const loaderUtils = require('loader-utils')

module.exports = function(source) {
  const callback = this.async()

  const { layers } = loaderUtils.getoptions(this)

  ;(async () => {
    const [projectRoot,component] = this.resourcePath.split(
      path.join('src','core')
    )

    let overwritable
    let usedLayer

    layers.forEach(layer => {
      if (!component) {
        return
      }

      // construct layer path
      const possibleLayerPath = `${path.join(
        projectRoot,'src',layer,component
      )}`

      // check if file exists in customizations
      const exists = fs.existsSync(possibleLayerPath)

      if (exists) {
        overwritable = possibleLayerPath
        usedLayer = layer
      }
    })

    if (overwritable) {
      // output customization and add path to watchable files
      const data = fs.readFileSync(overwritable,'utf8')

      this.addDependency(overwritable)
      return data
    }

    return source
  })().then(
    res => callback(undefined,res),err => callback(err)
  )
}

有没有人想用插件或加载器解决问题?

我将不胜感激

插件代码

const fs = require('fs')
const path = require('path')
const checkPossibleComponentPath = require('./checkPossiblePath')

const pathWithoutExtension = fullPath => {
  const parsed = path.parse(fullPath)
  return path.join(parsed.dir,parsed.name)
}

module.exports = class WebpackFileShadowPlugin {
  constructor(layers) {
    this.layers = [...layers,'core']
  }

  apply(resolver) {
    const describedRelative = resolver.getHook('describedRelative')

    resolver
      .getHook('resolve')
      .tapAsync(
        'WebpackFileShadowPlugin',(request,resolveContext,callback) => {
          const requestedLayer = this.getMatchingLayerForPath(request.path)

          // requested file is not in a layer,and not shadowable
          if (!requestedLayer) {
            return callback()
          }

          // get the location of the component relative to `src/${layer}`
          const [projectRoot,component] = request.path.split(
            path.join('src',requestedLayer)
          )

          // If a shadowing file requests its original file,then let the request go through
          if (
            request.context.issuer &&
            this.requestPathIsIssuerShadowPath({
              component,requestPath: request.path,issuerPath: request.context.issuer,})
          ) {
            return resolver.doResolve(
              describedRelative,request,null,{},callback
            )
          }

          // Shadowing algorithm
          const componentPath = this.resolveComponentPath({
            projectRoot,component,})

          if (componentPath) {
            return resolver.doResolve(
              describedRelative,{ ...request,path: componentPath || request.path },callback
            )
          } else {
            return callback()
          }
        }
      )
  }

  getMatchingLayerForPath(filepath) {
    // find out which layer we're requiring from
    return this.layers.find(layer => filepath.includes(path.join('src',layer)))
  }

  requestPathIsIssuerShadowPath({ component,issuerPath }) {
    const issuerLayer = this.getMatchingLayerForPath(issuerPath)

    // Issuer is not a shadowable file
    if (!issuerLayer) return false

    const [,issuerComponent] = pathWithoutExtension(issuerPath).split(
      path.join('src',issuerLayer)
    )

    const sameModule =
      component === issuerComponent ||
      path.join(component,'index') === issuerComponent

    return sameModule
  }

  resolveComponentPath({ projectRoot,component }) {
    // check configured layers for a shadowing file
    return this.layers
      .map(layer => path.join(projectRoot,component))
      .find(checkPossibleComponentPath)
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。