如何解决Webpack 5 文件阴影加载器
我们目前正在使用类似于 gatsby 文件阴影的文件阴影机制: https://www.gatsbyjs.com/docs/conceptual/how-shadowing-works/ 借助此解决方案,我们能够拥有一个 next.js 存储库,并为不同的客户及其自定义进行构建。
当我们尝试更新到 webpack 5 时,我们遇到了 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 举报,一经查实,本站将立刻删除。