6

I am trying to load an image url into a component using props but it seems like require cannot accept any variable. However, if I give require a plain text as parameter, it works

This one gives the error

Cannot find module '../assets/logo.png' at webpackEmptyContext (eval at ./src/component

<template>
    <div>

        {{imagelink}}
        <div style="width: 150px; height: 150px; background-color: red">
            <img :src="imglink" alt="" height="150px" width="150px">
        </div>
    </div>
</template>

<script>
    export default {
        name: "ImageTest",
        props:{
            imagelink: String,
        },
        computed: {
            imglink: function () {
                // this.imagelink
                const modulepatha = '../assets/logo.png'
                return  require(modulepatha)
            }
        }
    }</script>

<style scoped>
</style>

This one works:

<template>
    <div>

        {{imagelink}}
        <div style="width: 150px; height: 150px; background-color: red">
            <img :src="imglink" alt="" height="150px" width="150px">
        </div>
    </div>
</template>

<script>
    export default {
        name: "ImageTest",
        props:{
            imagelink: String,
        },
        computed: {
            imglink: function () {
                // this.imagelink
                const modulepatha = '../assets/logo.png'
                return  require('../assets/logo.png') //changed this
            }
        }
    }</script>

<style scoped>
</style>

Notice that I only changed the value inside require to a plain text

TSR
  • 17,242
  • 27
  • 93
  • 197

2 Answers2

17

Because webpack is a static build tool (it finds all the files needed at build time), a dynamic expression inside of that require statement isn't going to work because webpack has no idea what to resolve and where it exists.

That being said, a partial expression does provide webpack with enough information to load a file:

imglink: function() {
  const {someImageName} = this; 
  return require("../assets/${someImageName}");
}

This would tell webpack:

Hey webpack, find me all the possible modules that can be resolved in this partial path, then at runtime, when this function is called, only serve up the JS Module that corresponds to the name passed in.

Here's a fancy diagram I give in my code splitting patterns talk

enter image description here

If you truly need to fetch an image dynamically, I'd recommend not using require() for this purpose then. Otherwise, ensure that the images you are going to serve up are in your local codebase.

Sean Larkin
  • 6,290
  • 1
  • 28
  • 43
1

I ran into the same issue, and figured out that Webpack is a static build tool, so we can't normally use dynamic requires.

But about the solution:

  1. Solution #1 is using partial expressions (it's described here)

But using regx bundles all of the matching modules, which is not that dynamic and not probably what you want.

  1. Solution #2 is for when you're only targeting node (not browsers) : (source)
const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
const foo = requireFunc(moduleName);

this way webpack will put the normal node require on the bundle.

  1. Solution #3 is also for node target only. you can create a native-require.js file like below (source):
module.exports = require

and tell webpack to not parse it, with putting this on webpack.config.js:

module.exports = {
  "target": "node",
  "module": {"noParse": /native-require.js/}
}

then you can import the native-require like : const r = require('./native-require') and use it to dynamically import your modules.

I tested both #2 and #3 and both worked.

yaya
  • 7,675
  • 1
  • 39
  • 38