使用动态表达式动态引入文件编译后缺少模块信息?
好像内容有点太多了不方便阅读,总结一下:
项目信息:
- RuoYi-Vue2 前后端分离版本
Vue 2.6.12
VueCLI 4x
Webpack 4x
Node v16.15.1
npm 8.11.0
- 使用阿里镜像
- 项目使用 () => import(
@/views/${view}
) 的方式动态引入页面组件。 - 正常情况下
npm run build
项目可以正确分析并预载入@/views
目录下所有Vue组件。 - 使用
npm run build --mode xxxx
指定非development/production
的环境变量文件则无法正确分析和预载入@/views
目录下Vue组件 - 无法正确预载入
@/views
目录的问题并不是稳定复现,可能换一台电脑就可以正确编译了。 - 没有配置
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.production2VUE_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.jsCritical 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
的成本显然会更高。
如果其他大佬有想法可以指导本菜?解决问题的大概方向。
回答:
- 从描述来看,我猜测是你走的太远,超过了 webpack 通常测试的覆盖范围,遇到了不能稳定重现的 bug。bug 是什么与该怎么解决,我暂时也没有头绪。
- 不过我记得动态加载需要配合
/* webpack-** */
表达式,以便 weebpack 正确打包未明确引用的包,但是你的代码里我没看到。 - 因为有 dead code 的存在,其实环境变量可能影响到编译结果,但是看你的描述,更可能是有些代码被错误标记了。不确定该怎么解决,只能一步一步打断点调试,我觉得非常不经济。
- 我能想到的解决方案是升级 webpack 到 5,先试一下。
- 如果 Jenkins 升不了那就没办法。我其实一直很好奇,为啥非得上 Jenkins?小门小户的我,用 GitHub Actions、Vercel、OpenResty 自建系统从来没被限制过。
以上是 使用动态表达式动态引入文件编译后缺少模块信息? 的全部内容, 来源链接: utcz.com/p/934473.html