This article will briefly introduce Webpack Loader, and how to write a loader to meet its own needs, so as to improve the understanding and use of Webpack, and strive to advance the configuration engineer for Webpack.

Webpack Loader

Webpack must be front-end circle of people know, most people are more or less used. Simply put, it can load resource files, and perform some processing on these files, such as compilation, compression, and finally packaged together into the specified file. It can be said that as a packaging tool, in the wave of front-end engineering, played a mainstay role.

So a very important part of WebPack is the ability to do some processing with loaded resource files. For example, to compile less and Sass files into CSS files, the webpack loader is responsible for this process.

Loader is used to convert the module source code. Loader allows you to preprocess files when importing or “loading” modules. As such, Loader is similar to “tasks” in other build tools and provides a powerful way to handle the front-end build steps.

A slightly more complex example is vue-loader, which is described on its website as follows:

Vue-loader is a Webpack loader that converts vUE components written in a specified format into JavaScript modules.

The Vue component is divided into three parts by default,

What Loader do you need

We know that WebPack’s power rests on powerful loaders (as well as plugins, which will not be covered in this article). To really play Webpack, we have to master loader. Before we can use them, we need to know what loader we need. If you want to compile less, you can use less-loader; To load an HTML file and package a static file within its chain, use html-loader. Whenever we want to process a file, we can go to the corresponding loader.

What should I do if I can’t find the loader I want?

For example, I encountered a requirement a few days ago that I want to load HTML files nested in a layout.html file. As follows:

<! -- layout.html -->

      
<html>
<head>
  <meta charset="utf-8">
  <title>Pure Web</title>
  <meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
</head>
<body>
  <header>This is Header</header>

  <! -- I want the HTML I load with webpack to be nested in this {{__content__}} section -->
  {{__content__}}

  <footer>This is footer</header>
</body>
</html>Copy the code

This way, if I’m writing a multi-page application, I only need to write the only different central content, and leave out the common parts of the site as layout.

Unfortunately, html-loader can only help me load an HTML file from another HTML file, like this:

<body>
  ${require('@/htmls/header.html')}
  ${require('@/htmls/index.html')}
  ${require('@/htmls/footer.html')}
</body>Copy the code

This removes the common parts, but I still need to refer to them in each HTML file, and to keep the HTML structure in order, I have to cite the header and footer in each file again, instead of introducing them as a single layout. So it’s not exactly what I need.

What should we do? We have no choice but to write by ourselves.

Write a WebPack loader

First of all, we should read the webpack website: how to write a loader?

Loader receives a string (or buffer) and returns the string (or buffer). Webpack passes the loaded resource as a parameter to the Loader method, passes it to the Loader for processing, and returns it.

In my requirement, I put the HTML I loaded into the layout I set, and then return the HTML processed. The code looks like this:

// {string} source: the string value of the loaded HTML
module.exports = function (source) {
  return getLayoutHtml().replace('{{__content__}}', source)
}Copy the code

Think about it briefly, find it works, and start writing it.

Start trying to

So, as a first step, we just implement a getLayoutHtml method to get the layout. If you think about it, the layout file should be declared by configuration, and then you can use the Node API to load the file according to the configuration.

Refer to the Node and Webpack documentation to obtain the loader configuration items from loader-utils. To load the file from Node’s fs.readfilesync, we might write:

module.exports = function (source) {
  const options = loaderUtils.getOptions(this)
  const layoutHtml = fs.readFileSync(options.layout, 'utf-8')
  return layoutHtml.replace('{{__content__}}', source)
}Copy the code

Webpack config adds the following loader configuration:

{
  test: /\.(html)$/.loader: 'html-layout-loader'.include: htmlPath, // the htmls you want inject to layout
  options: {
    layout: layoutHtmlPath // the path of default layout html}}Copy the code

Incredibly, this is a basic HTML-layout-loader. Of course, this is the real start of making Loader usable and useful. We still have a lot of things to consider.

Perfect your own loader

Once it was clear that the code was working, we had to refine our feature points, and when I thought about it, I probably needed to consider the following features:

  1. You should be able to create your own layout file for each HTML you load, rather than having to load the same layout for all HTML.
  2. A placeholder for the replacement{{__content__}}It should also be configurable.

In addition, you need to consider handling exceptions, such as template files that cannot be found.

After completing the requirements, we can write the code again, this time I will not explain the code line by line, directly put the link: htML-layout-loader.

The code is also relatively simple, which is to achieve their basic requirements, if you are interested in the introduction of readme.

Write in the last

When faced with a big problem, the first thought is to search for a solution, but the reality is that there is no solution. In this case, we can also try to write some plug-ins, components, or a general solution to solve our own problems and gain some knowledge at the same time. And it’s not that hard after all.

In addition, if this loader is also helpful to readers, please feel free to use it. If you have any questions or ideas, please feel free to issue or PR.

Please get my authorization before reprinting.