This is the 9th day of my participation in Gwen Challenge

1. Differences between Loader and Plugin

1.1 Loader

Loader is a file loader that loads resource files, performs some processing, such as compilation and compression, on these files, and finally packages them into a specified file.

Loader features:

Multiple Loaders can be used to process a file. The execution sequence of loaders is reversed, that is, the last loader is executed first and the first loader is executed last. The first loader that executes receives the contents of the source file as a parameter, and the other Loaders receive the return value of the previous loader that executes as a parameter. The last loader to execute returns the JavaScript source code for this module. Loaders can be synchronous or asynchronous. Loader runs node.js and can do everything possible. The loader receives the Query parameter. These parameters are passed inside the Loaders as configuration. Loaders can be published or installed using NPM. In addition to the loader exported using package.json’s main, general modules can also export a Loader.

1.2 the Plugin

Plugin extends the functionality of WebPack. It works directly on WebPack, extending its capabilities. Of course loader also extends Webpack in a way, but it only focuses on the area of transform files. Plugin features are more rich, not limited to the loading of resources.

A number of events are broadcast during the life cycle of a Webpack run, and the Plugin can listen for these events and change the output when appropriate through the API provided by Webpack.

1.3 What is the difference between plugin and Loader?

For loader, it is A converter to compile file A into file B. For example, a.css or A.less is converted to B. CSS

Plugin is an extender, which enrichis Wepack itself. It is aimed at the whole process of Webpack packaging after loader ends. It does not operate files directly, but works based on the event mechanism, and will listen to some nodes in the process of Webpack packaging to perform a wide range of tasks.

In use: Loader can be used without import, while plugin needs import to be used.

2, how to write a Loader

A loader is simply a JavaScript module exported as a function. The Loader Runner calls this function and passes in the result or resource file generated by the previous loader. The function’s this context will be populated by Webpack, and the Loader Runner has some useful methods to change the Loader to make asynchronous calls, or to get query parameters.

The first loader passes in only one argument: the contents of the resource file. Compiler needs to get the processing results generated by the last loader. The result should be a String or Buffer (converted to a String) that represents the JavaScript source code for the module. An optional SourceMap result (formatted as a JSON object) can also be passed.

If the result is a single process, it can be returned directly in synchronous mode. If there are multiple processing results, this.callback() must be called. In asynchronous mode, this.async() must be called to instruct the Loader runner to wait for the asynchronous result, which will return the this.callback() callback, which must then return undefined and call the callback.

Write the entry’s index.js file under SRC with the following contents

console.log('hello webapck')
console.log('http://blog.dunizb.com')
Copy the code

We need to write a Loader to process this file and replace the string hello with the string we passed in (options.name).

// Synchronous mode
const loaderUtils = require('loader-utils')
module.exports = function(source) {
    // console.log(this.query)
    const options = loaderUtils.getOptions(this)
    const result = source.replace('hello', options.name)
    this.callback(null, result)
}
Copy the code
// Asynchronous mode
const loaderUtils = require('loader-utils')
module.exports = function(source) {
    const options = loaderUtils.getOptions(this)
    const callback = this.async();
    setTimeout(() = > {
        const result = source.replace('hello', options.name)
        callback(null, result);
    }, 1000);
}
Copy the code

Webpack.config. js uses the Loader you’ve written

const path = require('path')
module.exports = {
    mode: 'development'.entry: './src/index.js'.output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    resolveLoader: {
        modules: ['node_modules'.'./loaders'].// When you reference a Loader it looks for node_modules, and if it can't find node_modules./loaders looks for node_modules
    },
    module: {
        rules: [{
            test: /\.js$/,
            use: [
                {
                    // loader: path.resolve(__dirname, './loaders/replaceLoaderAsync.js'),
                    loader: 'replaceLoaderAsync'.options: {
                        name: 'https'}}, {// loader: path.resolve(__dirname, './loaders/replaceLoader.js'),
                    loader: 'replaceLoader'.options: {
                        name: 'hello'}}]}}Copy the code

3. How to write a Plugin

Plugin and Loader are different, a plug-in must be a Class, because we use plug-ins in the form of new XXXX (). We need to create a copyright file during build, so we write a Plugin to handle it.

Define the plugin

// Generate a copyright file
class CopyrightWebpackPlugin {
    constructor() {
        console.log('Plugin used')}apply(compiler) {    // This method is called when the plug-in is called
        // ...}}module.exports = CopyrightWebpackPlugin
Copy the code
/ / configuration webpack. Config. Js
const path = require('path')
const CopyrightWebpackPlugin = require('./plugins/copyright-webpack-plugin')
module.exports = {
    mode: 'development'.entry: './src/index.js'.output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    plugins: [
        new CopyrightWebpackPlugin()
    ]
}
Copy the code

When compiled with Webpack, the console prints “The plug-in is used.” Continue to supplement the apply method

// ...
// This method is called when the plug-in is called
// Compiler is an instance of Webpack
apply(compiler) {
    The emit hook is used to generate resources to the output directory. Asynchronous hooks
    // compilation stores all the contents of this compilation
    compiler.hooks.emit.tapAsync('CopyrightWebpackPlugin'.(compilation, cb) = > {
        / / add copyright. TXT
        compilation.assets['copyright.txt'] = {
            source: function() {
                return 'Copyright by Dunizb'
            },
            size: function() { // File size, length
                return 20;
            }
        }
        cb(); // It must be called last})}Copy the code

Tap is called directly if it is synchronous.

The result of the compilation is as follows. You can see that the package contains an additional copyright. TXT file with a size of 20 bytes. In addition, a file named Copyright. TXT with “Copyright by Dunizb” was generated in the final packaged dist directory.