at0g / nunjucks-loader

A webpack loader for nunjucks.
MIT License
79 stars 39 forks source link

Support 'html-webpack-plugin'? #35

Open dfdgsdfg opened 8 years ago

dfdgsdfg commented 8 years ago

Html-Webpack-Plugin is just a index.html compiler.

It can use with template like below.

module: {
  loaders: [
    { test: /\.hbs$/, loader: "handlebars" }
  ]
},
plugins: [
  new HtmlWebpackPlugin({
    title: 'Custom template using Handlebars',
    template: 'my-index.hbs'
  })
]

If I try with nunjucks-loader, I've got [nunjucks-loader] non-web targets are not supported.

What about support it? 😃

at0g commented 8 years ago

Unfortunately this is difficult (possibly won't fix) due to how nunjucks 2.x loads dependencies (and a lack of UMD support). If you want to take a crack at it, a PR is welcome

langri-sha commented 8 years ago

What is the exact problem, though? It seems that html-webpack-plugin expects the template loader to return a template function, i.e.:

const template = require('./index.nunjucks')
template(context);

Instead of:

const template = require('./index.nunjucks')
template.render(context)

If that's the case, then perhaps users can use the exports loader somehow?

at0g commented 8 years ago

What is the exact problem, though?

Nunjucks uses it's own mechanism for loading dependencies and that mechanism depends on the template object (and not just the render method). In a nutshell, this module is monkey patching nunjucks own proprietary dependency resolution system to use require from webpack.

What this means (and getting to the exact problem) is that when b depends on a, it's dependent on a being an instance of nunjucks.Template and not just the render method.

In regards to the non-web targets are not supported - the 1.x versions of this library did support UMD/node build targets, but a packaging change when nunjucks 2.x was released made this difficult - as a result, I dropped node support. That said, there have been a few changes to nunjucks recently that may make this possible again.

ghost commented 8 years ago

I'm getting the same here. Any news on this?

Using:

    "html-webpack-plugin": "^2.22.0",
    "nunjucks": "^2.5.2",
    "nunjucks-loader": "^2.4.4",
    "webpack": "^2.1.0-beta.25",
Html Webpack Plugin:
  Error: Child compilation failed:
  Module build failed: Error: [nunjucks-loader] non-web targets are not supported

  - Error: [nunjucks-loader] non-web targets are not supported

  - compiler.js:76 
    [rpg-web]/[html-webpack-plugin]/lib/compiler.js:76:16

  - Compiler.js:279 Compiler.
    [rpg-web]/[webpack]/lib/Compiler.js:279:10

  - Compiler.js:474 
    [rpg-web]/[webpack]/lib/Compiler.js:474:13

  [...]
stephanedemotte commented 7 years ago

@at0g

 That said, there have been a few changes to nunjucks recently that may make this possible again.

Still possible ?

stephanedemotte commented 7 years ago

@at0g yes ? no ? We have to make another template choice for this ?

Thank you

at0g commented 7 years ago

@stephanedemotte that's a no for now

stephanedemotte commented 7 years ago

Thanks ;)

aendra-rininsland commented 7 years ago

Anyone needing to use Nunjucks with html-webpack-plugin, one solution is to use nunjucks-html-loader in conjunction with HTML loader:

      {
        test: /\.(html|njk)$/,
        use: [
          {
            loader: 'html-loader',
          },
          {
            loader: 'nunjucks-html-loader',
            options: {
              searchPaths: [
                resolve(__dirname, 'views'),
              ],
              filters: require('./filters'),
              context: {hi: "there"},
            }
          },
        ]
      },
...
plugins: [
    new HtmlWebpackPlugin({
      template: 'client/index.html',
    }),
]

nunjucks-html-loader is sort of outdated (I think is more geared towards Webpack 1?) and I've forked it to be a bit more modern: https://github.com/ft-interactive/nunjucks-html-loader

superjose commented 7 years ago

@aendrew Thank you! Your post lead me to my current solution. In conjunction with this post, I was able to come up with a solution that allows me to use a .njk or .nunjucks file as an entry point:

First, we install nunjucks-html-loader: npm i nunjucks-html-loader -D

Or with yarn: yarn add nunjucks-html-loader -D

Imagine we have the following folder structure:

- client/
     -templates/
          index.njk   
          layout.njk
- webpack.config.js

Inside index.njk:

<!-- index.nunjucks -->
{% extends "layout.njk" %}
{% block content %}
{% endblock %}

As you can see I'm including layout.njk inside my index.njk

Here's how we achieve it with Webpack: You're flexible to modify it.

Second, we configure Webpack with the following:

//#1: Define the HTML Webpack Plugin:
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    filename: 'index.html',
    inject: 'body',
// Here is part of the magic, we get the index.njk but we tell
// webpack to pass it through the nunjucks-html-loader
    template: 'nunjucks-html-loader!./client/templates/index.njk',
  });

module.exports = {
// You should not have this the same. This is from my site. Go down to see the important part:
    entry: './client/index.js',
    output: {
      filename: production ? '[name]-[hash].js' : 'bundle.js',
      path: __dirname + '/dist',
      publicPath: 'dist/' //Important!!! : https://github.com/webpack/webpack/issues/1426
    },
   // #2  We load the HTMLWebpackPluginConfig
    plugins: [
      HtmlWebpackPluginConfig,
      extractTextPlugin
    ],

    resolve: {
      extensions: ['.Webpack.js', '.web.js', '.ts', '.js', '.tsx']
    },

// HERE is the important part
    module: {
      loaders: [
        {
          // HTML LOADER
          // Super important: We need to test for the html 
          // as well as the nunjucks files
          test: /\.html$|njk|nunjucks/,
          use: ['html-loader',{
            loader: 'nunjucks-html-loader',
            options : {
               // Other super important. This will be the base
               // directory in which webpack is going to find 
               // the layout and any other file index.njk is calling.
              searchPaths: ['./client/templates'],
            }
          }]
        }
        ]
    }
}

Run webpack, and you shall be ready to go ;)

3dos commented 6 years ago

Thank you @superjose ! This was helpful but I still got a little issue here. I cannot manage to pass data from webpack to the templates. Even htmlWebpackPlugin.options isn't available. Any hint or solution to accomplish this ?

I tried the following

new HtmlWebpackPlugin({
    someVar: 'hey, I want to be available in the template',
    filename: path.join(__dirname, '/' + page.filename),
    template: 'nunjucks-html-loader!assets/templates/' + page.name + '.njk'
})

And defining global variables in my webpack.config.js but nothing seems to do the trick.

EDIT: Nevermind, I just realized nunchucks-html-loader was a static template loader. Seems like there are currently no way to dynamically use a extendable template engine with the html webpack plugin and I'm definitely not experienced enough to dig into this loader to make the said feature available

superjose commented 6 years ago

@3dos Wait. Are you referring to using layouts on nunjucks?

3dos commented 6 years ago

@superjose I finally tried another loader, details on stackoverflow

andreyvolokitin commented 6 years ago

Can gulp tasks related to nunjucks be somehow helpful? It is sad that we have no robust loader in webpack ecosystem...

at0g commented 6 years ago

Have a look at #60