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

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

  1. 项目信息:

  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

阅读 3.4k
2 个回答

依旧只是在环境变量文件中增加了 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 自建系统从来没被限制过。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题