What is loader?

Loader is a function that is executed during compilation of WebPack. Webpack does not recognize modules that do not end with JS and tells Webpack how to package certain files

Replace a string

Here I want to use loader to replace WORD with XXX, but I find there is no loader I want to use, so I have to write one myself

console.log('hello word');
Copy the code
// module.exports = function (source, map, export) meta) { return source.replace('word', 'xxx'); }Copy the code
// webpack.config.js
const path = require('path');

module.exports = {
	mode: 'development',
	entry: {
		main: './src/index.js'
	},
	module: {
		rules: [{
			test: /.js/,
			use: [
				{
					loader: path.resolve(__dirname, './loaders/replaceLoader.js'),
				},
			]
		}]
	},
	output: {
		path: path.resolve(__dirname, 'dist'),
		filename: '[name].js'
	}
}
Copy the code

Build result, custom loader implements our effect

Is it possible to pass the substitution as an argument?

The options of the Loader configuration are obtained from the loader function this.query

// loader
module.exports = function (source, map, meta) {
    const options = this.query;
    return source.replace('word', options.name);
}
Copy the code

Obtain the value from loader-utils

const loaderUtils = require('loader-utils');

module.exports = function(source) {
	const options = loaderUtils.getOptions(this);
	return source.replace('dell', options.name);
}
Copy the code
const path = require('path'); module.exports = { mode: 'development', entry: { main: './src/index.js' }, module: { rules: [ { test: /.js/, use: [{loader: path. Resolve (__dirname, '. / loaders/replaceLoader. Js'), / / the loader function is equivalent to pass parameters options: {name: '123123123' } } ] } ] }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js' }, };Copy the code

We import loader through path. Can we write loader name directly like less-loader? ResolveLoader can configure loader folder

const path = require('path'); Module.exports = {mode: 'development', entry: {main: './ SRC /index.js'}, // Custom loader folder resolveLoader: {modules: ['node_modules', './loaders'] }, module: { rules: [ { test: /.js/, use: [{// node_modules or loaders find replaceloader. js loader: 'replaceLoader', options: {name: '123123123' } } ] } ] }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].js' }, };Copy the code

this.callback

In addition to returning the value of the loader compilation, this. Callback can also be used

this.callback( err: Error | null, content: string | Buffer, sourceMap? : SourceMap, meta? : any );Copy the code
const loaderUtils = require('loader-utils');

module.exports = function(source) {
	const options = loaderUtils.getOptions(this);
	callback(null, source.replace('word', options.name));
}
Copy the code

Asynchronous loader (blocking)

Async loader, using this.async(), returns the value through the return value callback of this.async()

const loaderUtils = require('loader-utils');

module.exports = function(source) {
	const options = loaderUtils.getOptions(this);
	const callback = this.async();

	setTimeout(() => {
		const result = source.replace('word', options.name);
		callback(null, result);
	}, 1000);
}
Copy the code

What should I pay attention to when defining a loader

  1. Commonjs style
  2. It’s a function
  3. This cannot be the arrow function. There are a lot of arguments on this. See the webpack documentation

See more loader configurations

Webpack is definitely a huge system. This article only introduces how to define a loader completely. If you want to know more, you can see webpack Loader-API