I know that style-loader adds CSS to a dom by injecting a tag. And css-loader gets css as string when it meets require('./style.css');
.
But, How style-loader plays with css-loader??
I'm reading style-loader source code and css-loader source code. But I cannot understand how they play together.
How the css string which css-loader gets from style.css is passed to style-loader?
The style loader takes CSS and actually inserts it into the page so that the styles are active on the page.
To be able to use CSS in your webpack app, you need to set up a new loader. Out-of-the-box, webpack only understands Javascript and JSON. With a loader, you can translate another type of file to a format that webpack understands and can work with. There are many webpack loaders and each loader has a specific purpose.
They allow you to pre-process files as you import or “load” them. Thus, loaders are kind of like “tasks” in other build tools and provide a powerful way to handle front-end build steps. Loaders can transform files from a different language (like TypeScript) to JavaScript or load inline images as data URLs.
By default, Webpack will inline your CSS as Javascript tags that injects the CSS into the page. This sounds strange but it lets you do hot reloading in development. In production you extract them to a file using the ExtractTextPlugin, and require it with a normal link tag.
Good question. I've done quite some homework in order to properly answer it. Here's what I found.
The common understanding of webpack loaders, is that they are units chained-up to form a pipeline. Each loader processes the input source code, transforms it, then passes the result down to the next unit in the pipeline. And this process repeats until the last unit done its job.
But above is only part of the whole picture, only true for normal loaders. style-loader
is not a normal loader, because it also has a pitch method.
pitch
Method of LoaderNote, there's no such thing as pitch loader, cus every loader can have a "normal side" and "pitch side".
Here's the not-very-helpful webpack doc on pitching loader. The most useful info is the concept of "pitch phase" and "normal phase" and their execution order.
|- a-loader `pitch`
|- b-loader `pitch`
|- c-loader `pitch`
|- requested module is picked up as a dependency
|- c-loader normal execution
|- b-loader normal execution
|- a-loader normal execution
You've seen style-loader
's source code, the export looks like:
module.exports = {}
module.exports.pitch = function loader(request) {
/* ... */
return [/* some string */].join('\n')
}
The only related part in the doc to above source code:
if a loader delivers a result in the pitch method the process turns around and skips the remaining loaders.
It's still quite unclear on how exactly this pitch thing works.
I finally came across this blog post (written in chinese tho) talks about the detail. Specifically, it analyses the exact case like in style-loader
where the pitch
method returns something.
As per the blog, the pitch
method is mainly used to access and modify metadata early in the loader process. Returning from pitch
method is indeed rare, and poorly documented. But when it does return sth other than undefined
, here's what happens:
# Normal execution order is disrupted.
|- style-loader `pitch` # <-- because this guy returns string early
# below steps are all canceled out
|- css-loader `pitch`
|- requested module is picked up as a dependency
|- css-loader normal execution
|- style-loader normal execution
Then the return value from styleLoader.pitch
just becomes a new in-memory file entry. This file is then loaded like a normal file and transformed using a brand new load process.
If you check, the content of this on-the-fly generated file from styleLoader.pitch
looks something like
var content = require("!!./node_modules/css-loader/dist/cjs.js??ref--8-3!./index.css");
You'll notice every require
request is fully configured using inline query. Thus these request won't go through any test
in webpackConfig.module.rules
.
Basically, this is what style-loader
does:
pitch
method.require(...)
I don't know any better, all truth is held in the source code of loader-runner
module. If anyone has better ref sources or understanding, please comment, post an answer or edit mine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With