preface
When I build a project from zero at ordinary times, although I am familiar with the basic configuration, such as configuring file-loader, URL-loader, CSS-loader, etc., it is not difficult to configure, but how does it work? Today, I will talk about how to write a Webpack loader.
Loader role
According to my own simple understanding, loader usually refers to the package scheme, that is, how to handle the package, when it can take the module source code, after the specific loader conversion to return the new result.
For example, Sass-Loader can convert SCSS code into CSS code
Write the Loader
Keep the function simple
There may be a lot of configuration in our project, but remember that to keep the functions of a Loader single, avoid doing multiple functions, just complete one function conversion.
Therefore, for example, converting less files into CSS files is not a step in one step, but the chain calls of less-loader, CSS-loader, and style-loader can complete the conversion.
The module
Since Webpack itself runs on node.js, a loader is essentially a Node module that exports a function:
module.exports = function (source) {
// source is the original content of a file passed to the Loader by the Compiler
/ / processing...
return source // We need to return the processed content
}
Copy the code
The job of this exported function is to get the original content before processing, perform processing on the original content, and return the processed content.
Loader to replace strings
For example, if we want to replace the string of the source file when we package, we can use Loader, because Loader takes the content of the source file, processes it, and returns it.
For example, there are three files in the SRC directory:
src/msg1.js
export const msg1 = 'Learning framework'
Copy the code
src/msg2.js
export const msg2 = 'Deep understanding of JS'
Copy the code
src/index.js
import { msg1 } from './msg1'
import { msg2 } from './msg2'
function print() {
console.log(` output:${msg1}.${msg2}`)
} print() Copy the code
All you have to do is import msg1 and MSg2 files and print two strings.
So what we’re going to do is we’re going to change “framework” to “React framework “and “JS” to “JavaScript”.
New SRC/loaders/replaceLoader js file,
module.exports = function (source) {
const handleContent = source.replace('frame'.'the React framework').replace('JS'.'JavaScript')
return handleContent
}
Copy the code
Loader is finished!!
Source is the content of the source file.
Using the Loader
Next, we’ll use it to create a new file, webpack.config.js, in the root directory
const path = require('path')
module.exports = {
mode: 'production'. entry: './src/index.js'. module: { rules: [ { test: /\.js$/. use: './src/loaders/replaceLoader.js'. }, ]. }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js'. }, } Copy the code
Execute NPX webpack to see the package result dist/main.js
((a)= >{"use strict";console.log("Output: Learn the React framework for an in-depth understanding of JavaScript")}) ();Copy the code
Replacement successful!
Please note that the loader filled in use is found in node_modules directory. Since we are a custom loader, we cannot write use directly: ‘replaceLoader’, but it’s a bit awkward to write the path directly, we can configure it via Webpack:
module.exports = {
resolveLoader: {
modules: ['node_modules'.'./src/loaders'].// node_modules cannot be found, go to./ SRC /loaders
},
module: {
rules: [ { test: /\.js$/. use: 'replaceLoader'. }, ]. }, } Copy the code
Obtain loader options
When we’re done, let’s think about it, we’re actually writing a function.
Of course, this is just the simplest example, what if loader could pass in arguments like:
module: {
rules: [
{
test: /\.js$/. use: {
loader: 'replaceLoader'. options: { params: 'replaceString'. }, }, }, ].}, Copy the code
Query (this.query. Params, this.query. Params, this.query. Params, this.query.
Webpack, however, prefers the loader-utils module, which provides a number of useful tools, the most common of which is to get options passed to the Loader.
The first thing is to install
npm i -D loader-utils
Copy the code
Modify the SRC/loaders/replaceLoader. Js
const { getOptions } = require('loader-utils')
module.exports = function (source) {
console.log(getOptions(this)) // { params: 'replaceString' }
console.log(this.query.params) // replaceString
const handleContent = source.replace('frame'.'the React framework').replace('JS'.'JavaScript') return handleContent } Copy the code
The important thing to notice here is that the getOptions(this) argument is passed in as this, which means
Print result:
{ params: 'replaceString' }
{ params: 'replaceString' }
{ params: 'replaceString' }
Copy the code
this.callback()
All of the above return the converted content, but in some scenarios you need to return something else like sourceMap
module.exports = function (source) {
// Tells Webpack the result returned
this.callback(null, source, sourceMaps)
}
Copy the code
Return is also not needed, so you can use this API instead of return
const { getOptions } = require('loader-utils')
module.exports = function (source) {
const handleContent = source.replace('frame'.'the React framework').replace('JS'.'JavaScript')
this.callback(null, handleContent)
} Copy the code
Customize loader application scenarios
- Add a try catch block to all functions to catch errors and avoid manual additions.
- Implement Chinese and English substitution: text can be used as placeholders such as
{{ title }}
Package, placeholder detected according to the environment variable is replaced with Chinese and English.
- Ps: Personal technical blog Github warehouse, if you feel good welcome star, give me a little encouragement to continue writing ~