使用 webpack 从目录中动态导入图片

Posted

技术标签:

【中文标题】使用 webpack 从目录中动态导入图片【英文标题】:Dynamically import images from a directory using webpack 【发布时间】:2017-06-26 09:01:57 【问题描述】:

这是我目前通过 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'] />

【问题讨论】:

我只想指出.map 有点期待返回值。在您的情况下,可以改用一个好的 ol' forEach @BramVanroy 或直接将其设为单行并直接返回 r.keys.().map(...)... 【参考方案1】:

我觉得必须有某种方法可以动态导入特定目录中的所有文件作为其名称无扩展名,然后根据需要使用这些文件。

在 ES6 中没有。 importexport 的全部意义在于可以静态确定依赖关系,即无需执行代码。

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

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


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

【讨论】:

“这里没有发生” 你的意思是文件没有出现在输出文件夹中?你仍然可以通过上面的代码找到他们的路径吗?我认为不需要做任何特别的事情来支持这一点...... 不知道为什么,买我的装载机没有运行,我得到了原始路径。加载程序现在工作正常,并且正在提供正确的路径!惊人的。感谢您引入 require.context :D! 如果我有 create-react-app(cra) 怎么办? incra importAll 没有返回任何内容。 这对我有用,但是你如何在 TypeScript 中写同样的东西呢?它的正确类型是什么? 如果有人想知道如何使用返回的数组,那么返回数组中的每一项都会有一个以default为键的对象,可以直接用作&lt;img src=item.default /&gt;【参考方案2】:

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

render() 
    const 
      someProp,
     = this.props

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

    return (
    <img src=graphImage/>
    )

【讨论】:

我认为需要做更多的工作才能使用 webpack。 你能把你的 webpack 配置文件粘贴到这里吗? 我不建议使用这样的全局要求 - 请参阅 eslint.org/docs/rules/global-require【参考方案3】:

解决这个问题的函数式方法:

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】:

我有一个名为 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()]  />
        </div>
      );
    ;

export default CountryFlagByCode;

【讨论】:

【参考方案5】:

更新 好像我不太明白这个问题。 @Felix 做对了,所以请检查他的答案。以下代码仅适用于 Nodejs 环境。

images 文件夹中添加一个index.js 文件

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 将对其进行解析并加载所需的文件。

【讨论】:

【参考方案6】:

这是我在 Reactjs 中制作的一个功能组件,用于使用 webpack 文档和此处的一些答案简单地显示我项目中media 文件夹中的所有图像(与组件相同)。

import React from 'react';

const cache = ;

function importAll(r) 
    r.keys().forEach((key) => (cache[key] = r(key)));

// Note from the docs -> Warning: The arguments passed to require.context must be literals!
importAll(require.context("./media", false, /\.(png|jpe?g|svg)$/));

const images = Object.entries(cache).map(module => module[1].default);


const MediaPage = () => 
    return (
        <>
            <p>Media Page..</p>

            images.map(image => (
                <img style=width: 100 src=image />
            ))
        </>
    );


export default MediaPage;

通过我加载图像的方式,文件名在从cache 对象映射时会丢失,但如果您需要它们,您可以直接使用cache 对象,因为键是文件名。

// example with styles just for clarity
return (
    <>
        <p>Media Page..</p>

        Object.entries(cache).map(module => 
            const image = module[1].default;
            const name = module[0].replace("./","");
            return (
                <div style=float: 'left', padding: 10, margin: 10, border: '2px solid white' >
                    <img style=width: 100, margin: 'auto', display: 'block' src=image />
                    <p>name</p>
                </div>
            )
        )
    </>
);

【讨论】:

以上是关于使用 webpack 从目录中动态导入图片的主要内容,如果未能解决你的问题,请参考以下文章

解决ps导入webp图片

PhotoShop导入webp格式图片

webpack入坑之旅扬帆起航

如何在 NPM 包中使用 webpack 动态导入?

iOS中如何从URL获取webp图片大小?

为啥 webpack 没有从我的动态导入中生成块?