5

I'm searching a way of using Nunjucks with the htmlWebpackPlugin to generate some html files on webpack compiling.

What I achieved so far

I managed to actually generate HTML from nunjucks template files through the nunjucks-html-loader but looking a bit closer to the code of said loader, the render method is called without sending vars to the templates.

So, for now with the following plugin config, I generate HTML without dynamically inserted vars

new HtmlWebpackPlugin({
  filename: path.join(__dirname, '/' + page.filename),
  template: 'nunjucks-html-loader!assets/templates/' + page.name + '.njk'
})

What I tried

For a testing purpose, I tried some changes on the node_module itself (I know, I know...) and changed

html = template.render(nunjucksContext);

into

html = template.render(nunjucksContext, { globals: global.globals });

Trying to define global.globals in my webpack.config.js file but this crashes with the following error

ERROR in Error: Child compilation failed: Module build failed: TypeError: parentFrame.push is not a function

which is beyond my comprehension.

What I want

Is to use an extendable template engine like nunjucks which allows me to structure my templates like the following

<html>
<!-- layout structure inherited from every template -->
</html>

Every page I make extends the layout and only overrides some blocks

What I try to avoid

Partials like for exemple

header file :

<html>
<!-- header layout -->

footer file

<!-- footer layout -->
</html>

Every page I make includes partials


So my question is : Is it even possible tu use a template engine supporting inheritance like nunjucks with the htmlWebpackPlugin or is it mandatory to use another one like ejs for exemple and chunking the layout into partials which I do not like?

3Dos
  • 3,210
  • 3
  • 24
  • 37

2 Answers2

4

Alright, so I found a workaround here with the nunjucks-isomorphic-loader which seems not super supported but still. It works for now !

Here's my webPack config

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const DEV_ENV = process.env.NODE_ENV === 'dev'

const wpConfig = {
  entry: './assets/js/app.js',

  output: {
    path: path.resolve('./dist/js'),
    filename: 'bundle.js'
  },

  module: {
    rules: [
      // Javascript
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader'
        }
      },

      // Nunjucks - HTML
      {
        test: /\.njk$/,
        use: [
          {
            loader: 'nunjucks-isomorphic-loader',
            query: {
              root: [path.resolve(__dirname, 'assets/templates')]
            }
          }
        ]
      }
    ]
  },

  plugins: [
    new webpack.DefinePlugin({
      DEV_ENV: DEV_ENV
    }),

    new HtmlWebpackPlugin({
      myOptions: { foo: 'bar' },
      filename: path.join(__dirname, '/' + page.filename),
      template: 'assets/templates/index.njk'
    })
  ]
}

module.exports = wpConfig

having the following templates

_layout.njk

{% set vars = htmlWebpackPlugin.options.myOptions %}

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{{ vars.foo }}</title>
  </head>
  <body>
    <header>
    {% block header %}
      <h1 class="header-logo">
        <a href="#">{{ vars.foo }}</a><!-- Outputs bar -->
      </h1>
    {% endblock %}
    </header>

    {% block content %}

    {% endblock %}
  </body>
</html>

index.njk

{% extends "_layout.njk" %}

{% block content %}
here's the content of my `foo` var: {{ vars.foo }}
{% endblock %}
3Dos
  • 3,210
  • 3
  • 24
  • 37
  • In your example - what is "page" defined as in "page.filepath"? Also, how do you still feel about this approach a year later? – Stu Furlong Jan 02 '19 at 21:51
  • 1
    @StuFurlong I must admit I can't figure out where `page` is defined now but looks like a path. I stripped down unnecessary details in this conf file for more clarity but I seem to have forgotten this one. I don't use template systems anymore (as I fully threw myself into React and Elm) so I cannot really tell you my feelings about this. I think the package I used is not maintained anymore (but still exists). All I can remember is that this was a bit of a hack and nunjucks is not really adapted to this use case. – 3Dos Jan 03 '19 at 08:47
  • thanks for the response, yeah its a shame as I'm looking for just some basic pre-production template creation and nothing quite fits the bill like nunjucks. Looks like people are moving on and webpack doesn't have any real solid integration with it - your approach here is the only thing I could get truly working. Doesn't seem the juice is worth the squeeze (or risk) though. I might check out ejs, thanks! – Stu Furlong Jan 03 '19 at 15:53
  • This is exactly how I felt at the time! Good luck with you template creation. – 3Dos Jan 03 '19 at 19:32
2

I have write simple-nunjucks-loader, that have some advantages to other solutions, like tracking down only required dependencies and html-webpack-plugin support out of the box.

Lesha Ogonkov
  • 1,218
  • 8
  • 20