Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] 目前不支持的第三方 webpack 导入方式问题 #10583

Closed
fz6m opened this issue Feb 23, 2023 · 5 comments
Closed

[Bug] 目前不支持的第三方 webpack 导入方式问题 #10583

fz6m opened this issue Feb 23, 2023 · 5 comments

Comments

@fz6m
Copy link
Member

fz6m commented Feb 23, 2023

说明

Version :2024-05-19

若遇到使用 webpack 插件、babel 插件,报错找不到某个 webpack 模块问题,原因是因为:

  1. 这些插件中,使用了 webpack 包中的某些深层的方法或类,如直接导入了 webpack/lib/TemplatedPathPlugin

  2. umi 预打包了 webpack ,而预打包的 webpack 中没包含到要深层导入的类。

目前可以尝试的几种解决方法

方法一:延后导入法

将导入时机从 import 最早改为 chainWebpackrequire ,尝试看看会不会还报错,因为 import 的时机太早了,在太早的时机可能 umi 还没有 hook 到 webpack 的导入。

// .umirc.ts
-  import { GenerateSW } from "workbox-webpack-plugin";

// ...

  chainWebpack() {
+   const { GenerateSW } = require("workbox-webpack-plugin");    
  }

方法二:提出 issue ,等待 PR 修复

附带最小复现,提出你报错的 issue ,排查找到是哪些找不到后,把这些内容添加到 umi 的 webpack hook 列表即可。

方法三:手动 hook 找不到的导入

先安装 webpack :

  pnpm add -D webpack

在配置文件最上面添加如下代码片段:

// .umirc.ts

function webpackDeepPathImportWorkaround() {
  const webpackPath = path.join(__dirname, './node_modules/webpack/lib')
  const mod = require('module')
  const resolveFilename = mod._resolveFilename
  const hookPropertyMap = new Map()
  hookPropertyMap.set(
    'webpack/lib/TemplatedPathPlugin',
    path.join(webpackPath, './TemplatedPathPlugin.js')
  )
  hookPropertyMap.set(
    'webpack/lib/util/createHash',
    path.join(webpackPath, './util/createHash.js')
  )
  mod._resolveFilename = function (
    request: string,
    parent: any,
    isMain: boolean,
    options: any
  ) {
    const hookResolved = hookPropertyMap.get(request)
    if (hookResolved) request = hookResolved
    return resolveFilename.call(mod, request, parent, isMain, options)
  }
}
webpackDeepPathImportWorkaround()

以上代码片段可以人为去 hook 那些找不到的 webpack 变量,需要自己去调查下使用的包里用到了哪些 webpack 的深层导入。

注:此种方法并不是完美的。比如涉及到大量的深层导入,可能要写一个工具去扫描都有哪些导入抽取出来;比如涉及到 webpack module 相关的 class ,如果插件通过导入 webpack module 类来新增代码块,由于自己安装的 webpack 和真正运行的 webpack 不是一个,所以也会导致新增的 module 代码块生成失败,最终解决方案还是 方法 2 :提交 issue 通过添加找不到的导入到 umi 仓库内解决

以下内容已过时(截止 2024-05-19 ),展开查看

问题

目前 umi 4 不支持以下两种与 webpack 有关的导入。

使用的 webpack 插件中导入了 webpack

如果 webpack 插件使用了 webpack 实例,比如 require('webpack') 导入,此时是找不到的,因为解析配置文件的时机还没有 hook webpack 导入,在 pnpm 的严格隔离机制下,无法找到 webpack 。

反馈来自于:#10289 (插件 workbox-webpack-plugin 中导入了 webpack 但找不到报错)

解决方法

可以手动延缓该插件的导入时机,比如不在配置文件顶层导入而是放到 chainWebpack 中:

// .umirc.ts
-  import { GenerateSW } from "workbox-webpack-plugin";

// ...

  chainWebpack() {
+   const { GenerateSW } = require("workbox-webpack-plugin");    
  }

或者手动安装一个 webpack ,让他能找到 webpack 实例:

  pnpm add -D webpack

理想的预期情况是该插件支持传入 webpack 实例的实现,但涉及到插件内改造推进困难。

深层的 webpack 路径导入

反馈来自于:#10565#10712

比如 babel 插件中使用了 webpack 的非公开方法,比如 babel-plugin-react-css-modules 插件使用了:

// https://github.com/birdofpreyru/babel-plugin-react-css-modules/blob/master/src/getLocalIdent.js

import TemplatedPathPlugin from 'webpack/lib/TemplatedPathPlugin';
import createHash from 'webpack/lib/util/createHash';

这两个深层路径方法都不是 webpack 公开方法(指无法通过 webpack.xxx 使用),在 umi 4 中也无法通过 deepimport.json 的方式 hook 他的导入,因为预打包的产物是 index.js ,没有路径,我们也没有办法从公开方法上取到他。

解决方法

目前一种很 hack 的解决方法是用户自己 hook 需要的 webpack 深层路径导入:

  pnpm add -D webpack
// .umirc.ts

function webpackDeepPathImportWorkaround() {
  const webpackPath = path.join(__dirname, './node_modules/webpack/lib')
  const mod = require('module')
  const resolveFilename = mod._resolveFilename
  const hookPropertyMap = new Map()
  hookPropertyMap.set(
    'webpack/lib/TemplatedPathPlugin',
    path.join(webpackPath, './TemplatedPathPlugin.js')
  )
  hookPropertyMap.set(
    'webpack/lib/util/createHash',
    path.join(webpackPath, './util/createHash.js')
  )
  mod._resolveFilename = function (
    request: string,
    parent: any,
    isMain: boolean,
    options: any
  ) {
    const hookResolved = hookPropertyMap.get(request)
    if (hookResolved) request = hookResolved
    return resolveFilename.call(mod, request, parent, isMain, options)
  }
}
webpackDeepPathImportWorkaround()

这种方式需要提前获知使用的插件有哪些深层的 webpack 导入,成本较高。

@fz6m fz6m changed the title [Bug] webpack 深层导入相关问题 [Bug] 目前不支持的第三方 webpack 导入方式问题 Feb 23, 2023
@xierenyuan
Copy link
Member

多安装一个 webpack 会不会有多实列的问题 我记得 webpack 有多实列出错的问题
深层的webpack 引入感觉遇到一类就加一类吧 -.- 上一次就加了好几个

@fz6m
Copy link
Member Author

fz6m commented Feb 23, 2023

多安装一个 webpack 会不会有多实列的问题 我记得 webpack 有多实列出错的问题 深层的webpack 引入感觉遇到一类就加一类吧 -.- 上一次就加了好几个

在这个用例里面是没问题的,主要是 webpack 没公开这个类,稍微是有些 “非常规” 的用法的,如果是公开方法,加上没问题的。

@yq756530939
Copy link

I tried all the methods above,but the problem still exists。Switch webpack version to 4.44.x,No template for dependency: ConstDependency

@fz6m
Copy link
Member Author

fz6m commented May 29, 2023

umi 4 不支持 webpack 4 。

@fz6m
Copy link
Member Author

fz6m commented May 19, 2024

此问题已有多个解决方法,遇到问题选其一尝试即可,故关闭 issue 。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants