Webpack loader
What is loader?
Loader is a file loader that can load different resources and perform operations on these files, such as compilation, compression, and finally packaging to a specified file.
- A file can be parsed by multiple Loaders. Loaders are loaded in reverse order, from the last loader upwards
- Each loader file provides a function and the arguments are the contents of the parsed file. When multiple loaders are executed, the arguments for each loader are the results of the previous loader’s execution
2. Hand write a Loader
Requirement: Remove all console.log from Javascript code
The directory structure
|-- package-lock.json
|-- package.json
|-- README.md
|-- webpack.config.js / / webpack configuration
|-- loaders
| |-- del-log-loader.js // Delete the loader of console.log
| |-- tranform-async.js // Process the asynchronous loader
|-- src
|-- index.js // Object file
Copy the code
1. Implement delete code inconsole.log
1.1 webpack.config.js
Export the configuration as follows
const path = require('path')
module.exports = {
mode: 'development'.entry: {
main: './src/index.js',},output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js'
},
module: {
rules: [{
test: /\.js$/,
use: [
{
loader: path.resolve(__dirname, 'loaders/del-log-loader.js')}]}],},};Copy the code
1.2src /index.js
class Animation {
run(a, b) {
console.log('running... ');
returna + b; }}const an = new Animation();
an.run(1.2);
Copy the code
1.3 Write del-log-Loader, the main function of the loader to receive the target JS, the code inconsole.log
Remove and return the processed result.
module.exports = function (source) {
const reg = /console.log\([\s\S]*? \); /g;
source = source.replace(reg, ' ');
return source;
}
Copy the code
1.4 inpackage.json
Add to file"build": "webpack"
instruction
"scripts": {
+ "build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
}
Copy the code
1.5 performnpm run build
Command to obtain the processed result
eval("\r\nclass Animation {\r\n run(a, b) {\r\n \r\n return a + b; \r\n }\r\n}\r\nconst an = new Animation()\r\nan.run(1, 2)\n\n//# sourceURL=webpack://demo1/./src/index.js?");
Copy the code
2. Loader returns multiple parameters
Usually write loader, sometimes need to pass to the next loader extra parameter, due to the return return value limits, but fortunately the loader provides a callback will drop function accept multiple parameters (note: the first three parameters must be error, the source and map)
2.1 to modifydel-log-loader
module.exports = function (source) { const reg = /console.log\([\s\S]*? \); /g;+ const error = null
+ const map = {
+ name: 'zhang SAN'
+}
source = source.replace(reg, '');
+ this.callback(error, source, map)
}
Copy the code
2.2 Add another Loader to verify the result
module.exports = function (source, map) {
console.log(map)
return source
}
Copy the code
3. Verify the options parameter in the Loader
In webPack configuration, options are usually passed to loader for use in the webpack. To obtain and verify options, two toolkits are provided: Loader-utils and Scheme-utils. Continue to improve the del-log-loader. In order to make users more flexible, you can pass parameters to decide whether to delete console.log
3.1 Webpack.config. js Modify the configuration
rules: [{
test: /\.js$/,
use: [
{
loader: path.resolve(__dirname, 'loaders/tranform-async.js')
},
{
loader: path.resolve(__dirname, 'loaders/del-log-loader.js'),
+ options: {
+ isDelLog: process.env.NODE_ENV === "production"
+}}}]].Copy the code
3.2 Modifying del-log-loader.js, adding the code for obtaining and verifying options
+ const schemaUtils = require('schema-utils'); / / check the options
+ const loaderUtils = require('loader-utils'); / / get the options
+ const schema = {
+ type: 'object',
+ properties: {
+ isDelLog: { type: 'boolean' }
+},
+ additionalProperties: false
+};
module.exports = function (source) {
+ const options = loaderUtils.getOptions(this);
+ schemaUtils.validate(schema, options, 'del-log-loader');
+ const { isDelLog } = options;
+ if (isDelLog) {
+ const reg = /console.log\([\s\S]*? \); /g;
+ source = source.replace(reg, '');
+}Const error = null const map = {name: 'span'} this.callback(error, source, map)}Copy the code
4. The transform – loader development
Transform-loader is an asynchronous loader that converts ES6 syntax to ES5 and returns the converted code. The development of asynchronous and synchronous loaders is basically the same, the difference is that asynchronous Loaders must call the async method in the loader context before returning.
In webpack.config.js, add transform-loader to rules, and put transform-loader before del-log-loader, because normal loaders are executed from the back, passing in the returned values.
use: [
+ {
+ loader: path.resolve(__dirname, 'loaders/tranform-async.js')
+},
{
loader: path.resolve(__dirname, 'loaders/del-log-loader.js'),
options: {
isDelLog: process.env.NODE_ENV === "production"}}]Copy the code
Edit transform-loader.js to accept the source and map returned by del-log-loader and return the transformation.
const babel = require('@babel/core'); // Use Babel to convert
module.exports = function (source) {
const callback = this.async();
babel.transform(source, {
presets: ['@babel/preset-env']},(err, result) = > {
const { code } = result;
callback(err, code, map);
});
}
Copy the code
results
var Animation = /*#__PURE__*/function () {
function Animation() {
_classCallCheck(this, Animation);
}
_createClass(Animation, [{
key: "run".value: function run(a, b) {
console.log('running... ');
returna + b; }}]);returnAnimation; } ();var an = new Animation();
an.run(1.2);
Copy the code
conclusion
From the basic implementation of a loader, parameter passing, and asynchronous loader development, in the daily development of basic can cope with some knowledge required to customize a loader, more detailed can see webpack’s official website.