preface
Webpack is written by Node, so it can only recognize JS files. So today we will explore how loader in Webpack implements file recognition and conversion
To understand
Through a simple configuration, to understand, the most classic is csS-loader because Webpack can only recognize JS files, what about CSS files?
// A simple WebPack configuration
const path = require('path');
module.exports = {
entry: './main.js'.output: {
filename: 'bundle[hash:6].js'.path: path.resolve(__dirname, './dist'),},module: { // Where the loader is mainly used
rules: [
// To configure the loader for packing CSS files, use defines the loader to be used, and pay attention to the sequence
// style-loader must be placed before CSS-loader because loader is executed from right to left
{
test: /\.css$/.// Matches files with a.css suffix
use: ['style-loader'.'css-loader'}]}};Copy the code
Responsibility and Logic
Loader has a single responsibility and only needs to complete one identification and transformation. If a source file needs to be converted for many times to achieve the desired effect, it will take a long time to convert it through multiple Loaders. When multiple Loaders are called to convert a file, each Loader will execute it in chained order from right to left. The results processed by the previous Loader are passed to the next Loader for further processing, and the last Loader returns the processed results to Webpack
basis
Loader is a file processing module written by Node. In essence, Loader is a function
function LoadrFunc (source) {
// Source is the parameter, which is the content of the file entity to process
// do something
// The 'Loader' does not perform any conversion
return source;
};
module.exports = LoadrFunc
Copy the code
Take a parameter source, which is the source of the file to be converted, convert it, and return it to Webpack
The advanced
After looking at how loader is implemented, we also know that in everyday use, we might write es6 to ES5
{
test:/\.js$/.// Matches files with the.js suffix
use:{ // This is written as an object
loader: 'babel-loader'.options: {
presets: ['@babel/preset-env'].// Convert es6 to ES5}}}Copy the code
Here use ES6 conversion ES5 example to demonstrate, loader options is how to implement? Loader-utils is a class package for loader, which contains some commonly used methods of Loader
// Import the loader-utils package
const loaderUtils = require('loader-utils');
function LoadrFunc (source) {
// Source is the parameter, which is the content of the file entity to process
// Get the options passed by the user to the current Loader
const options = loaderUtils.getOptions(this);
// do something
// The 'Loader' does not perform any conversion
return source;
};
module.exports = LoadrFunc
Copy the code
How to implement a Loader
ES6 conversion ES5 loader to example evolution, see how to implement a similar loader
First, install the Loader-utils toolkit
npm install loader-utils -D
Copy the code
Using the relevant Configuration
// A simple WebPack configuration
const path = require('path');
module.exports = {
entry: './main.js'.output: {
filename: 'bundle[hash:6].js'.path: path.resolve(__dirname, './dist'),},resolveLoader: {// The default is node_modules. If you can't find it, go to customLoaderDir
modules: ["node_modules",path.resolve(__dirname,"customLoaderDir")].// Alias mode, absolute path
/ / alias: {
// "es6ToEs5-loader":path.resolve(__dirname,"customLoaderDir","es6ToEs5-loader.js")
// }
},
module: { // Where the loader is mainly used
rules: [{test:/\.js$/.// Matches files with the.js suffix
use:{ // This is written as an object
loader: 'babel-loader'.options: {
presets: ['@babel/preset-env'].// Convert es6 to ES5}}}]}};Copy the code
Here I will write es6 conversion ES5 loader, named es6toES5-loader, using the structure of the conventional loader
Node_modules (customLoaderDir, customLoaderDir, customLoaderDir, customLoaderDir); The loader name is the name of the custom Loader JS file
// create es6toes5-loader.js in customLoaderDir
// Import the loader-utils package
let loaderUtils = require('loader-utils');
// Introduce the core of Babel
let babel = require("@babel/core")
function LoadrFunc (source) {
// Source is the parameter, which is the content of the file entity to process
// Get the options passed by the user to the current Loader
const options = loaderUtils.getOptions(this);
// This is asynchronous, so we need to call the asynchronous API async. Here we can print this to see what other methods and properties are available
let callback = this.async()
// Through the Babel core quasi - substitution syntaxbabel.transform(source,{ ... options,sourceMap:true.// This can also be done in loader configuration options
fileNmae: this.resourcePath.split("/").pop() // Give the map file a nickname
},function (err,result) {
The callback function takes two arguments, a failure cause and a result
// result.code Specifies the converted code
// result.map is the source of the mapping
callback(err,result.code,result.map)
})
// In this case, the return function has no use, because the above is a callback function, obviously asynchronous processing, so the core of the callback function
// return source;
};
module.exports = LoadrFunc
Copy the code
Ok, through a simple example, we can clearly understand how loader is implemented in Webpack. In the next chapter, I will share the principle of Plugin plug-in in Webpack
Small encouragement, great growth, welcome to praise