Custom loader that invokes other loaders

Hi folks!

I’m quite new to webpack (I’ve been experimenting with it in my spare time for 2-3 months now), but I’ve already written a couple of plugins and some loaders (maybe I’m misusing it since I need to modify how it works out of the box, but anyway…).

I’m currently working on a loader that “combines” different kinds of content (html, css, etc) based on a specific source file (a vue-component file, if you’re curious). After reading blocks of different content from the file, I want my loader to invoke the other loaders defined in the webpack options for each content block, just as if they were separate files of their own, and then continue processing (i.e. combining) the results. Do you follow?

Currently my loader works by tricking webpack to think there are different files, but this is messy and it also doesn’t work with the dev-server, so I want to improve it by directly invoking the other loaders from my loader.

I’ve been digging through the _compiler and _compilation objects available in the loader context, but I feel a little lost. So, assuming my loader is invoked for path/to/myfile.vue, how can I, from my loader, invoke all the loaders that would be invoked for the hypothetical file path/to/myfile.less, providing the file contents as a string and getting the resulting script back as a string?

Author: Fantashit

1 thought on “Custom loader that invokes other loaders

  1. Are you saying it’s not possible to invoke another loader from inside a loader?

    You can either do this by emitting js code that calls require(...) with that loader. Or you can use this.loadModule(request, callback) with compiles a module and callbacks with the result.


    Try to not use this._compiler, this._compilation or this.options.


    Try to design your loaders to use chaining. I. e. your loader shouldn’t know how parts of the vue component are processed. It should return the parts and give the user the opportunity to define how the parts are processed.

    Here is an example:

    It have files that can contain multiple parts separated by ---.

    exports.answer = 42;
    ---
    body { background: red; }

    I can now write a loader that does exactly one task: “get one of the parts of the file”. I name it multipart-loader and it takes a number as query argument.

    i. e. require("multipart?0!./file.js+css") runs only the component. require("style!css!multipart?1!./file.js+css") runs the css part.

    A configuration like this allow to require("./file.js+css"), which runs both:

    { test: /\.js+css$/, loader: multiLoader(
      "style!css!multipart?1",
      "multipart?0"
    )}

    And with this flexiblity I give the user the choice to change the behavior to their needs:

    { test: /\.js+less$/, loader: multiLoader(
      "style!css!less!multipart?1",
      "multipart?0"
    )}
    { test: /\.js+css$/, loader: multiLoader(
      ExtractTextPlugin.extract("style", "css!multipart?1"),
      "multipart?0"
    )}

    The multipart-loader can internally call this.loadModule("!!" + require.resolve("./getParts") + "!" + remainingRequest, ...) to get an array of all parts. Grab the correct part and pass (return) it to the next loader.

Comments are closed.