Vue-loader: resolve `require` in <template>

Created on 8 Sep 2016  路  7Comments  路  Source: vuejs/vue-loader

This is possible with pug-loader but not with vue-loader

div
  img(src=require("./my/image.png"))

This also would be very handy:

- sitemap = require("./sitemap.json")

It would allow to use the templating engine iteration mechanism instead of v-for wherever v-for isn't suited.

feature request

Most helpful comment

Custom templating engine in vue-loader in general should only be used for translating the template syntax into plain HTML-based syntax.

Also, vue-loader already translates <img src="./my/image/png"> into require calls for you.

Not sure what your last point means...

All 7 comments

Custom templating engine in vue-loader in general should only be used for translating the template syntax into plain HTML-based syntax.

Also, vue-loader already translates <img src="./my/image/png"> into require calls for you.

Not sure what your last point means...

you are right, the first example works.

Here is my (simplified) case:

table
  row(v-for="row in rows")
    col(v-for="col in cols")

This is too expensive. (I made it cheaper with vue-data-table - but the row-template needs to be static.)

And I also need the information of cols in the <script> block.

So to go with single-source-of-truth, I figured I could put the information of cols in a json file and load this this file in <script> and <template> and generate the row-template with pug.

Current workaround: move the template in an extra file and load it with pug-loader instead.

module.exports =
  template: require("./table.pug")
  data: ->
    cols: require("./cols.json")
//- ./table.pug
- cols = require("./cols.json")
table
  row(v-for="row in rows")
    each col in cols
      col

Now I have 3 files to maintain..
I'm open for advice :smile:

edit:
no - my workaround wont work

Ok, I did some digging. To resolve such requires within pug

- cols = require("./cols.json")

seams nearly impossible so implement.

But I have another solution, which is fairly easy and has some nice side effects for usability:

Add an optional attribute opt to <template> which will be merged with the global webpack vue.options and then passed down to the render engine here.

Like this:

<template lang="jade" opt="{pretty:true}">
</template>
<template lang="jade" opt="options.json">
</template>
//parser:
opt = getAttribute(node, 'opt')
if (type === 'template') {
        output.template.push({
          src: src,
          lang: lang,
          opt: opt
        })

//loader:
return defaultLoaders.html + '!' + rewriter + templateLoader + '?raw&opt=' + opt + '&engine=' + lang + '!'

//template-loader:
try {
  opt = JSON.parse(opt)
} catch { 
  try {
    opt = require(opt)
  } catch {
  // didn't work
  }
}

I'm willing to create a PR if this pleases.

Close (you can use the loaders chaining)

for me this worked:

img(:src="require('src/images/payment-liqpay.png')") 

(hope it could help someone, who also came from google)

I struggled with this for a long time, and found that the solution was as simple as adding this in your webpack config. If you're using vue-cli, so put this in your vue.config.js:

module.exports = {
  // ...
  chainWebpack: config => {
    config.module
      .rule('pug')
      .use('pug-plain-loader')
      .loader('pug-plain-loader')
      .options({ data: { require } }); // pass require as a local variable!
  },
  // ...
}

Now you can do:

- const _ = require('lodash')
div
  p=_.whatever('whatever')

@nachocab after a very long search on the issue you are my light. Worked for me in nuxt.js, thanks a lot!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lijialiang picture lijialiang  路  3Comments

snoopdouglas picture snoopdouglas  路  3Comments

amorphine picture amorphine  路  3Comments

NextSeason picture NextSeason  路  3Comments

githoniel picture githoniel  路  3Comments