webpack require.context() 在 Vue App 中使用动态目录的解决方法
Workaround for webpack require.context() using dynamic directories in Vue App
我有一个 Vue 应用程序,它包含一个包含多个图像库的路径。用户可以单击这些画廊之一以转到动态组件,该组件将显示属于他们正在查看的特定画廊的图像。
例如,用户看到 2 张卡片,foo
和 bar
。单击它们会将用户带到 /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
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
不会通过网络“加载”文件,它只是文件的 returns URL(在构建期间)。为了将文件加载到浏览器,您需要在 img
标签内使用它(例如)
我有一个 Vue 应用程序,它包含一个包含多个图像库的路径。用户可以单击这些画廊之一以转到动态组件,该组件将显示属于他们正在查看的特定画廊的图像。
例如,用户看到 2 张卡片,foo
和 bar
。单击它们会将用户带到 /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
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
不会通过网络“加载”文件,它只是文件的 returns URL(在构建期间)。为了将文件加载到浏览器,您需要在 img
标签内使用它(例如)