sagold / handlebars-webpack-plugin

Renders your html-template at build time
162 stars 45 forks source link

TypeError: Cannot read property 'tap' of undefined after enabling htmlWebpackPlugin #66

Closed abachi closed 4 years ago

abachi commented 4 years ago

Hello,

I am trying to use html-webpack-plugin with handlebars-webpack-plugin. when I set htmlWebpackPlugin.enable to true

htmlWebpackPlugin: {
   enabled: true,
   prefix: 'html'
}

and compile I get the following error:

TypeError: Cannot read property 'tap' of undefined
    at D:\projects\test-handlebars\node_modules\handlebars-webpack-plugin\index.js:124:76
    at SyncHook.eval [as call] (eval at create (D:\projects\test-handlebars\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:7:1)
    at SyncHook.lazyCompileHook (D:\projects\test-handlebars\node_modules\tapable\lib\Hook.js:154:20)
    at Compiler.newCompilation (D:\projects\test-handlebars\node_modules\webpack\lib\Compiler.js:631:26)
    at D:\projects\test-handlebars\node_modules\webpack\lib\Compiler.js:667:29
    at AsyncSeriesHook.eval [as callAsync] (eval at create (D:\projects\test-handlebars\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (D:\projects\test-handlebars\node_modules\tapable\lib\Hook.js:154:20)
    at Compiler.compile (D:\projects\test-handlebars\node_modules\webpack\lib\Compiler.js:662:28)
    at D:\projects\test-handlebars\node_modules\webpack\lib\Watching.js:77:18
    at AsyncSeriesHook.eval [as callAsync] (eval at create (D:\projects\test-handlebars\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:24:1)

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HandlebarsPlugin = require('handlebars-webpack-plugin');
module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      { test: /\.hbs$/, loader: 'handlebars-loader' },
      {
        test: /\.js$/, //using regex to tell babel exactly what files to transcompile
        exclude: /node_modules/, // files to be ignored
        use: {
          loader: 'babel-loader', // specify the loader
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      // the template you want to use
      template: path.join(__dirname, 'src', 'index.hbs'),
      // the output file name
      filename: path.join(__dirname, 'dist', 'index.html'),
      inject: false,
    }),

    new HandlebarsPlugin({
      htmlWebpackPlugin: {
        enabled: true,
        prefix: 'html',
      },
      entry: path.join(process.cwd(), 'src', 'components', '*.hbs'),
      output: path.join(process.cwd(), 'dist', '[name].html'),
      partials: [
        path.join(process.cwd(), 'html', '*', '*.hbs'),
        path.join(process.cwd(), 'src', 'components', '*', '*.hbs'),
      ],
      onBeforeSetup: function (Handlebars) {},
      onBeforeAddPartials: function (Handlebars, partialsMap) {},
      onBeforeCompile: function (Handlebars, templateContent) {},
      onBeforeRender: function (Handlebars, data, filename) {},
      onBeforeSave: function (Handlebars, resultHtml, filename) {},
      onDone: function (Handlebars, filename) {},
    }),
  ],
};

package.json

{
  "name": "test-handlebars",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --config ./webpack.config.js",
    "build": "NODE_ENV=production webpack --config ./webpack.config.js --mode=production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.9.6",
    "@babel/preset-env": "^7.9.6",
    "babel-loader": "^8.1.0",
    "handlebars": "^4.7.6",
    "handlebars-loader": "^1.7.1",
    "handlebars-webpack-plugin": "^1.8.1",
    "html-webpack-plugin": "^4.3.0",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "@babel/runtime": "^7.9.6",
    "core-js": "^3.6.5"
  }
}

I couldn't figure out what is the problem. Am I missing something in the configuration?

rustyy commented 4 years ago

You don't miss something - with version 4.0.0 html-webpack-plugin renamed the "AfterHtmlProcessing"-hook to "beforeEmit" - that's why the handlebar-plugin breaks. The hook isn't present - so "tap" is either.

rustyy commented 4 years ago

Seems the solution is stated in the blog-post: https://dev.to/jantimon/html-webpack-plugin-4-has-been-released-125d

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

class MyPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      // Static Plugin interface |compilation |HOOK NAME | register listener 
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        'MyPlugin', // <-- Set a meaningful name here for stacktraces
        (data, cb) => {
          // Manipulate the content
          data.html += 'The Magic Footer'
          // Tell webpack to move on
          cb(null, data)
        }
      )
    })
  }
}

module.exports = MyPlugin
xavierfoucrier commented 4 years ago

@sagold @rustyy is this issues planned to be fixed soon? Thanks :wink:

rustyy commented 4 years ago

@xavierfoucrier - I don't know as I haven't contributed yet, but I may give it a try

xavierfoucrier commented 4 years ago

@rustyy no problem, I am just asking to know a little bit more about the maintainability of this project.

sagold commented 4 years ago

Hi there.

A fix has been published with version 2.1.0

Thank you for your help.

xavierfoucrier commented 4 years ago

@sagold & @rustyy thx! :wink: