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?
You can either do this by emitting js code that calls
require(...)
with that loader. Or you can usethis.loadModule(request, callback)
with compiles a module and callbacks with the result.Try to not use
this._compiler
,this._compilation
orthis.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
---
.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:And with this flexiblity I give the user the choice to change the behavior to their needs:
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.