使用webpack从目录动态导入图像


99

因此,这是我当前通过ES6导入Webpack中的图像和图标的工作流程:

import cat from './images/cat1.jpg'
import cat2 from './images/cat2.svg'
import doggy from './images/doggy.png'
import turtle from './images/turtle.png'

<img src={doggy} />

这变得很快。这就是我想要的:

import * from './images'

<img src={doggy} />
<img src={turtle} />

我觉得必须有某种方法可以动态地从特定目录中导入所有文件(不带扩展名),然后根据需要使用这些文件。

任何人都看过此事,或者对最佳解决方案有任何想法?


更新:

使用选择的答案,我能够做到这一点:

function importAll(r) {
  let images = {};
  r.keys().map((item, index) => { images[item.replace('./', '')] = r(item); });
  return images;
}

const images = importAll(require.context('./images', false, /\.(png|jpe?g|svg)$/));

<img src={images['doggy.png']} />

7
我只想指出.map这种期望的返回值。在您的情况下,您会forEach改用其他语言。
布拉姆·范罗伊

1
@BramVanroy或只是将其制成单线并r.keys.().map(...)直接返回...
LinusGeffarth '19

Answers:


120

我觉得必须有某种方法可以动态地从特定目录中导入所有文件(不带扩展名),然后根据需要使用这些文件。

ES6中没有。整点importexport是依赖关系可被确定静态,即没有执行代码。

但是,由于您使用的是webpack,因此请参阅require.context。您应该能够执行以下操作:

function importAll(r) {
  return r.keys().map(r);
}

const images = importAll(require.context('./', false, /\.(png|jpe?g|svg)$/));

有趣的是...因此,我目前在Webpack配置中使用“文件加载器”将所有这些文件移动到我的应用程序公共目录中的单个位置。这不是在这里发生。加载程序如何与require.context一起使用?
klinore

1
“这里没有发生”,您的意思是文件没有出现在输出文件夹中?您仍然可以通过上面的代码找到它们的路径吗?我认为不需要做任何特别的事情来支持这一点……
Felix Kling

2
不知道为什么,购买我的装载机没有在运行,我在找原始路径。加载程序现在可以正常工作,并且提供了正确的路径!太棒了 感谢您对require.context的介绍:D!
klinore

1
如果我有create-react-app(cra),该怎么用?在cra importAll什么也没有返回。
giorgim

2
这对我有用,但是您将如何在TypeScript中编写相同的内容?正确的类型是什么?
Maximilian Lindsey

10

这很容易。您可以在中使用require(静态方法,导入仅用于动态文件)render。像下面的例子:

render() {
    const {
      someProp,
    } = this.props

    const graphImage = require('./graph-' + anyVariable + '.png')
    const tableImage = require('./table-' + anyVariable2 + '.png')

    return (
    <img src={graphImage}/>
    )
}

1
我认为需要做更多工作才能使用webpack进行这项工作。
菲利克斯·克林

您可以在此处粘贴您的webpack配置文件吗?
Robsonsjre

3
这是光荣的。谢谢!
poweratom

1
我不建议您使用像这样的全局需求-请参阅eslint.org/docs/rules/global-require
markyph

7

我有png国家标志的目录,如au.png,nl.png等。所以我有:

-svg-country-flags
 --png100px
   ---au.png
   ---au.png
 --index.js
 --CountryFlagByCode.js

index.js

const context = require.context('./png100px', true, /.png$/);

const obj = {};
context.keys().forEach((key) => {
  const countryCode = key.split('./').pop() // remove the first 2 characters
    .substring(0, key.length - 6); // remove the file extension
  obj[countryCode] = context(key);
});

export default obj;

我读了这样的文件:

CountryFlagByCode.js

import React from 'react';
import countryFlags from './index';

const CountryFlagByCode = (countryCode) => {
    return (
        <div>
          <img src={countryFlags[countryCode.toLowerCase()]} alt="country_flag" />
        </div>
      );
    };

export default CountryFlagByCode;

5

解决此问题的实用方法:

const importAll = require =>
  require.keys().reduce((acc, next) => {
    acc[next.replace("./", "")] = require(next);
    return acc;
  }, {});

const images = importAll(
  require.context("./image", false, /\.(png|jpe?g|svg)$/)
);

谢谢!完美的作品!
Zakalwe

4

更新 似乎我不太明白这个问题。@Felix正确,请检查他的答案。以下代码仅适用于Node.js环境。

index.jsimages文件夹中添加文件

const testFolder = './';
const fs = require('fs');
const path = require('path')

const allowedExts = [
  '.png' // add any extensions you need
]

const modules = {};

const files = fs.readdirSync(testFolder);

if (files && files.length) {
  files
    .filter(file => allowedExts.indexOf(path.extname(file)) > -1)
    .forEach(file => exports[path.basename(file, path.extname(file))] = require(`./${file}`));
}

module.exports = modules;

这将允许您从另一个文件导入所有内容,Wepback将对其进行解析并加载所需的文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.