mozilla / nunjucks

A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)
https://mozilla.github.io/nunjucks/
BSD 2-Clause "Simplified" License
8.49k stars 637 forks source link

Relative paths not working in precompiled templates in the browser #755

Open rhengles opened 8 years ago

rhengles commented 8 years ago

I am trying to use the PrecompiledLoader in the browser, but I'm getting this error:

TypeError: path.dirname is not a function at Obj.extend.resolve (http://localhost:8576/js/nunjucks-slim.js:2504:35) at Obj.extend.resolveTemplate (http://localhost:8576/js/nunjucks-slim.js:597:56) at Obj.extend.getTemplate (http://localhost:8576/js/nunjucks-slim.js:627:35) at root as rootRenderFunc at Obj.extend.render (http://localhost:8576/js/nunjucks-slim.js:923:16) at http://localhost:8576/js/nunjucks-slim.js:756:36 at createTemplate (http://localhost:8576/js/nunjucks-slim.js:679:26) at handle (http://localhost:8576/js/nunjucks-slim.js:694:26) at http://localhost:8576/js/nunjucks-slim.js:708:22 at next (http://localhost:8576/js/nunjucks-slim.js:347:14)

I found out it's because the precompiled templates still have the relative paths - they're not converted to absolute paths - and the nunjucks runtime is calling Loader#resolve() which uses "path.dirname" and "path.resolve" from require("path").

In my case, I don't know how, but the "path" variable has this value:

{
    "PrecompiledLoader": function () {
            if(prototype.init) {
                prototype.init.apply(this, arguments);
            }
    }
}

How do I solve this? I'm using nunjucks 2.4.2. I did a little research here, and if I'm not mistaken, this was supposed to have been implemented in #349.

Thanks!

@carljm

carljm commented 8 years ago

The webpack config mocks out the path module to an empty module for the browser, which explains why you're seeing something odd there. By relative paths I assume you mean paths beginning with ../ or ./? I've never used that feature, so it's certainly possible that it's broken with precompiling in the browser. If so, seems like the fix would be to resolve in precompilation so they don't need resolution at runtime.

ogonkov commented 4 years ago

It's broken for precompiled templates generally, not browser only. Nunjucks seems didn't process paths in same way as it do for ordinary render().

chrisdevereux commented 2 months ago

This very hacky workaround does the trick for me:

import * as path from "path-webpack";
import * as njk from "nunjucks/browser/nunjucks-slim";

njk.PrecompiledLoader.prototype.resolve = function patchedResolve(from, to) {
  return path.resolve(path.dirname(from), to)
}

perhaps the use of node:path in PrecompiledLoader could be replaced with something like this?