1

I'm trying something that looks pretty basic with webpack: to include .pug and .scss files with import from Javascript and have the compilation export the respective .html and .css with the extract-loader and file-loader.

To make it easy to reproduce/demonstrate, I created a repo here: https://github.com/brianmhunt/broken--pug-loader

The minimal webpack config is pretty trivial, being:

const path = require('path')

module.exports = {
  output: { filename: 'app.js' },
  entry: path.join(__dirname, 'index.js'),
  module: {
    rules: [
      {
        test: /\.pug$/,
        use: [
          { loader: 'file-loader', options: { name: 'index.html' } },
          'extract-loader',
          'html-loader',
          'pug-html-loader'
        ] },
      {
        test: /\.scss$/,
        use: [
          { loader: 'file-loader', options: { name: 'main.css' } },
          'extract-loader',
          'css-loader',
          'sass-loader'
        ] }
    ]
  },
}

The files are set up/included as:

entry: index.js
  import 'one.pug'
    import three.pug
  import 'two.pug'

  import 'abc.scss'
     @import 'ghi.scss'
  import 'def.scss'

Only the content from one.pug and three.pug end up in index.html, and only abc and ghi in the css, so it seems then that the second file is ignored by the extract-loader.

Among other options, I tried concat-loader but my experiments did not yield any useful results.

To replicate the issue:

$ git clone git@github.com:brianmhunt/broken--pug-loader.git
$ yarn install
$ yarn run webpack --mode=production
Graham
  • 7,431
  • 18
  • 59
  • 84
Brian M. Hunt
  • 81,008
  • 74
  • 230
  • 343

1 Answers1

1

use include three.pug in one.pug instead of import or require. for resources use something like img(src="./img/image.png"), webpack will resolve this. I added a file load for png and tested that it then outputs .png files to the dist and sets the src="d41d8cd98f00b204e9800998ecf8427e.png" correctly.

and then in your webpack.config your entry point is just overwriting index.html twice, so you need to do something like

  {
    test: /one\.pug$/,
    use: [
      { loader: 'file-loader', options: { name: 'index.html' } },
      'concat-loader',
      'extract-loader',
      'html-loader',
      'pug-html-loader'
    ] },
  {
    test: /two\.pug$/,
      use: [
        { loader: 'file-loader', options: { name: 'index2.html' } },
        'concat-loader',
        'extract-loader',
        'html-loader',
        'pug-html-loader'
      ] },

which can be simplified to

{ loader: 'file-loader', options: { name: '[name].html' } }, for all files.

and similarly for css files.

https://github.com/cwg999/broken--pug-loader/tree/stackoverflow/cwg999-response

Cody G
  • 8,368
  • 2
  • 35
  • 50
  • Thanks Cody; I should have mentioned but there are an arbitrary number of two, three, ..., n pug files; I am sure you agree adding a config section for every file would be absurdly unmaintanable, brittle, and confusing. . With that in mind is there a way to accomplish this? – Brian M. Hunt Jun 15 '18 at 20:36
  • Yeah just use `{ loader: 'file-loader', options: { name: '[name].html' } },` – Cody G Jun 15 '18 at 20:39
  • How does one aggregate these files into one (anticipating hundreds ...)? – Brian M. Hunt Jun 16 '18 at 02:06
  • If these aren't seperate entry points for the html then you should just use the `pug` - `include` feature, shouldn't you (similar to pug 1 including 3)? Also not saying I'm an expert in this either, I never really got pug-loader to work the way I wanted it to. – Cody G Jun 18 '18 at 01:15
  • Thanks Cody. The issue is that we've a bunch of different, separate entry points to discrete modules - each with their own JS, CSS and HTML; to make it manageable at scale we'd like to include (and remove) a single entry point (e.g. the `index.js` file) that includes all the dependencies for each module. You'd think it'd be trivial ... and yet here we are – Brian M. Hunt Jun 18 '18 at 11:03
  • It's a little unclear, so basically you want `require('one.pug')` and `require('two.pug')` to actually merge together? And the reason you dont' want to do this in a `main.pug` file is because it would be in a separate file. I think there's a "append" loader of sorts... – Cody G Jun 19 '18 at 12:14
  • Yeah, I tried the `concat` loader, but that didn't seem to do the trick. It's a mystery. – Brian M. Hunt Jun 19 '18 at 12:54
  • You can write a post script loader and concat them all yourself into a new file and remove the files you imported. If you look at that concat loader you'll see it's not a very large plugin... `module.exports = function(content) { this.cacheable && this.cacheable(); this.value = content; return content; }` – Cody G Jun 20 '18 at 17:13
  • Something like https://www.npmjs.com/package/webpack-concat-plugin might work, but I don't think it works for "post webpack emit" type ordeals. – Cody G Jun 20 '18 at 17:15
  • I’ve gone on to another design so the build system here is no longer needed. I’m marking this answer as correct because I think it provides the essentials for anyone who also comes across this problem. – Brian M. Hunt Jun 20 '18 at 22:11