1

I'm trying to use Webpack to simulate Parcel's behavior in a multi-page application (I would use Parcel, but Parcel 1 won't work on Node 15 and Parcel 2 is still a beta with too many bugs to be usable at present.), and part of that is that I need to be able to have multiple HTML files with shared markup. In parcel, I used posthtml-include, so I would like to do the same with Webpack, although I am open to other options. To do this, I found this github repository, which appears to be the official way to integrate posthtml and Webpack. With this, I created a minimal Webpack project to figure out how to use it, and I found that it does not work as expected. My minimal, complete, verifiable example follows:

package.json:

{
  "name": "posthtml",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "html-loader": "^1.3.2",
    "posthtml-include": "^1.6.0",
    "posthtml-loader": "^2.0.1",
    "webpack": "^5.6.0",
    "webpack-cli": "^4.2.0"
  }
}

webpack.config.js (basically a copy/paste of the example in the linked github repository):

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
    },
    module: {
        rules: [
            {
                test: /\.html$/,
                use: [
                    'html-loader',
                    {
                        loader: 'posthtml-loader',
                        options: {
                            ident: 'posthtml',
                            parser: 'PostHTML Parser',
                            plugins: [
                                /* PostHTML Plugins */
                                require('posthtml-include')(options)
                            ]
                        }
                    }
                ]
            },
        ]
    }
};

src/index.js:

import html from './index.html';

src/index.html:

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <h1>Test</h1>
    </body>
</html>

When I run npm run build on this project, I expect it to output an index.html file in the dist subfolder that displays my heading (actually using Webpack's and Posthtml's features comes after it's working at all.), yet instead I get the following error:

$ npm run build

> posthtml@ build <path to the project directory is redacted>
> webpack

[webpack-cli] ReferenceError: options is not defined
    at Object.<anonymous> (<path to the project directory is redacted>/webpack.config.js:22:35)
    at Module._compile (<path to the project directory is redacted>/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1131:10)
    at Module.load (node:internal/modules/cjs/loader:967:32)
    at Function.Module._load (node:internal/modules/cjs/loader:807:14)
    at Module.require (node:internal/modules/cjs/loader:991:19)
    at require (<path to the project directory is redacted>/node_modules/v8-compile-cache/v8-compile-cache.js:159:20)
    at requireConfig (/<path to the project directory is redacted>/node_modules/webpack-cli/lib/groups/resolveConfig.js:73:18)
    at Array.map (<anonymous>)
    at resolveConfigFiles (<path to the project directory is redacted>/node_modules/webpack-cli/lib/groups/resolveConfig.js:124:40)
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! posthtml@ build: `webpack`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the posthtml@ build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     <home directory is redacted>/.npm/_logs/<current time, which gives timezone, is redacted>-debug.log

Why is Webpack not behaving how I expected it to? How can I cause it to behave as I expect it to? I tried to find other sources for how to use Posthtml with Webpack, but most of what I find only gives information on how to use regular HTML files with Webpack. When I use the exact code that is given in the example of what appears to be the official Github repository for this integration, it makes no sense that it's not working.

Version information:

$ npm --version            
6.14.8
$ node --version
v15.2.1
$ uname -a      
Linux blue 5.9.10-arch1-1 #1 SMP PREEMPT <date is redacted> x86_64 GNU/Linux
john01dav
  • 1,842
  • 1
  • 21
  • 40

2 Answers2

2

Because you have require('posthtml-include')(options), and that options are not defined anywhere in your webpack configuration.

Sam Chen
  • 1,933
  • 16
  • 24
  • Thanks! I fixed this by changing `(options)` to `()` and then I had to install `posthtml-include` to dev dependencies, and it builds *something* but it just outputs a single main.js file, and no HTML file in `dist`. How can I get it to output the HTML files? It looks like there's more than one error with my configuration (and it would be helpful to figure readers who look up how to use PostHTML with Webpack if all the needed information was in one SO queston).. – john01dav Nov 25 '20 at 12:59
  • That's expected, check https://github.com/jantimon/html-webpack-plugin if you want to output html file. – Sam Chen Nov 25 '20 at 13:12
  • I see how to use that plugin with a template, but I have no idea how to integrate it with posthtml. Can you clarify this point, please? – john01dav Nov 25 '20 at 14:54
  • Sorry I can't help here as I have no experience with `posthtml` or `html-loader`. Not long ago, I wrote a framework https://github.com/chenxsan/voidjs to generate multiple HTML pages with shareable React Components, and it's quite complex. I'm afraid your use case wouldn't be easy too. Hope someone else can help. – Sam Chen Nov 25 '20 at 15:17
0

I don't really understand the end goal and maybe this option will suit you?

{
  "name": "posthtml",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "extract-loader": "^5.1.0",
    "file-loader": "^6.2.0",
    "html-loader": "^1.3.2",
    "posthtml-include": "^1.6.0",
    "posthtml-loader": "^2.0.1",
    "webpack": "^5.6.0",
    "webpack-cli": "^4.2.0"
  }
}
const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
    },
    module: {
        rules: [
            {
                test: /\.html$/,
                use: [
                    'file-loader',
                    'extract-loader',
                    'html-loader',
                    {
                        loader: 'posthtml-loader',
                        options: {
                            plugins: [
                                require('posthtml-include')()
                            ]
                        }
                    }
                ]
            },
        ]
    }
};

But if you only need to generate html you can use posthtml-cli