Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

preface

The webpack5.x update is one year old, and so far the webpack discussion has been summed up in just one word YYDS, so if you still don’t know how to develop a loader, this article is worth reading. The article is more friendly to the novice oh ~ which various descriptions are very nanny please understand (I have a nanny heart), have webpack configuration basis directly from the [loader how to implement] start to see,

The power of WebPack rests on various loaders and plugins.

What is the loader

Let’s explain it with a basic example

  1. Create a write-loader folder

  2. NPM init-y initializes

  3. npm install webpack webpack-cli

Create the directory structure as shown

In SRC > index.js we write a little code

function add(a, b) {
  return a + b
}
add(1, 2)
Copy the code

Assuming that this code is all our project code, the next step is to introduce this JS into THE HTML file. However, in consideration of saving server resources, we hope to package and compress the project before launching the project, so the ability of Webpack will come into play

const path = require('path')

module.exports = {
  mode: 'development',
  entry: {
    main: './src/index.js'
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js',
  }
}
Copy the code

Webpack configuration properties are not familiar with the official website! Or how many webpack configuration articles the Nuggets already have. Then we go to package.js to configure a command for easy execution

. "Scripts ": {"test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack --config webpack.config.js" },Copy the code

Finally, execute NPM run dev and you’ll see that the package is successfully packaged, with the dist folder in the root directory lying quietly in main.js. Next, import mian.js directly into index.html to see it printed

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta  name="viewport" content="width=device-width, <script SRC ="./dist/main.js"></script> </head> <body> <div id="app">hello world</div> </body> </html>Copy the code

The above is the most basic configuration of Webpack, this part should appear in this article (how I can not change the nanny mentality)

Back to what is loader? Now when I want to change the color of the Hello World text in HTML, in the single-page application craze these days, we write CSS like this:

// src > style.css
#app{
  font-size: 30px;
  font-weight: bold;
  color: red;
}
Copy the code

The styles are ready to be introduced in index.js:

Function add(a, b) {return a + b} add(1, 2)Copy the code

What do you see when you do the packaging?

Error!!!!!

We need a CSS-Loader to help WebPack parse CSS syntax. We need a csS-Loader to help WebPack parse CSS syntax. Style-loader is used to load parsed CSS codes into HTML files with style tags. Run the NPM I CSs-loader style-loader command

Modify the webPack configuration file:

const path = require('path') module.exports = { mode: 'development', entry: { main: './src/index.js' }, module: {rules: [{test: / \. CSS $/, / / + + + regular matching. The CSS file suffix use: ['style-loader', 'css-loader']}]}, output: {path: path.resolve(__dirname, 'dist'), filename: 'main.js', } }Copy the code

NPM run dev again, comfortable, you can see our CSS at line 19 of the packaged main.js

This means that our CSS is packaged together with js code, which is still usable.

Webpack loader helps Webpack parse or execute files that webpack cannot do by itself

How to implement loader

You already know the role of Loader. What’s more, we need to further understand the underlying principle of Loader

1. The principle of the loader

The official Webpack documentation tells us the following:

1. Loader is a function

2. The loader function must return string or buffer

3. The loader parameter is the matched content *

And the design principles of Webpack Loader should follow:

1. Single responsibility (low coupling and higher loader reuse)

2. Chain combination (files that have been operated by one loader can be continued by another loader)

3. Modularization (Each Loader should be written as a module)

4. Stateless (Loader should not have its own state, think react stateless components you will see a lot)

5. Combine loader-utils (explained later)

6. Loader integrates dependencies

7. Common code

Loader-utils is important for loader writing. The code is the best explanation. Create loader-util file in the root directory

Function loader(content) {console.log(' inside loader '); return 'hello' } module.exports = loaderCopy the code

Consider it a loader we wrote and use it:

// webpack.config.js module: {rules: [(... omitted some code) {test: /\.js$/, use: [{loader: path.resolve('./loader-util.js'), options: { name: 'wn' } } ] }, ] }Copy the code

When webpack compilation matches a js file, the loader function in loader-util.js will be called to test NPM run dev

Sure enough, add another line to print:

Function loader(content) {console.log(' inside loader '); console.log(content); // +++ return 'hello' }Copy the code

Run the compile and you will see:

This is the code we wrote in the JS file. 3. The loader argument is the current matched content.

Loader-utils can be used to obtain the parameters that are passed by the loader function. This is a webpack method that is allowed to pass parameters to the loader function. Add the following code to loader-util.js:

Const loaderUtils = require('loader-utils') // +++ function loader(content) {console.log(' inside loader '); console.log(content); console.log(loaderUtils.getOptions(this)); // +++ return 'hello' } module.exports = loaderCopy the code

GetOptions is a method provided by loader-utils to go back to the options argument, so you can see what’s going on and can’t wait to execute the package:

Loader-utils: Loader utils: loader utils: Loader utils: Loader utils: Loader utils: Loader utils

Loader loader loader loader loader loader Loader Loader Loader Loader Loader loader loader

2. Implementation of Loader

Let’s create a requirement, for example: I have a requirement to implement HTML file packaging, according to the design principle of a single responsibility, this requirement should contain two functions

  1. Parsing HTML syntax
  2. HTML file compression

That is to say, such a requirement should be designed into two Loaders to complete, considering the first function of parsing HTML syntax loader implementation is too complex, we will use a node library existing HTMl-loader to complete, we will manually implement the second function.

Create an html-minify-loader.js file in the root directory

// html-minify-loader.js

module.exports = function(source) {
  console.log(source);
}
Copy the code

As you already know, the source argument will program the matching HTML code. Add app.js and example. HTML to SRC

// example.html <! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta  name="viewport" content="width=device-width, > <title>Document</title> </head> <body> example </body> </ HTML >Copy the code
// app.js

var html = require('./example.html')
console.log(html);
Copy the code

Now let’s go modify the configuration file

// webpack.config.js const path = require('path') module.exports = { mode: 'development', entry: { main: '. / SRC/app. Js' / / entrance to app. Js}, the module: {rules: [{$/ test: / \. HTML, use: ['html-loader', // this requires NPM I html-loader installation {loader: Path.resolve ('./html-minify-loader.js'), // introduce our own loader options: {comments: }}]}, output: {path: path.resolve(__dirname, 'dist'), filename: 'main.js',}}Copy the code

In order to compress HTML, the htML-minify-loader can reasonably eliminate whitespace and newlines in HTML code. This can be done by writing your own regulars, or by using a disarmed wheel. We’re really just talking about how loader works, and all the other difficulties we encounter with this requirement are solved with wheels, NPM I can take care of

// html-minify-loader.js var Minimize = require('minimize') var loaderUtils = require('loader-utils') module.exports = function(source) { // console.log(source); / / var options to configure the options parameter = loaderUtils. GetOptions (this) | | {} / / give parameters to minimize the var minimize = new Minimize(options); // Return minimize compressed HTML code returns minimize. Parse (source); }Copy the code

Dist > main.js and you can find the compressed HTML for Example

You understand a big factory interviewer often test questions, next time write project encounter, can try to write a laoder!

The source address

reference

website

IKamp # Teach you to lift a Webpack Loader by hand