在 Vue App 中使用动态目录的 webpack require.context() 的解决方法

Posted

技术标签:

【中文标题】在 Vue App 中使用动态目录的 webpack require.context() 的解决方法【英文标题】:Workaround for webpack require.context() using dynamic directories in Vue App 【发布时间】:2020-12-09 18:04:37 【问题描述】:

我有一个 Vue 应用程序,它包含一个带有多个图像库的路由。用户可以点击其中一个画廊,进入一个动态组件,该组件将显示属于他们正在查看的特定画廊的图像。

例如,用户看到 2 张卡片,foobar。单击它们会将用户带到/gallery/foo/gallery/bar。我的资产文件夹是这样组织的

src/assets/images
├── foo
│   └── 1.jpg
└── bar
    └── 2.jpg

因此,每个画廊都有一个相应的文件夹,其中包含所有图像。我在这里无法访问任何类型的数据库或 API,这个项目基本上是一个静态网站,调用任何类型的外部资源都超出了这个项目的范围。

我在这里尝试使用 Webpack 的 require.context(),但它不适用于我想要做的动态路径,如 Webpack Issue #4772 所示。

我试过的相关代码

data() 
  return 
    images: null
  
),
mounted() 
    this.populatePage();
  
,
methods: 
  populatePage() 
    const imagePath = `@/assets/images/$this.$route.params.id/`;
    this.images = this.importAll(require.context(imagePath, true, /\.(jpe?g)$/));
  ,
  importAll(r) 
     return r.keys().map(r);
  

由于我在我的require.context() 中使用了imagePath,这显然不像 Github 问题中所展示的那样工作。如果我只做@/assets/images/,它可以正常工作,但问题是它会导入图像目录中的每一个jpg,这显然不是我想要的。

获得所需效果的最佳方法是什么?最好我想避免加载任何不属于用户所在页面的图像,因为可能有数百个,即使它们被尽可能地优化,它们仍然可能很大(每个约 150kb,因为这些分辨率必须非常高)

最初我尝试做一些变体,只导入所有内容,然后可能从 webpack 生成的块中正则表达式文件夹名称,但 webpack 将省略目录并在文件名末尾添加不同的哈希值。有没有办法让 webpack 将目录附加到 Vue 中的文件名,或者真的一般?

/img/1.2f159e72.jpg
/img/2.2c1da0da.jpg

【问题讨论】:

可以在codesandbox提供示例代码吗? $this.$route.params.id 的回报是什么? @tuhin47 回到我的电脑后我会这样做@ThRnk 这是一个 Vue 路由器变量,它将返回当前路由的 id 参数。例如在gallery/foo 页面上,this.$route.params.id 返回foo 请问您使用 assets 目录而不是 public 目录的原因是什么?见cli.vuejs.org/guide/… 【参考方案1】:

Webpack 是高度可配置的。您可以将其设置为保留目录结构 - 请参阅 file-loader documentation

webpack.config.js

module.exports = 
  module: 
    rules: [
      
        test: /\.(png|jpe?g|gif)$/i,
        loader: 'file-loader',
        options: 
          name: '[path][name].[ext]',
        ,
      ,
    ],
  ,
;

然后您可以轻松地使用原始方法导入整个根目录(带有画廊目录)并仅过滤您想要的画廊中的文件。不要害怕导入所有内容 - file-loader 不会通过网络“加载”文件,它只是返回文件的 URL(在构建期间)。为了将文件加载到浏览器,您需要在img标签内使用它(例如)

【讨论】:

以上是关于在 Vue App 中使用动态目录的 webpack require.context() 的解决方法的主要内容,如果未能解决你的问题,请参考以下文章

前端Vue项目:旅游App-TabBar:搭建TabBar循环获取动态数据相关工具封装

如何为 vue3 main div #app 提供动态类?

前端Vue项目:旅游App-(12)home-Calendar:日期选择日历动态显示时间

前端Vue项目:旅游App-(12)home-Calendar:日期选择日历动态显示时间

如何在 Vue3 中使用 second.html 动态启动应用程序?

前端Vue项目:旅游App-(20)home:点击跳转至带参数的动态路由