Search code examples
webpackpugpug-loader

What is the order loaders applying in Webpack?


I am trying to setup the loading of .pug files by Webpack depending on interim filename extension, herewith it should be default one. In my case, the files which names ends with .vue.pug must me loaded with by different rules that plain .pug.

enter image description here

In above preset, the { test: /\.vue.pug$/, /* ... */ } part is related with Vue framework and has been recommended me by developers of @webdiscus/pug-loader. The last part (test: /(?!.*\.vue\.pug$).*\.pug$/) is the default loader for Pug files.

{

  // ...

  module: {

    //
    rules: [

      // === Loading of Pug from files related with Vue
      {
        test: /\.vue.pug$/,
        oneOf: [
          // allow <template lang="pug"> in Vue components
          {
            resourceQuery: /.vue$/u,
            loader: '@webdiscus/pug-loader', // <-- it is same pug-loader as in PugPlugin.loader
            options: {
              method: 'html', // render Pug into pure HTML string
            },
          },
          // allow import of Pug in JS/TS and for "other cases", if a file hasn't the extension `.vue`
          {
            resourceQuery: ".vue.ts",
            loader: '@webdiscus/pug-loader', // <-- it is same pug-loader as in PugPlugin.loader
            options: {
              method: 'compile', // compile Pug into template function, use it if you want pass custom data into template on clinet-side rendering.
              //method: 'render', // compile Pug into template string, use if your template has't external custom data, generates smallest file
              //esModule: true, // should be `true` for importing in ES module, e.g. `import tmpl from './myTemplate.pug';`
                              // defaults is false, used for CommonJS, e.g.  `const tmpl = require('./myTemplate.pug');`
                              // NOTE: this option is optional, if it is not defined, importing in ES module works too.
            },
          },
        ],
      },

      // Loading of Pug from files not related with Vue
      {
        test: /(?!.*\.vue\.pug$).*\.pug$/,
        loader: '@webdiscus/pug-loader',
        options: {
          method: 'render'
        },
      },

    ]
  },

  // ...

};

Although the building is being executed without error, if to run script in browser, we'll get an error:

Uncaught TypeError: _ExampleMultipleFilesComponent_vue_pug__WEBPACK_IMPORTED_MODULE_0___default(...) is not a function

If to remove below part and do not import .pug files to non-vue files, no error will be.

{
  test: /(?!.*\.vue\.pug$).*\.pug$/,
  loader: '@webdiscus/pug-loader',
  options: {
    method: 'render'
  },
}

Looks like I do not understand how Webpack selects the appropriate loader. Please explain.

Repro repository (please make sure that you are checking out @problem/default_loader branch)


Solution

  • Although the building is being executed without error, if to run script in browser, we'll get an error:

    I can't reproduce the error in browser (FireFox). In the browser I see compiled Vue components:

    Example single file component
    Example multiple files component with custom variable "someText": Hello Pug!
    

    Explain how works the pug-loader

    {
      test: /\.pug$/,
      oneOf: [
        // [1] issuer is VUE file
        {
          resourceQuery: /^\?vue/u,
          loader: '@webdiscus/pug-loader',
          options: {
            method: 'html', // exports rendered HTML sting
          },
        },
        // [2] issuer is TS file
        {
          loader: '@webdiscus/pug-loader',
          options: {
            method: 'compile', // export compiled template function
          },
        },
      ],
    }
    

    You load anywhere a Pug file .pug, then Webpack select the rule to process this file via the loader.

    Where the Pug file is loaded is important, because for each issuer (parent) will be generate expected result.

    You have two issuer types:

    1. Vue file. If you use Pug code in a Vue file, e.g. in ExampleSingleFileComponent.vue, then Webpack select [1] loader with the options to render Pug into pure HTML string, so is expected in this case.

    2. TS file. If you load a Pug file in TS/JS, e.g. in ExampleMultipleFilesComponent.vue.ts then Webpack select [2] loader with the options to compile the Pug file into JS template function. This template function you can call with variables to render it into HTML at the runtime, in browser.