1. Loader development scenario
When we need to process our files in the project, but the existing loader cannot meet the requirements, it is more important to develop a loader by ourselves. For example, when we are developing a component library, we want to use Markdown to compose the feature description pages of the website. In our markdown file, we need to create a new custom tag for internationalization. For example, we must use a < CHN > tag, but this tag is not supported by the existing Markdown loader, so we need to add a new loader to parse the tag.
2. Depth of discussion in this paper
This article is not an introduction to the source code implementation of WebPack Loader, but focuses on how we develop a working loader. So let’s start with some analysis of the Loader.
3. Classification of Loaders in Webpack
Loaders in Webpack are classified into the following categories:
- The pre command is executed preferentially
- Post is postpended, and is executed last
- Normal ordinary
- The inline inline
The execution sequence of the Loader is involved. Such as:
module: {
rules: [{test: /.less$/,
use: 'style-loader'
},
{
test: /.less$/,
use: 'css-loader'
},
{
test: /.less$/,
use: 'less-loader'}},Copy the code
This is the loader we use most often, and the order of execution is actually from bottom up (or right to left). So the order of execution is:
less-loader -> css-loader -> style-loader
If we set Enforce, the custom execution order is clear, for example:
module: {
rules: [{test: /.less$/,
use: 'less-loader'.enforce: 'pre'
},
{
test: /.less$/,
use: 'css-loader'
},
{
test: /.less$/,
use: 'style-loader'.enforce: 'post'}},Copy the code
To manually determine the order of execution, write as above:
less-loader -> css-loader -> style-loader
normal
We refer to Loader in rules normally
Inline is another way to write it:
style-loader! css-loader! stylus-loaderCopy the code
Of course, the current use of inline is limited because many times you pass various parameters to the Loader.
Good, basic usage and not commonly used enforce finished, below, with normal, to focus on
4. Normal Loader and Pitching Loader
4.1 General Execution structure of Loader
The overall structure of the Loader is to export a function to the WebPack runtime(which I abstract myself).
4.2 Development mode and Execution of Normal Loader
Let’s start with the basics:
// vue-pre-loader.js
const vuePreLoader = (content, map, meta) = > {
console.log('Obtained by vue PreLoader')
console.log('Vue PreLoader logic execution');
return content;
}
module.exports = vuePreLoader;
Copy the code
Use in Webpack:
const {resolve} = require('path');
/ /...
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader'
},
{
loader: resolve(__dirname, './loader/vue-pre-loader.js'}]},]Copy the code
When compiling the.vue file, we will execute our own loader first and print out the content. The content is a string, and we can do a second processing of the data.
Ok, now let’s develop another loader for vue-loader after execution.
// vue-after-loader.js
const vueAfterLoader = (content, map, meta) = > {
// Remove the HTML comment from the content
const regExp = / <! --((\s|\r|\n)*((? ! -- >).) *\s|\r|\n)*-->/;
if(regExp.test(content)) {
content = content.replace(content.match(regExp)[0].' ');
}
console.log('vueAfterLoader logic execution ');
return content;
}
module.exports = vueAfterLoader;
Copy the code
Also, update the configuration in WebPack:
const {resolve} = require('path');
/ /...
rules: [
{
test: /\.vue$/,
use: [
{
loader: resolve(__dirname, './loader/vue-after-loader.js')}, {loader: 'vue-loader'
},
{
loader: resolve(__dirname, './loader/vue-pre-loader.js'}]},]Copy the code
Note the following two points when reexecuting:
- The content of the Content can be processed, processed into what we want
- Execution sequence: Run vue-pre-loader and then vue-arger-loader
4.3 What is a Pitching Loader
This concept is not used in many of the projects I work on, so it needs to be studied. After research, it was discovered that this pitching was actually related to circuit breakers.
Try adding this pitch first
// vue-pre-loader.js
const vuePreLoader = (content, map, meta) = > {
console.log('Vue PreLoader logic execution');
return content;
}
vuePreLoader.pitch = function(remainingRequest, precedingRequest, data) {
console.log('Execute vuePreLoader pitching');
}
module.exports = vuePreLoader;
// vue-after-loader.js
const vueAfterLoader = (content, map, meta) = > {
// Remove the HTML comment from the content
const regExp = / <! --((\s|\r|\n)*((? ! -- >).) *\s|\r|\n)*-->/;
if(regExp.test(content)) {
content = content.replace(content.match(regExp)[0].' ');
}
console.log('vueAfterLoader logic execution ');
return content;
}
vueAfterLoader.pitch = function(remainingRequest, precedingRequest, data) {
console.log('Execute vueAfterLoader pitching');
}
module.exports = vueAfterLoader;
Copy the code
Again, we find that the order of execution is as follows:
Execute vueAfterLoader pitching -> Execute vuePreLoader pitching -> Execute Vue PreLoader logic -> execute vueAfterLoader logic
In other words:The execution of pitch is from front to back. After the execution of pitch, the loader is executed from back to front
So what is this pitching application? One important function is the aforementioned circuit breaker. When pitch returns non-undefined, the previous process is blocked. For example, I do a return operation in vue-pre-loader.js
vuePreLoader.pitch = function(remainingRequest, precedingRequest, data) {
console.log('Execute vuePreLoader pitching');
return 'Circuit breaker';
}
Copy the code
Then look at the execution result:
Execute vueAfterLoader pitching -> Execute vuePreLoader pitching -> execute vueAfterLoader logic
See? It fuses the following process, so the vue PreLoader logic does not execute and returns to vue-after-loader
The overall process looks like this:
It’s not a very good drawing, but try to show the relationship between them. I hope to inspire you a little bit.
Above is all the content I want to express today, while sharing with you, I also have a deeper understanding of some of the principles, I hope to be useful to you. If you like it, don’t forget to give it a thumbs up