A difficult knowledge point of webpack: deep analysis of dependency graph

InfoQ 2021-06-18 21:29:18
difficult knowledge point webpack deep


{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}},{"type":"strong","attrs":{}}],"text":"*","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":" The full text 2500 word , Read for about 30 minute . If you think the article is useful , Welcome to like your attention , But writing is not easy , Without the consent of the author , It is forbidden to reprint in any form !!!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"*","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" background ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":"Dependency Graph The concept comes from the official website ","attrs":{}},{"type":"link","attrs":{"href":"https://webpack.js.org/concepts/dependency-graph/","title":null,"type":null},"content":[{"type":"text","text":"Dependency Graph | webpack","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}]},{"type":"text","text":" One article , The original explanation is like this :","attrs":{}}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}},{"type":"strong","attrs":{}}],"text":"*","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"Any time one file depends on another, webpack treats this as a ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}},{"type":"color","attrs":{"color":"#3594F7","name":"user"}},{"type":"strong","attrs":{}}],"text":"dependency","attrs":{}},{"type":"text","text":". This allows webpack to take non-code assets, such as images or web fonts, and also provide them as ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}},{"type":"color","attrs":{"color":"#3594F7","name":"user"}},{"type":"strong","attrs":{}}],"text":"dependencies","attrs":{}},{"type":"text","text":" for your application.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"When webpack processes your application, it starts from a list of modules defined on the command line or in its configuration file. Starting from these ","attrs":{}},{"type":"link","attrs":{"href":"https://webpack.js.org/concepts/entry-points/","title":null,"type":null},"content":[{"type":"text","text":"entry points","attrs":{}}],"marks":[{"type":"italic"},{"type":"color","attrs":{"color":"#40B8FA","name":"user"}},{"type":"strong"}]},{"type":"text","text":", webpack recursively builds a ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}},{"type":"color","attrs":{"color":"#3594F7","name":"user"}},{"type":"strong","attrs":{}}],"text":"dependency graph","attrs":{}},{"type":"text","text":" that includes every module your application needs, then bundles all of those modules into a small number of ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}},{"type":"color","attrs":{"color":"#3594F7","name":"user"}},{"type":"strong","attrs":{}}],"text":"bundles","attrs":{}},{"type":"text","text":" - often, just one - to be loaded by the browser.","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"*","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" The core meaning of translation is :webpack When dealing with application code , It'll come from the developers entry Start to recursively build the... That contains all the modules ","attrs":{}},{"type":"text","marks":[{"type":"italic","attrs":{}},{"type":"color","attrs":{"color":"#3594F7","name":"user"}},{"type":"strong","attrs":{}}],"text":"「dependency graph」","attrs":{}},{"type":"text","text":" _,_ And then I'll put these module Packaging for bundles .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" However, the fact is far more than the description on the official website ,Dependency Graph through webpack The whole running cycle , from make Module analysis of phase , To seal Stage chunk Generate , as well as tree-shaking Functions are highly dependent on Dependency Graph , yes webpack Resource construction is a very core data structure .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" This article will focus on [email protected] Of Dependency Graph Realization , There are three aspects to discuss :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"Dependency Graph stay webpack What kind of data structure is used in the implementation ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"Webpack How to collect dependencies between modules during operation , And then build Dependency Graph","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"Dependency Graph So once you've built it , How is it consumed ","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" Study this article , You will learn more about webpack Processing details of module parsing , Combined with the above ","attrs":{}},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/363928061","title":null,"type":null},"content":[{"type":"text","text":"[ Ten thousand word summary ] I have a thorough understanding of it Webpack The core principle ","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}]},{"type":"text","text":" , You can learn more about webpack The core mechanism of .","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":"Dependency Graph","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" This section goes into webpack Source code , Reading Dependency Graph The internal data structure and dependency collection process of . Before the official launch , It's necessary to review a few webpack Important concepts :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":": Resources in webpack Internal mapping objects , Contains the path of the resource 、 Context 、 rely on 、 Content and other information ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Dependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : Reference other modules in a module , for example ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"import \"a.js\"","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" sentence ,webpack We will first express the reference relationship as Dependency Subclass and associate module object , Until now module After all the contents are parsed , Starting the next cycle will start Dependency Object to the appropriate Module Subclass .","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Chunk","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : Objects used to organize output structures ,webpack After analyzing the contents of all module resources , Build a complete Dependency Graph after , According to user configuration and Dependency Graph Content builds one or more chunk example , Every chunk And the final output file is roughly one-to-one correspondence .","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" data structure ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":"Webpack 4.x Of Dependency Graph Simple implementation , Mainly by Dependence/Module Built in series property record reference 、 The cited relationship .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" and Webpack 5.0 After that, we implemented a relatively complex class structure to record the dependencies between modules , Take module dependency related logic from Dependence/Module Decoupling into a set of independent type structures , The main types are :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ModuleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : Record Dependency Graph The container of information , On the one hand, it saves all the information involved in the construction process ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" 、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"dependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" object , And these objects refer to each other ; On the other hand, it provides various tools and methods , It is convenient for users to read out quickly ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" or ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"dependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Additional information ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphConnection","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : Data structure that records the reference relationship between modules , Through internal ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"originModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Property records refer to the parent module in the relationship , adopt ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Attribute record submodule . In addition, a series of function tools are provided to judge the validity of the corresponding reference relationship ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" :","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The object is Dependency Graph Supplementary information under the system , That contains module objects ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incomingConnections","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" —— To the module itself ModuleGraphConnection aggregate , Who refers to the module itself ;","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"outgoingConnections","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" —— The external dependence of the module , That is, the module refers to other modules .","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" The relationship between classes is roughly :","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ee/ee39ebfcf4f5274dbd20113f8f5da810.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" The above class diagram needs extra attention :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ModuleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Object passing ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"_dependencyMap","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Property record ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Dependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Object and the ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphConnection","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The mapping between connected objects , In the subsequent processing, we can quickly find... Based on this layer mapping ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Dependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The reference corresponding to the instance and the referenced ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ModuleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Object passing ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"_moduleMap","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" stay ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" On the basis of ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Information , and ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The biggest function is to record the reference and referenced relationship of the module , Subsequent processing can be found based on this attribute ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" All dependencies and dependents of an instance ","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" Rely on the collection process ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ModuleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphConnection","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The three work together , stay webpack The build process (make Stage ) Step by step collect dependencies between modules in , Looking back ","attrs":{}},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/363928061","title":null,"type":null},"content":[{"type":"text","text":"[ Ten thousand word summary ] I have a thorough understanding of it Webpack The core principle ","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}]},{"type":"text","text":" The construction flow chart mentioned :","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/86/86836f19526963148ced041e2cbb583e.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" The build process itself is complex , Readers are advised to read in contrast ","attrs":{}},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/363928061","title":null,"type":null},"content":[{"type":"text","text":"[ Ten thousand word summary ] I have a thorough understanding of it Webpack The core principle ","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}]},{"type":"text","text":" One article , Deepen the understanding . The dependency collection process mainly takes place in two nodes :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"addDependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" :webpack After resolving the reference relationship from the module content , Create the right ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Dependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Subclass and call the method to record to ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" example ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"handleModuleCreation","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : After the module is parsed ,webpack Traverse the dependency set of the parent module , Call this method to create ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Dependency","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Corresponding submodule object , Then call ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"compilation.moduleGraph.setResolvedModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Method to record the parent-child reference information to ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"moduleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" On the object ","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"setResolvedModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The logic of the method is roughly :","attrs":{}}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"class ModuleGraph {\n    constructor() {\n        /** @type {Map} */\n        this._dependencyMap = new Map();\n        /** @type {Map} */\n        this._moduleMap = new Map();\n    }\n\n    /**\n     * @param {Module} originModule the referencing module\n     * @param {Dependency} dependency the referencing dependency\n     * @param {Module} module the referenced module\n     * @returns {void}\n     */\n    setResolvedModule(originModule, dependency, module) {\n        const connection = new ModuleGraphConnection(\n            originModule,\n            dependency,\n            module,\n            undefined,\n            dependency.weak,\n            dependency.getCondition(this)\n        );\n        this._dependencyMap.set(dependency, connection);\n        const connections = this._getModuleGraphModule(module).incomingConnections;\n        connections.add(connection);\n        const mgm = this._getModuleGraphModule(originModule);\n        if (mgm.outgoingConnections === undefined) {\n            mgm.outgoingConnections = new Set();\n        }\n        mgm.outgoingConnections.add(connection);\n    }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" The code in the above example is mainly changed ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"_dependencyMap","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" And ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"moduleGraphModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" In and out of ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"connections","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" attribute , To collect the upstream and downstream dependencies of the current module .","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" Instance analysis ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" Take a simple example , For the following dependencies :","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b4/b4c1ca87fb1cbf65e951bc02677bb653.png","alt":"","title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":"Webpack After starting , Call recursively during the build phase ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"compilation.handleModuleCreation","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" function , Gradually complete Dependency Graph structure , Finally, the following data results may be generated :","attrs":{}}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"\nModuleGraph: {\n    _dependencyMap: Map(3){\n        { \n            EntryDependency{request: \"./src/index.js\"} => ModuleGraphConnection{\n                module: NormalModule{request: \"./src/index.js\"}, \n                //  The entry module has no references , Therefore, it is set as  null\n                originModule: null\n            } \n        },\n        { \n            HarmonyImportSideEffectDependency{request: \"./src/a.js\"} => ModuleGraphConnection{\n                module: NormalModule{request: \"./src/a.js\"}, \n                originModule: NormalModule{request: \"./src/index.js\"}\n            } \n        },\n        { \n            HarmonyImportSideEffectDependency{request: \"./src/a.js\"} => ModuleGraphConnection{\n                module: NormalModule{request: \"./src/b.js\"}, \n                originModule: NormalModule{request: \"./src/index.js\"}\n            } \n        }\n    },\n\n    _moduleMap: Map(3){\n        NormalModule{request: \"./src/index.js\"} => ModuleGraphModule{\n            incomingConnections: Set(1) [\n                // entry  modular , Corresponding  originModule  by null\n                ModuleGraphConnection{ module: NormalModule{request: \"./src/index.js\"}, originModule:null }\n            ],\n            outgoingConnections: Set(2) [\n                //  from  index  Point to  a  modular \n                ModuleGraphConnection{ module: NormalModule{request: \"./src/a.js\"}, originModule: NormalModule{request: \"./src/index.js\"} },\n                //  from  index  Point to  b  modular \n                ModuleGraphConnection{ module: NormalModule{request: \"./src/b.js\"}, originModule: NormalModule{request: \"./src/index.js\"} }\n            ]\n        },\n        NormalModule{request: \"./src/a.js\"} => ModuleGraphModule{\n            incomingConnections: Set(1) [\n                ModuleGraphConnection{ module: NormalModule{request: \"./src/a.js\"}, originModule: NormalModule{request: \"./src/index.js\"} }\n            ],\n            // a  The module has no other dependencies , so  outgoingConnections  The property value is  undefined\n            outgoingConnections: undefined\n        },\n        NormalModule{request: \"./src/b.js\"} => ModuleGraphModule{\n            incomingConnections: Set(1) [\n                ModuleGraphConnection{ module: NormalModule{request: \"./src/b.js\"}, originModule: NormalModule{request: \"./src/index.js\"} }\n            ],\n            // b  The module has no other dependencies , so  outgoingConnections  The property value is  undefined\n            outgoingConnections: undefined\n        }\n    }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" From the above Dependency Graph It can be seen that , Essentially ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ModuleGraph._moduleMap","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" A directed acyclic graph structure has been formed , Among them, the dictionary ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"_moduleMap","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Of key Is the node of the graph , Corresponding value ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ModuleGraphModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The structure of the ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"outgoingConnections","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The attribute is the edge of the graph , In the above example, from the starting point ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"index.js","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Starting edge ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"outgoingConnections","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" All the vertices of the graph can be traversed forward .","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" effect ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" With [email protected] For example , keyword ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"moduleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" There is 1277 Time , It's almost covered ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"webpack/lib","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" All the files under the folder , Its function can be seen . Although the frequency is very high , But on the whole, it can be seen that there are two main functions : Information index 、 Turn into ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ChunkGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" To determine the output structure .","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" Information index ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"ModuleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Types provide many implementations module / dependency Information query tool function , for example :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"getModule(dep: Dependency)","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : according to dep Find the corresponding ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" example ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"getOutgoingConnections(module: Module)","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : lookup ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" All dependencies of the instance ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"getIssuer(module: Module)","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" : lookup ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"module","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Where to be quoted ( About issuer More about the mechanism , Please refer to another article of mine : ","attrs":{}},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/368391369","title":null,"type":null},"content":[{"type":"text","text":" Ten minutes Webpack:module.issuer Properties, ","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}]},{"type":"text","text":" )","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" wait .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":"[email protected] Many plug-ins inside 、Dependency Subclass 、Module Subclass implementation needs to use these tool functions to find specific modules 、 Dependent information , for example :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"SplitChunksPlugin","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Optimizing chunks In processing , Need to use ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"moduleGraph.getExportsInfo","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Query each module's ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"exportsInfo","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" ( A collection of information exported by a module , And tree-shaking Strong correlation , There will be a single article to explain ) Information to determine how to separate ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"chunk","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":".","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":" stay ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"compilation.seal","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Function , Need to traverse entry Corresponding dep And call ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"moduleGraph.getModule","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Get the complete module Definition ","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"...","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" that , When you write plug-ins , Consider a moderate reference ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"webpack/lib/ModuleGraph.js","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Method provided in , Confirm that you can get the information you need by using those functions .","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" structure ChunkGraph","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":"Webpack In the main process ,make At the end of the build phase, you go to ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"seal","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Stage , Start sorting out how to organize the output content . stay [email protected] when ,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"seal","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" The stage mainly revolves around ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Chunk","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" And ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ChunkGroup","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Two types expand , And by the 5.0 after , And Dependency Graph Similarly, a new system based on ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ChunkGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Graph structure to achieve resource generation algorithm .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" stay compilation.seal Function , First, according to the default rules —— Every entry The corresponding organization is a chunk , Then call ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"webpack/lib/buildChunkGraph.js","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" File defined ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"buildChunkGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Method , Traverse ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"make","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" stage-generated ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"moduleGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" Object so that module Dependency is transformed into ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"chunkGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" object .","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" The logic of this part is also very complicated , Not here , Next time, I will write a separate article to explain ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"chunk/chunkGroup/chunkGraph","attrs":{}}],"marks":[{"type":"color","attrs":{"color":"#3594F7","name":"user"}}],"attrs":{}},{"type":"text","text":" And so on .","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40B8FA","name":"user"}}],"text":" summary ","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" This article discusses the Dependency Graph Concept in webpack The interior is heavily used , So understanding this concept is important for us to understand webpack Source code , Or learn how to write plug-ins 、loader Will be of great help . In fact, many new knowledge blind spots have been found in the process of analysis :","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"Chunk What's the complete mechanism of ?","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"Dependency How to realize the complete system of , What's the use ?","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#595959","name":"user"}}],"text":"Module Of exportsInfo How to collect ? stay tree-shaking How to be used in the process ?","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#2b2b2b","name":"user"}}],"text":" If you are also interested in the above questions , Welcome to like your attention , The follow-up will focus on webpack Output more useful articles .","attrs":{}}]}]}
版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/06/20210604093342489n.html

  1. HTML + CSS + JavaScript to achieve cool Fireworks (cloud like particle text 3D opening)
  2. HTML + CSS + JavaScript realizes 520 advertising love tree (including music), which is necessary for programmers to express themselves
  3. Solve the problem of Web front-end deployment server (it can be deployed online without a server)
  4. HTML + CSS + JS make wedding countdown web page template (520 / Tanabata Valentine's Day / programmer advertisement)
  5. What else can driverless minibus do besides "Park connection"?
  6. Cloud native leads the era of all cloud development
  7. NRM mirror source management tool
  8. Bring it to you, flex Jiugong
  9. Lolstyle UI component development practice (II) -- button group component
  10. Deconstruction assignment in ES6
  11. Luo 2 peerless Tang clan was officially launched. The official gave a key point, and the broadcast time was implied
  12. 20初识前端HTML(1)
  13. 当新零售遇上 Serverless
  14. 20 initial knowledge of front-end HTML (1)
  15. When new retail meets serverless
  16. [golang] - go into go language lesson 5 type conversion
  17. [golang] - go into go language lesson 6 conditional expression
  18. HTML5(八)——SVG 之 path 详解
  19. HTML5 (8) -- detailed explanation of SVG path
  20. 需要开通VIP以后页面内容才能复制怎么办?控制台禁用javascript即可
  21. Web前端|CSS入门教程(超详细的CSS使用讲解,适合前端初学者)
  22. 实践积累 —— 用Vue3简单写一个单行横向滚动组件
  23. Serverless 全能选手,再下一城
  24. What if you need to open a VIP to copy the page content? Just disable JavaScript on the console
  25. Web front end | CSS introductory tutorial (super detailed CSS explanation, suitable for front-end beginners)
  26. Practice accumulation - write a single line horizontal scroll component simply with vue3
  27. Dili Reba is thin again. She looks elegant and high in a strapless hollow skirt, and her "palm waist" is beautiful to a new height
  28. Serverless all-round player, next city
  29. The difference between MySQL semi synchronous replication and lossless semi synchronous replication
  30. Vue表单设计器的终极解决方案
  31. The ultimate solution for Vue form designer
  32. Nginx从理论到实践超详细笔记
  33. Yu Shuxin's red backless swimsuit is split to the waist and tail, with a concave convex figure and excessive color matching, and his face is white to dazzling
  34. Nginx ultra detailed notes from theory to practice
  35. 【动画消消乐|CSS】086.炫酷水波浪Loading过渡动画
  36. typecho全站启用https
  37. CCTV has another popular employee. The off-site interpretation is very professional, and the appearance ability is no less than that of Wang Bingbing
  38. [animation Xiaole | CSS] 086. Cool water wave loading transition animation
  39. Enable HTTPS in Typecho
  40. 50天用JavaScript完成50个web项目,我学到了什么?
  41. 根据JavaScript中原生的XMLHttpRequest实现jQuery的Ajax
  42. What have I learned from completing 50 web projects with JavaScript in 50 days?
  43. "My neighbor doesn't grow up" has hit the whole network. There are countless horse music circles, and actor Zhou Xiaochuan has successfully made a circle
  44. 根据JavaScript中原生的XMLHttpRequest实现jQuery的Ajax
  45. Implement the Ajax of jQuery according to the native XMLHttpRequest in JavaScript
  46. Implement the Ajax of jQuery according to the native XMLHttpRequest in JavaScript
  47. 30 + women still wear less T-shirts and jeans. If they wear them like stars, they will lose weight
  48. 数栈技术分享前端篇:TS,看你哪里逃~
  49. Several stack technology sharing front end: TS, see where you escape~
  50. 舍弃Kong和Nginx,Apache APISIX 在趣链科技 BaaS 平台的落地实践
  51. Abandon the landing practice of Kong and nginx, Apache apisik on the baas platform of fun chain technology
  52. 浪迹天涯king教你用elementui做复杂的表格,去处理报表数据(合并表头,合并表体行和列)
  53. 前端HTML两万字图文大总结,快来看看你会多少!【️熬夜整理&建议收藏️】
  54. Wandering around the world king teaches you to use elementui to make complex tables and process report data (merge header, merge table body rows and columns)
  55. 路由刷新数据丢失 - vuex数据读取的问题
  56. Front end HTML 20000 word graphic summary, come and see how much you can【 Stay up late to sort out & suggestions]
  57. Route refresh data loss - vuex data reading problem
  58. Systemctl系统启动Nginx服务脚本
  59. Systemctl system startup nginx service script
  60. sleepless