Html-webpack-plugin: templateParameters is called too early

Created on 10 Jul 2018  路  17Comments  路  Source: jantimon/html-webpack-plugin

Hi,

I started to build my own plugin to merge some json files and the merged files should be used by TemplateParameters, but templateParameters is called too early, I always get the error message

no such file or directory,

I tried to use the hook htmlWebpackPluginBeforeHtmlGeneration but then I get the error Message

TypeError: Cannot read property 'tapAsync' of undefined

MergeJsons.prototype.apply = function (compiler) {
  compiler.hooks.compilation.tap('MergeJsons', (compilation) => {
    compilation.hooks.htmlWebpackPluginBeforeHtmlGeneration.tapAsync('MergeJsons', () => {
        glob('./src/data/*.json', (error, files) => {
            files.forEach((filename) => {
                const content = JSON.parse(fs.readFileSync(filename, 'utf8'));
                Object.assign(merged, content);
            });
            fs.writeFileSync('merged.json', JSON.stringify(merged));
        });
      }
    )
  })
}

my webpack.config

new MergeJsons(),
...pages.map(page => new HtmlWebpackPlugin({
    template: 'hbs/pages/'+page,
    filename: page.split(".")[0]+".html",
    templateParameters: JSON.parse(fs.readFileSync('merged.json', 'utf8'));
}))

Should I use another hook? Or how can I achieve that the templateParameters isn't called so early?

All 17 comments

We are changing the structure of hooks right now:
https://github.com/jantimon/html-webpack-plugin/pull/953

It will probably look like documented here:
https://github.com/jantimon/html-webpack-plugin/tree/webpack-4#events

Just a side node - your approach looks very slow.
If your template would require the json files webpack could use a cache and read the jsons only once.

Thank you. I will try it later.

This is my first plugin. I started with webpack a few weeks ago. Do you mean I should do

templateParameters: require('merged.json')

?

Rather inside your hbs helper:

require.context('./your/directory/', true, /\.json$/);
const jsons = requireTest.keys().forEach(requireTest);
// maybe some merge logic here
return jsons;

I installed

npm i html-webpack-plugin@next

but get this error message now

TypeError: HtmlWebpackPlugin.getHooks is not a function

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

MergeJsons.prototype.apply = function (compiler) {
  compiler.hooks.compilation.tap('MergeJsons', (compilation) => {
    HtmlWebpackPlugin.getHooks(compilation).beforeHtmlGeneration.tapAsync('MergeJsons', () => {
      ....
    })
  })
}

That's correct we will release the new version soon

Hey @gregorvoinov.

You're getting TypeError: Cannot read property 'tapAsync' of undefined because you're inserting your plugin before HTMLWebpackPlugin in the plugins array. HTMLWebpackPlugin needs to have been applied before your plugin.

Also, on tapAsync you're missing the callback:

compiler.hooks.compilation.tap('SomePlugin', compilation => {
  compilation.hooks.htmlWebpackPluginBeforeHtmlGeneration.tapAsync('SomePlugin', (data, callback) => {
    // Do async stuff here and then return within callback

    // The first argument corresponds to errors you might want to return
    // The second corresponds to the result
    callback(null, result)
  });
});

For that hook specifically, the data has the below shape, and HTMLWebpackPlugin expects you to return an object with the same shape in the result鈥攖hat object is used in the later steps to postprocess the HTML.

{
  assets: {
    publicPath: string,
    js: Array<{entryName: string, path: string}>,
    css: Array<{entryName: string, path: string}>,
  },
  outputName: string,
  plugin: HtmlWebpackPlugin
}

@emilio-martinez this will also change with the @next version (I'll try to release a beta this week)

any news for the release? ;)

@gregorvoinov sorry it's even more work than expected - I am on it :)

I'll release a beta once #1032 is merged - @gregorvoinov could you please take a look at it?

sry for late reply, I was on vacation :)

But no, now I get this error message

TypeError: Cannot read property 'tapAsync' of undefined
at compiler.hooks.compilation.tap (/path/src/plugin/mergeJson.js:16:69)
at SyncHook.eval [as call] (eval at create (/path/node_modules/tapable/lib/HookCodeFactory.js:17:12), :7:1)
...

This is the latest @next release?

"html-webpack-plugin": "^4.0.0-alpha.2",

Can you please add the code of /path/src/plugin/mergeJson.js:16:69)

Yes 4.0.0-alpha.2 is the current @next release

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

function MergeJsons(options) {

}

MergeJsons.prototype.apply = function (compiler) {
    compiler.hooks.compilation.tap('MergeJsons', (compilation) => {
        HtmlWebpackPlugin.getHooks(compilation).beforeHtmlGeneration.tapAsync('MergeJsons', () 
            console.log('merge something');
        })
    })
}

module.exports = MergeJsons

The hooks have been renamed:

oh thx now I have no errors

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

var-bp picture var-bp  路  3Comments

azat-io picture azat-io  路  4Comments

MatthewKosloski picture MatthewKosloski  路  3Comments

amorphius picture amorphius  路  3Comments

mmjamal picture mmjamal  路  3Comments