使用动态表达式动态引入文件编译后缺少模块信息?

好像内容有点太多了不方便阅读,总结一下:

  1. 项目信息:

    • RuoYi-Vue2 前后端分离版本
    • Vue 2.6.12
    • VueCLI 4x
    • Webpack 4x
    • Node v16.15.1
    • npm 8.11.0
    • 使用阿里镜像
  2. 项目使用 () => import(@/views/${view}) 的方式动态引入页面组件。
  3. 正常情况下 npm run build 项目可以正确分析并预载入 @/views 目录下所有Vue组件。
  4. 使用 npm run build --mode xxxx 指定非 development/production 的环境变量文件则无法正确分析和预载入 @/views 目录下Vue组件
  5. 无法正确预载入 @/views 目录的问题并不是稳定复现,可能换一台电脑就可以正确编译了。
  6. 没有配置 cache 功能,除了 compression-webpack-plugin 生成的 gzip 文件。

比较疑惑的是为什么没有指定环境变量文件直接使用 npm run build 编译项目(也就是默认使用 .env.production)可以正确编译,但是指定了其他环境变量文件则不会正确编译。

以下是原问题内容


按照 Webpack 文档中的信息 import() 中的表达式,使用以下方式动态引入 /views/ 目录下的所有文件。

// https://github.com/yangzongzhuan/RuoYi-Vue/blob/master/ruoyi-ui/src/store/modules/permission.js#L124

...

export const loadView = (view) => {

if (process.env.NODE_ENV === 'development') {

return (resolve) => require([`@/views/${view}`], resolve)

} else {

// 使用 import 实现生产环境的路由懒加载

return () => import(`@/views/${view}`)

}

}

正常使用 npm run build 是会正确分析预先加载所有的页面文件。

最近需要部署到一个新的生产环境中,所以创建并使用了一个新的 .env.production2 的环境变量文件来区分不同的环境,在编译时使用 npm run build --mode production2 来执行编译。

# .env.production2

VUE_APP_TITLE = 后台管理系统

BABEL_ENV = production

NODE_ENV = production

ENV = production

VUE_APP_BASE_API = /prod-api

但是编译时并不会正确预加载所有的页面文件,只会编译在静态路由表中的页面组件。并且提示:Cannot find module XXX。查看了一下 Jenkins 日志文件,发现有一个相关的警告信息:

warning  in ./src/store/modules/permission.js

Critical dependency: the request of a dependency is an expression

看起来是因为项目使用的是 webpack4 不支持动态 import 的缘故,但重新使用 npm run build 编译项目时又会正确预加载所有页面文件。

我在本地环境使用 npm run build --mode production2 编译项目时又可以成功预加载所有页面文件了,只不过在 Jenkins 中没法正确预加载。

有一些评论是说 node_modules 中的依赖项版本不同导致的,在本地删除 node_modules 目录后再使用 npm clean cache --force 清除缓存,重新 npm install。确实重新安装依赖后第一次编译时没法正确预加载了,但是我修改了一下环境变量,增加上 BABEL_ENV = production 的环境变量之后又可以成功完成编译了。
重新提交代码再使用 Jenkins 重复以上步骤编译项目时,却没办法正常预载加页面文件。但使用 npm run build 仍然可以正确预加载。

但我重新在自己本地就无论如何都没办法复现了。所以我就很迷惑。一下子没有了思绪。希望可以给一些方向。

相关Issues

  • 动态路由按需加载-Cannot find module · Issue #I4PZJF · 若依/RuoYi-Vue - Gitee.com
  • 修复版本差异导致的懒加载报错问题 · 6e14601 · 若依/RuoYi-Vue - Gitee.com
  • #如何实现路由的懒加载 常见问题 | RuoYi
  • import()拼接表达式报错 cannot find module - SegmentFault 思否


回答:

依旧只是在环境变量文件中增加了 BABEL_ENV=production,指定为生产环境。


反反复复想找出稳定复现的场景。最后可以稳定复现场景为:

  • 环境变量文件配置的 VUE_APP_TITLE 为中文时就可以正确分析并打包页面文件。使用英文就没办法正确分析。

但显然问题并不是这里导致的,所以只能怀疑是缓存的缘故。但是反复删除 node_modules 并且使用 npm cache clean --force 清理缓存,仍可以稳定复现(搞得我有点怀疑人生)。

花了太久时间复现问题了,开发工期太紧张已经不适合在投入时间在这个上面了。中间也尝试过升级到 VueCLI 5 来快速升级到 Webpack 5,但是高版本的 npm 在使用 VueCLI 更新的时候会引发依赖树分析的版本冲突问题,如果不想改变 npm 版本的话暂时没办法解决。手动升级 Webpack5 或者迁移到 Vite 的成本显然会更高。

如果其他大佬有想法可以指导本菜?解决问题的大概方向。


回答:

  1. 从描述来看,我猜测是你走的太远,超过了 webpack 通常测试的覆盖范围,遇到了不能稳定重现的 bug。bug 是什么与该怎么解决,我暂时也没有头绪。
  2. 不过我记得动态加载需要配合 /* webpack-** */ 表达式,以便 weebpack 正确打包未明确引用的包,但是你的代码里我没看到。
  3. 因为有 dead code 的存在,其实环境变量可能影响到编译结果,但是看你的描述,更可能是有些代码被错误标记了。不确定该怎么解决,只能一步一步打断点调试,我觉得非常不经济。
  4. 我能想到的解决方案是升级 webpack 到 5,先试一下。
  5. 如果 Jenkins 升不了那就没办法。我其实一直很好奇,为啥非得上 Jenkins?小门小户的我,用 GitHub Actions、Vercel、OpenResty 自建系统从来没被限制过。

以上是 使用动态表达式动态引入文件编译后缺少模块信息? 的全部内容, 来源链接: utcz.com/p/934473.html

回到顶部