Search code examples
webpackwebpack-4sass-loaderpug-loader

Webpack 4 + pug/sass extract/file-loaders not working with multiple imports


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 [email protected]:brianmhunt/broken--pug-loader.git
$ yarn install
$ yarn run webpack --mode=production

Solution

  • 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