.7-analysis of the Webpackoptionsdefaulter module of Webpack source code

Source: Internet
Author: User

Webpackoptionsdefaulter Module

After the parameter detection, according to the single/multi-configuration processing, this article is based on a single configuration, so will be carried out to the following code:

if (Array.isarray (options)) {    new Multicompiler (Options.map (options)  if (typeof options = = = = "Object")    {//  TODO webpack 4:process Returns options    //  The processing here is partly for webpack4.0 to prepare    new  Webpackoptionsdefaulter (). process (options);     //  ...}

The function of the module is to set the default value, the flowchart is as follows:

  

Enter the module:

"Use strict"= require ("./optionsdefaulter"= require ("./template"); class Webpackoptionsdefaulter extends Optionsdefaulter {    constructor () {        super ();          This false );         // a lot of This.set ...      = webpackoptionsdefaulter;

As you can see, the content of this module is written in ES6 's new syntax, well understood, because this module is only for webpack default settings, so the main function content should be on the prototype, directly into the Optionsdefaulter module:

"Use Strict";functionGetProperty (obj, name) {/**/ }functionSetProperty (obj, name, value) {/**/}class Optionsdefaulter {constructor () { This. defaults = {};  This. config = {}; } process (options) {//Todo:change this for webpack 4:options = Object.assign ({}, options);         for(Let nameinch  This. Defaults) {            Switch( This. Config[name]) {                //Case ...}}} set (name, config, def) {if(Arguments.length = = 3) {             This. defaults[name] =def;  This. config[name] =config; } Else {             This. defaults[name] =config; Delete  This. Config[name]; }}}module.exports= Optionsdefaulter;

This module is also written in ES6, the content is relatively simple, the main content is as follows:

1. A constructor defines two objects Defaults,config

2, two prototype methods Process,set

3, two tool methods Getproperty,setproperty

The constructor creates two objects, the Defaults object holds the default values for the parameters, and the Config object preserves the special handling of some parameters.

Since the prototype method relies on tool methods, it starts with a tool approach:

GetProperty

//obj is the optionsfunctiongetProperty (obj, name) {//Cut nameName = Name.split (".")); //notice this is length-1 .     for(Let i = 0; i < name.length-1; i++) {        //Layer Assignmentobj =Obj[name[i]]; //If obj non-object returns directly back to undefined        if(typeofObj!== "Object" | | !obj)return; }    //returns the value of the last layer    returnObj[name.pop ()];}

This function is interesting, directly look at the more confused force, need to take a case:

//obj = {entry: './inpuit.js ', Output:{filename: ' Output.js '}}//name = Output.filenamefunctiongetProperty (obj, name) {//get [output,filename] after cuttingName = Name.split (".")); //second jump out of the loop     for(Let i = 0; i < name.length-1; i++) {        //obj = {filename: ' output.js '}obj =Obj[name[i]]; //returned the object, and there's no return.        if(typeofObj!== "Object" | | !obj)return; }    //notice here that obj is Options.output    //so the return is options.output.filename.    returnObj[name.pop ()];}

As can be seen, this function is to try to get the object of a key, the progression of the key with a point to connect, if the acquisition failed to return undefined.

Ingenious Function! Avoids multiple judgments Obj[key] is undefined, which solves this problem directly in the form of a string.

SetProperty

functionsetProperty (obj, name, value) {Name= Name.split (".");  for(Let i = 0; i < name.length-1; i++) {        //non-object direct return undefined        if(typeofObj[name[i]]!== "Object" &&typeofObj[name[i]]!== "undefined")return; //Set As Object        if(!obj[name[i]]) obj[name[i]] = {}; Obj=Obj[name[i]]; }    //set the corresponding valueObj[name.pop ()] =value;}

With the GetProperty in front, this is more understood.

Here is the prototype method:

Set

    Set (name, config, def) {        if (arguments.length = = = 3) {            this. Defaults [Name] = def;             this. config[name] = config;        } Else {            this. defaults[name] = config;              Delete  This . Config[name];        }    }

There's nothing to say, the object generated by the constructor is copied based on the number of arguments.

As for the process method will be called later, so here for the time being, go back to the webpackoptionsdefaulter in the large set, extract two cases to explain:

this. Set ("Output.chunkfilename", "make", (options)    = = options.output.filename;     return filename.indexof ("[Name]") >= 0? Filename.replace ("[Name]", "[ID]"): "[id]." + filename;}); this. Set ("Resolve.extensions", [". js", ". JSON"]);

After calling these two methods, the defaults and Config objects are as follows:

Defaults = {    "resolve.extensions": [". js", ". JSON"],    "Output.chunkfilename": (Options) = > {        = options.output.filename;         return filename.indexof ("[Name]") >= 0? Filename.replace ("[Name]", "[ID]"): "[id]." + filename;     = {    "output.chunkfilename": "Make"}

function, the value can be taken because output.filename is a required parameter.

The Chunkfilename function will replace [ name] in the string with [ ID], and if not, add the [ID.] prefix.

For example, multiple outputs often take [name].js as the output file name, where the default value of Chunkfilename is [Id].js .

After a large amount of set, you can look at the process function, for the convenience of display, written in function form:

//options to pass infunctionprocess (options) {//traversing Defaults Objects     for(Let nameinch  This. Defaults) {        //match config parameter        Switch( This. Config[name]) {            //assign values directly by default             Caseundefined:if(GetProperty (options, name) = = =undefined) setProperty (options, name, This. Defaults[name]);  Break; //used to ensure that the root key is an object             Case"Call": SetProperty (options, name, This. Defaults[name].call ( This, GetProperty (options, name), options), options);  Break; //The default value is injected by calling the function                //Pass in an options parameter             Case"Make":                if(GetProperty (options, name) = = =undefined) setProperty (options, name, This. Defaults[name].call ( This, Options), options);  Break; //add default values to an existing array             Case"Append": {Let oldValue=getProperty (options, name); if(! Array.isarray (oldValue)) OldValue = []; OldValue.push.apply (OldValue, This. Defaults[name]);                    SetProperty (options, name, OldValue);  Break; }            default:                Throw NewError ("Optionsdefaulter cannot process" + This. Config[name]); }    }}

There are 4 default injection methods based on config, where function invocation can be configured more flexibly.

For completeness, there are calls to the Template.toidentifier method In some sets, with a glance at its internal implementation:

//matches all non-uppercase and lowercase letters $_Const IDENTIFIER_NAME_REPLACE_REGEX =/^[^a-za-z$_]/;//matches all non-uppercase and lowercase alphanumeric $_Const IDENTIFIER_ALPHA_NUMERIC_NAME_REPLACE_REGEX =/[^a-za-z0-9$_]/G;module.exports=class Template extends Tapable {constructor (outputoptions) {/**/ }    //static method calls directlystatic Toidentifier (str) {if(typeofSTR!== "string")return""; //all special symbols are replaced by _        returnStr.replace (Identifier_name_replace_regex, "_"). Replace (Identifier_alpha_numeric_name_replace_regex, "_"); }    //The rest of the methods ...}

Just a normal character substitution function.

In a nutshell: The Webpackoptionsdefaulter module adds a number of default parameters to the options configuration object.

Finished ~

.7-analysis of the Webpackoptionsdefaulter module of Webpack source code

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.