26-analysis of the event flow of Webpack source make (1)

Source: Internet
Author: User
Tags semaphore

In the compilation event stream, the flow of events is still injected into the detail steps, and the Code flow

// apply = This-compilation //  //  return compialtionthis. newcompilation (params); this. Applypluginsparallel ("Make", compilation, err = {    //  callback ... });

After the compilation event stream is triggered, a compilation object is returned directly and then the next event stream make is triggered.

The source of make is in the Entryoptionplugin plug-in, which, whether the entry parameter is a single-entry string, a single-entry array, a multi-entry object, or a dynamic function, injects a make event after the corresponding entry plug-in is introduced.

First, take the simplest single-entry string as an example to start running the make event stream:

// singleentryplugincompiler.plugin ("Make", (compilation, callback) = {    //  Generates a dependency class of type single entry    //  dep.loc = name    const DEP = Singleentryplugin.createdependency (this. Name);    Compilation.addentry (this. Name, callback);});

Compilation.addentry

This returns to the compilation class, calling the prototype function AddEntry.

Class Compilation extends Tapable {// ...    //context = default = PROCESS.CWD ()    //entry = DEP = Singleentrydependency    //name = Single entry default to main    //callback = the process behindaddentry (context, entry, name, callback) {const slot={name:name, module:NULL        }; //initial to []         This. Preparedchunks.push (slot);  This. _addmodulechain (Context, entry, (module) and = {/**/}, (err, module) = = {/**/ }); }}

Compilation._addmodulechain

Nothing to say, go directly into the _addmodulechain function:

Class Compilation extends Tapable {// ..._addmodulechain (context, dependency, Onmodule, callback) {//Profile = Options.profile        //do not preach then start is undefinedConst START = This. Profile &&Date.now (); //bail = Options.bailConst ERRORANDCALLBACK = This. bail? (err) = ={callback (ERR); }: (Err)={err.dependencies=[dependency];  This. Errors.push (ERR);        Callback ();        }; if(typeofDependency!== "Object" | | Dependency = = =NULL|| !dependency.constructor) {Throw NewError ("Parameter ' dependency ' must be a dependency"); }        //Dependencyfactories contains all of the dependent collectionsConst Modulefactory = This. Dependencyfactories.get (Dependency.constructor); if(!modulefactory) {            Throw NewError (' No dependency factory available for  Thisdependency type: ${dependency.constructor.name} '); }         This. Semaphore.acquire (() = {/**/ }); }}

Profile and bail parameters will probably not be transmitted, all directly ignored.

The next step is to try to get the value of the dependency class from Dependencyfactories, the map object all values are set in the compilation event stream, the details can be seen in section 24 of the flowchart, Portal: http://www.cnblogs.com/ Qh-jimmy/p/8183840.html

Here, the dependency class originates from the singleentrydependency, and the key-value pairs are set at the same location from Singleentryplugin:

// singleentrypluginCompiler.plugin ("Compilation", (compilation, params)    = =  params.normalmodulefactory;     // here     Compilation.dependencyFactories.set (singleentrydependency, normalmodulefactory);});

So it's easy to call get here and take out the normalmodulefactory.

And this normalmodulefactory, in section 18, there is a brief introduction and analysis of the ruleset of module.rules processing, Portal: http://www.cnblogs.com/QH-Jimmy/p/8109903.html

  

Semaphore

After getting the corresponding modulefactory, call the This.semaphore which is to generate a new class:

 This New Semaphore (options.parallelism | | 100);

(The name of the class English translation is the signal machine)

The content is relatively simple, over the source code:

class Semaphore {//a number defaults toConstructor (available) { This. Available =available;  This. Waiters = [];    }; //when available is greater than 0 o'clock execute callback and subtract 1    //otherwise the callback will bounce into the waitersAcquire (callback) {if( This. Available > 0) {             This. available--;        Callback (); } Else {             This. Waiters.push (callback);    }    }; //attempt to remove the recently bounced callback and execute at the end of the event streamrelease () {if( This. waiters.length > 0) {Const callback= This. Waiters.pop ();        Process.nexttick (callback); } Else {             This. available++; }    }}

The design does look like a signal machine, and the constructor has an initial number of uses and an array of callback to execute.

Each time you call acquire, a callback is passed in, and if the number of times is positive callback is executed and the number of uses minus 1, if the number of times is exhausted, the callback is bounced into the waiters array.

Each time the release is called, the number of uses plus 1 is used to try to fetch the latest callback and execute as soon as possible, if there is no callback to execute.

Normalmodulefactory.create

In other words, the following code can be understood as a simple function call:

this. Semaphore.acquire (() = {    modulefactory.create {        contextinfo: {            "",              This . Compiler.name        },        Context:context,        dependencies: [Dependency]    /*  */ });});

In this way, the process runs to the Normalmodulefactory prototype method create.

class Normalmodulefactory extends Tapable {/*data = {contextinfo:{issuer: ', compiler:this.compile R.name//undefined}, Context:context,//PROCESS.CWD () dependencies: [Singleentrydepen Dency]}*/Create (data, callback) {const dependencies=data.dependencies; //try to fetch the cacheConst CACHEENTRY = dependencies[0].__normalmodulefactorycache; if(CacheEntry)returnCallbackNULL, CacheEntry); //context = PROCESS.CWD ()Const CONTEXT = Data.context | | This. Context; //Portal File String = =./input.jsConst REQUEST = Dependencies[0].request; Const ContextInfo= Data.contextinfo | | {};  This. Applypluginsasyncwaterfall ("Before-resolve", {contextinfo, context, request, dependencies}, (err, result) 
    = = {/**/ }); }}

This consolidates the context, the portal file, the Ingress module dependency class, and then starts triggering the flow of events on the Normalmodulefactory class.

About Normalmodulefactory's event flow injection, all in section 24 is described, and then a portal: http://www.cnblogs.com/QH-Jimmy/p/8183840.html

The event flow before-resolve here is not, so follow the tapable in the Applypluginsasyncwaterfall execution mode:

function Applypluginsasyncwaterfall (name, init, callback) {    if (!  Thisreturn callback (null, init);     // More ...}

This will call callback directly, passing NULL with the second argument, as follows:

 This. Applypluginsasyncwaterfall ("Before-resolve", {contextinfo, context, request, dependencies},//err = null    //result = the object above(err, result) = = {        if(ERR)returncallback (ERR); if(!result)returncallback (); //triggering the factory event streamConst FACTORY = This. ApplyPluginsWaterfall0 ("Factory",NULL); //ignored        if(!factory)returncallback (); Factory (result, (Err, module)= = {/**/ }); });

This will then trigger the factory event stream, which is directly plugin in the constructor.

class Normalmodulefactory extends Tapable {    Constructor (context, resolvers, options) {        super ();         // ... other property        this. Plugin ("Factory", () = = (result, callback) and            {thisnull  );             if return callback ();             /**/  });        });    }}

This also triggers the resolver event stream, which is another plugin event in the constructor.

This section is here first.

. 26-Analysis of Webpack source event flow make (1)

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.