TLDR;
// All of these works
const fileNameExt = 'foo.jpg'
<img src={require('../images/' + fileNameExt)} />
<img src={require(`../images/${fileNameExt}`)} />
const fileName = 'foo'
<img src={require('../images/' + fileName + '.jpg')} />
<img src={require(`../images/${fileName}.jpg`)} />
// These does not work:
const myPathVariable1 = '../images/' + 'foo' + '.jpg'
<img src={require(myPathVariable1)} />
const myPathVariable2 = '../images/' + 'foo.jpg'
<img src={require(myPathVariable2)} />
Explanation: You can not pass a variable name as argument to require because webpack doesn't do program flow analysis to know the variable value.
Webpack can not know which module it should load as it is unable to extract (guess) any information (path) about the module you provided in a variable. Hence, it fails to load when the argument is a variable.
But, webpack can require with expression because it can extract some information about the path if you provide it correctly.
For example, let's say this is the directory structure:
example_directory
│
└───template
│ │ table.ejs
│ │ table-row.ejs
│ │
│ └───directory
│ │ another.ejs
Method 1: Using variable (would not work):
var myPath = './template/table-row.ejs'
require(myPath)
// will not work as webpack can't extract anything path or file as myPath is just a variable
Method 2: Using expression (would work; involves some pattern webpack can understand):
var myPath = 'table'
require("./template/" + name + ".ejs")
Webpack can parse and generate below context from the expression in Method 2:
Directory: ./template // webpack understand that there is this directory
Regular expression: /^.*\.ejs$/ // and this regex about the modules
So, it will load all the matching modules:
./template/table.ejs
./template/table-row.ejs
./template/directory/another.ejs
// Note that it will load all matching even if we provide --> var myPath = 'table' shown above
So, whenever webpack see an "expression" (not the variable) in require
. It loads all matching modules and generates a "Context Module" which has information of all such loaded modules as a result of above expression.
So, you need to provide an expression which webpack can understand and make context module by loading all matches.
This means dynamic requires are supported but will cause all matching modules to be included in the bundle. (And might increase your bundle size so you need to be careful when using the expression inside require)
Answer to your question:
To make this work:
<img className='personal' alt='robots' src={require(`${src}`)}/>
You need to do:
<img className='personal' alt='robots' src={require("../images/" + src)}/>
// loads everyting inside "../images/"
or, better:
<img className='personal' alt='robots' src={require("../images/" + src + ".png")}/>
// loads everything inside "../images/" ending with ".png"
You can use backticks i.e. template literals too:
`../images/${src}.png`