Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can not use require with variable in mixin #122

Open
truonghoangphuc opened this issue Jul 10, 2019 · 6 comments
Open

Can not use require with variable in mixin #122

truonghoangphuc opened this issue Jul 10, 2019 · 6 comments

Comments

@truonghoangphuc
Copy link

truonghoangphuc commented Jul 10, 2019

Error:

mixin img(src,alt)
  \- if (typeof(src) === 'undefined') src ='../../assets/images/transparent.png'
  img(alt=alt, src=require(src))&attributes(attributes)

==> Cannot find module 'path to image source'
@Serrulien
Copy link

Serrulien commented Jul 11, 2019

I suspect that the problem is the use of require with a variable, not only in mixins.

//- works well
img(src=require('../path/to/image.png'))

However, things get buggy when using a variable :

- var path = '../path/to/image.png'
img(src=require(path))

which can outputs :

ERROR in Template execution failed: Error: Cannot find module '../path/to/image.png'
ERROR in   Error: Cannot find module '../path/to/image.png'
  - homepage.pug:438 webpackEmptyContext
    /mnt/c/Users/julien/Documents/hexa/test/src/home/homepage.pug:438:10
  - homepage.pug:150 template
    /mnt/c/Users/julien/Documents/hexa/test/src/home/homepage.pug:150:81
  - index.js:284 Promise.resolve.then
    [test]/[html-webpack-plugin]/index.js:284:18
...
WARNING in ./src/home/homepage.pug (./node_modules/html-webpack-plugin/lib/loader.js!./src/home/homepage.pug) 5:53-64
    Critical dependency: the request of a dependency is an expression

Is this problem linked to pug-loader or HtmlWebpackPlugin ?

@Serrulien
Copy link

Serrulien commented Jul 11, 2019

I made a minimal bug repo there https://github.com/Serrulien/bug-repo-pug-loader-require-with-variable

As a template, I used :

//- faultless
//- img(src=require('./logo.png'))

//- faulty
- var path = './logo.png'
img(src=require(path))

Then I looked at pug-loader's return string

  • faultless case :
'var pug = require("!../node_modules/pug-runtime/index.js");\n\nfunction template(locals) {var pug_html = "", pug_mixins = {}, pug_interp;pug_html = pug_html + "\\u003Cimg" + (pug.attr("src", require(\'./logo.png\'), true, true)) + "\\u003E";;return pug_html;};\nmodule.exports = template;'
  • faulty case :
'var pug = require("!../node_modules/pug-runtime/index.js");\n\nfunction template(locals) {var pug_html = "", pug_mixins = {}, pug_interp;var path = \'./logo.png\'\npug_html = pug_html + "\\u003Cimg" + (pug.attr("src", require(path), true, true)) + "\\u003E";;return pug_html;};\nmodule.exports = template;'

Let's focus on the img tag (second one is the faulty one) :

"\\u003Cimg" + (pug.attr("src", require(\'./logo.png\'), true, true)) + "\\u003E"
     versus
"\\u003Cimg" + (pug.attr("src", require(path), true, true)) + "\\u003E"

I managed to fix the faulty case by casting path into string before the call to require :

require(path+"")

So, one quick and dirty fix would be to add +"" after every require(someVar with require\([a-zA-Z\$_][a-zA-Z0-9\$_]* before the final return.

@Serrulien
Copy link

Serrulien commented Jul 30, 2019

I found a straightforward workaround. We just have to use attribute interpolation with the argument of require function so as to use create a dynamic require context (more info at https://stackoverflow.com/a/42804941).

myTemplate.pug :

- const path = './logo.png'

//- buggy
img(src=require(path))

//- works
img(src=require('./logo.png'))
img(src=require(`${path}`))
img(src=require('' + path))

@AliekseiDev
Copy link

I know it's too late, but other people who are looking for the answer about using variables with pug-loader will appreciate.

The problem is that require works in pug-loader as in browser. So require(var) is a dynamic require. The solution is to partially provide path for webpack.
For example:

- let img = 'image.png';
img(src=require('../images' + img))

https://github.com/webpack/webpack/tree/master/examples/require.context#examplejs

@Polovkin
Copy link

Polovkin commented Jun 28, 2020

One more problem.
In this form, everything compiles and works

//'@img': path.resolve(__dirname, '../../src/assets/img/')

- let a = '1-1.png';
img(src=require(`@img/${a}`));

But when I build the project (webpack=> file-loader), this code copies ALL the images from the @img/ folder. If you do not use the variable in require then only 1-1.png will be copied. Even if I leave empty file-loader settings or write require ('@ img / 1-1.png) .default

@webdiscus
Copy link

webdiscus commented Oct 20, 2021

I know it's too late, but other people who are looking for the answer about using variables with pug-loader will appreciate.

The problem is that require works in pug-loader as in browser. So require(var) is a dynamic require. The solution is to partially provide path for webpack. For example:

- let img = 'image.png';
img(src=require('../images' + img))

https://github.com/webpack/webpack/tree/master/examples/require.context#examplejs

Yes, this is correctly usage in the case with a dynamic require.
A variable must content only a filename without a path. A path must be defined in separate string before the variable.
Yet one same example but with a Webpack alias:

alias: {
  Images: path.resolve(__dirname, 'src/assets/images/')
}
- const files = ['image1.jpeg', 'image2.jpeg', 'image3.jpeg']
each file in files
  img(src=require(`Images/${file}`))

More usage examples of require() in pug see in the readme of a alternative pug-loader

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants