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代わりに良いol 'を使うでしょう。
Bram Vanroy、2018

1
@BramVanroyまたはそれをワンライナーにしてr.keys.().map(...)直接返す...
LinusGeffarth

回答:


120

特定のディレクトリからすべてのファイルを拡張子ではなく名前として動的にインポートし、必要に応じてそれらのファイルを使用する方法が必要だと思います。

ES6にはありません。importおよびの要点exportは、依存関係を静的に、つまりコードを実行せずに決定できることです。

ただし、webpackを使用しているため、をご覧くださいrequire.context。次のことができるはずです。

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

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

興味深い...それで、私は現在、Webpack構成で 'file-loader'を使用して、これらすべてのファイルをアプリのパブリックディレクトリの単一の場所に移動しています。それはここでは起こっていません。ローダーはrequire.contextとどのように連携しますか?
クリノア2017

1
「ここでは発生していません」出力フォルダにファイルが表示されないということですか?それでも、上記のコードでそれらへのパスを取得できますか?これをサポートするために何か特別なことをする必要はないと思います...
Felix Kling

2
なぜだかわからない、私のローダーが実行されておらず、元のパスを取得していた。ローダーは現在正常に動作しており、正しいパスが提供されています!驚くばかり。require.context:Dを導入していただきありがとうございます。
クリノア2017

1
create-react-app(cra)を使用している場合はどうすればよいですか?中にはcra importAll何も返されません。
giorgim 2018

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で機能させるには、さらに多くのことを行う必要があると思います。
フェリックスクリング2017

ここにwebpack設定ファイルを貼り付けることができますか?
Robsonsjre 2017

3
これは素晴らしいです。ありがとう!
poweratom 2018年

1
このようにグローバル要件
markyph

7

私はau.png、nl.pngなどのような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)$/)
);

ありがとうございました!完璧に動作します!
ザカルウェ

4

更新 質問がよくわからなかったようです。@Felixは正解だったので、彼の答えを確認してください。次のコードは、Nodejs環境でのみ機能します。

フォルダーにindex.jsファイルを追加するimages

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はそれを解析して必要なファイルをロードします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.