Explore the Webpack plugin mechanism

Source: Internet
Author: User
Tags emit function prototype new set

Webpack is a pleasant and worrying, powerful but requires a certain amount of learning costs. Before exploring the Webpack plug-in mechanism, we need to understand an interesting thing, the Webpack plug-in mechanism is the skeleton of the entire Webpack tool, and Webpack itself is built using this plug-in mechanism. Therefore, in-depth understanding of the Webpack plug-in mechanism, then to carry out the relevant optimization of the project, it will certainly be beneficial.

Webpack Plug-in

Let's go first. Application of Webpack plug-in in project

const=require('myplugin')const=require('webpack')webpack({  ...,  plugins: [newMyPlugin()]  ...,})

So what are the conditions that can be used as Webpack plugins? In general, the Webpack plugin has the following features:

    1. Independent JS module, exposing the corresponding function

    2. The Apply method on the function prototype injects the compiler object

    3. The corresponding Webpack event hooks are mounted on the compiler object

    4. The callback function of the event hook can get the compiled compilation object, if it is an asynchronous hook can get the corresponding callback

Here's a combination of code to see:

function   Myplugin  (options) {}  //2. The Apply method on a function prototype injects a compiler object  myplugin . prototype . apply  =  function  (compiler) { //3.compiler object is mounted on the corresponding Webpack event Hook 4. The callback function of the event hook can get the compiled compilation object 
      compiler . plugin  ( ' emit '  ,  (Compilation callback) =>  { ... } ) }  //1. Separate JS module, exposing the corresponding function  module . exports  =  Myplugin  

This way, the basic outline of the Webpack plug-in is sketched out, at this point there are a few questions,

    1. Question 1: Why do you define the Apply method on the prototype of a function? After reading the source code found in the source code by plugin.apply() calling the plugin.
const= (options,=>{  ...  for (constoptions.plugins{    plugin.apply(compiler);  }  ...}
    1. What is the question 2:compiler object?

    2. Question what is the event hooks on the 3:compiler object?

    3. Question 4: What is the compilation object that can be obtained in the callback function of the event hook?

These questions are also the clues of this article, let us explore one by one.

Compiler object

Compiler is the Webpack Editor object, when the Webpack is called, the compiler object is initialized automatically, the source code is as follows:

//Webpack/lib/webpack.jsConstCompiler= require("./compiler")ConstWebpack=(Options,Callback= {... options= New Webpackoptionsdefaulter().Process(options)//Initialize the Webpack configuration parameters   LetCompiler= New Compiler(Options.Context)//Initialize the compiler object, where Options.context is PROCESS.CWD ()  compiler.Options =Options//Add initialization parameters to compiler  New Nodeenvironmentplugin().Apply(compiler)//Add Node environment-related methods to compiler   for(ConstPlugin ofOptions.Plugins){    plugin.Apply(compiler);  }...}

Finally, the compiler object contains all the Webpack configurable content, and when developing the plugin, we can get all the content related to the Webpack master environment from the compiler object.

Compilation Object

The compilation object represents a single version build and build resource. When you run Webpack, whenever a file change is detected, a new compilation is created to generate a new set of compilation resources. A compiled object shows the current module resources, compiled build resources, changed files, and status information that is tracked.

In combination with the source code to understand the above paragraph, first webpack in each execution will be called compiler.run() (source location), and then trace the Oncompiled function passed the compilation parameter, you can find compilation from the constructor compilation.

// webpack/lib/Compiler.jsconst=require("./Compilation");newCompilation{  const=newCompilation(this);  ...  return compilation;}
Have to mention the Tapable library

After introducing the compiler object and the compilation object, we have to mention tapable this library, which exposes all the pub/sub methods associated with the event. and the function Compiler and function compilation inherit from Tapable.

Event Hooks

Event hooks are actually life-cycle functions like the MVVM framework, which can be handled in a specific way at a particular stage. Understanding some of the common event hooks is the pre-condition for writing Webpack plug-ins, here are some common event hooks and their effects:

Hooks function Parameters type
After-plugins After you set up a set of initialization plug-ins Compiler Sync
After-resolvers After setting up resolvers Compiler Sync
Run Before reading a record Compiler Async
Compile Before you create a new compilation Compilationparams Sync
Compilation Compilation Creation Complete Compilation Sync
Emit Before generating a resource and outputting it to a directory Compilation Async
After-emit After generating the resource and outputting it to the directory Compilation Async
Done Finish compiling Stats Sync

Please refer to the official documentation manual, and browse the relevant source code to see the definition of each event hook.

Analysis of plug-in process

Take emit hook for example, the following analysis under the plug-in call source code:

compiler.plugin('emit', (compilation,=>{  // 在生成资源并输出到目录之前完成某些逻辑})

The plugin function called here originates from the Tapable library mentioned above, and its final call stack points to Hook.tapasync (), which acts like Eventemitter on, with the following source code:

//Tapable.jsOptions= {...if(Hook!== undefined){    ConstTapopt= {      name: Options.fn.name || "Unnamed Compat plugin",      Stage: Options.Stage || 0    };    if(Options.Async)Hook.Tapasync(tapopt, Options.fn); //Inject the callback function of the asynchronous hooks in the plug-in    Else      Hook.Tap(tapopt, Options.fn);    return true;  }};

There is an injection must trigger the place, the source code through the Callasync method to trigger the asynchronous event injected before, callasync similar to Eventemitter emit, the relevant source code is as follows:

this.hooks.emit.callAsync(compilation,=>{    ifreturncallback(err);    =compilation.getPath(this.outputPath);    this.outputFileSystem.mkdirp(outputPath, emitFiles);});

Some in-depth details here will not unfold, say about reading more large-scale projects of the source of two points of experience,

    • To catch a main line to read, ignoring the details. Otherwise it will waste a lot of time and will be frustrated;

    • Combined with debugging tools to analyze, many points without debugging tools, it is easy to forgotten how;

Hands-on implementation of a Webpack plugin

Combined with the above knowledge point analysis, it is not difficult to write their own webpack plug-ins, the key lies in the idea. In order to count the effective use of webpack packages in the project, we upgraded the code on the basis of fork Webpack-visualizer and the project address. The effect is as follows:

The plug-in core code is based on the emit hooks mentioned above, as well as the compiler and compilation objects. The code is as follows:

classAnalyzewebpackplugin{  Constructor(OPTs= { filename: ' analyze.html ' }){     This.opts =OPTs}  Apply(compiler){    ConstSelf=  This    compiler.plugin("Emit", function(Compilation,Callback{       LetStats= compilation.GetStats().ToJson({ Chunkmodules: true })//Get the status of each module       LetStringifiedstats= JSON.stringify(stats)//service-Side rendering       LetHtml= ' <!doctype html><meta charset= "UTF-8" ><title>AnalyzeWebpackPlugin</title><style>${Cssstring}</style><div id= "App" ></div><script>window.stats =${Stringifiedstats};</script><script>${Jsstring}</script>      `      compilation.Assets[`${ Self.opts.filename}`]= { //Generate file path        Source:()=Html,        size:()= HTML.length      }      Callback()})}}
Resources

See the real Webpack plugin

Webpack official website

Explore the Webpack plugin mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.