<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Phodal Huang</title>
    <description>The latest articles on DEV Community by Phodal Huang (@phodal).</description>
    <link>https://dev.to/phodal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186338%2Fdbc46292-0d6f-4eef-8590-d1c510883383.jpeg</url>
      <title>DEV Community: Phodal Huang</title>
      <link>https://dev.to/phodal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phodal"/>
    <language>en</language>
    <item>
      <title>Architecture Workbench: Building Digital Twins of Enterprise (Application) Architectures</title>
      <dc:creator>Phodal Huang</dc:creator>
      <pubDate>Wed, 25 May 2022 11:13:40 +0000</pubDate>
      <link>https://dev.to/phodal/architecture-workbench-building-digital-twins-of-enterprise-application-architectures-1bj4</link>
      <guid>https://dev.to/phodal/architecture-workbench-building-digital-twins-of-enterprise-application-architectures-1bj4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The Architecture Workbench is an environment designed to help people design architectures, evolve architectures, observe architectures, and effectively use the high-quality tools required for architectures, such as interactive architecture development and analysis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the previous article "&lt;a href="https://www.phodal.com/blog/architecture-as-code/"&gt;Architecture as Code: Coding Next Generation Enterprise (Application) Architecture Systems&lt;/a&gt;", we introduced architecture as code The idea is how to combine and present architectural elements and features around a series of patterns of architecture, and closely integrate architectural decisions and design principles with the system.&lt;/p&gt;

&lt;p&gt;In order to implement and implement the concept of &lt;strong&gt;architecture as code&lt;/strong&gt;, it is also necessary to build a platform to run these codes, which we call the architecture workbench. But why are we building an architecture workbench? Just for fun. &lt;/p&gt;

&lt;p&gt;Here is screenshots:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--945MBeQp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/siu8lcizticd8foxgaub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--945MBeQp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/siu8lcizticd8foxgaub.png" alt="Image description" width="880" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build Architecture Workbench?
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://github.com/archguard"&gt;ArchGuard&lt;/a&gt;, we want to manage three forms of architecture: &lt;strong&gt;design state&lt;/strong&gt;, &lt;strong&gt;development state&lt;/strong&gt; and &lt;strong&gt;operation state&lt;/strong&gt;. corresponds to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design a new enterprise (application) architecture. Such as describing and designing the current architecture of the system.&lt;/li&gt;
&lt;li&gt;Understand and manage the current state of the system. Such as displaying the status quo of the system through visual means and managing the system with rules.&lt;/li&gt;
&lt;li&gt;Observe the operation of the system &amp;lt;=&amp;gt; architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Similarly, for the departments related to the structure of many medium and large organizers, they also have the above problems. And, I believe they face the same dilemma that we built ArchGuard:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Architecture is multidimensional. Including technology, data, security, operation and maintenance and systems, etc.&lt;/li&gt;
&lt;li&gt;Lack of a unified architecture &lt;strong&gt;language&lt;/strong&gt;. Human language for communication, such as what is a component?&lt;/li&gt;
&lt;li&gt;The architecture of the system is very strange. Architectural style or pattern differences, such as microservice architecture, plug-in architecture, etc.&lt;/li&gt;
&lt;li&gt;Lack of business context. Being an external architect lacks some context to help with governance.&lt;/li&gt;
&lt;li&gt;Details are the devil. The world of architecture is rich and colorful, and there is no way to show them all, such as a small interface, which may reverse our assumptions about understanding.&lt;/li&gt;
&lt;li&gt;Our (ArchGuard team) current architecture capabilities are limited - too few senior architects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, before implementing such a standardized system of architectural patterns, it is better to try to build a more flexible form: the Architecture Workbench. It can help us better explore the system and is more in line with our initial experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Architecture Workbench
&lt;/h2&gt;

&lt;p&gt;For the concept of workbench, as an active DSL creator, I am more familiar with Martin Fowler's definition of language workbench in Domain-Specific Languages:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Language Workbench is an environment designed from the ground up to help people build new DSLs and the high-quality tools they need to use those DSLs effectively.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Therefore, in terms of definition, we refer to the definition of the old horse, and draw on the modern workbench concept, mainly including: RStudio's &lt;strong&gt;code documentation&lt;/strong&gt;, Jupyter's &lt;strong&gt;interactive analysis&lt;/strong&gt;. So, our definition is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Architecture Workbench is an environment designed to help people design architectures, evolve architectures, observe architectures, and effectively use the high-quality tools required for architectures, such as interactive architecture development and analysis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Code documentation is used to help us better manage &lt;strong&gt;architecture code&lt;/strong&gt; and integrate it into the software development life cycle, such as architecture documentation, user stories, continuous integration, etc. The interactive analysis is used to help us effectively reduce the customized code, and then evolve into an API interface and customized code.&lt;/p&gt;

&lt;p&gt;For Architecture Workbench, its application includes the following core functions and features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design architecture, evolution architecture and observation architecture.&lt;/li&gt;
&lt;li&gt;Build a digital twin of the architecture&lt;/li&gt;
&lt;li&gt;Descriptive programming and explicit design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Among these features, we believe that building the digital twin of the architecture is the most important part of this workbench, and the basic blocks are: design architecture, evolution architecture and observation architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basics: Design Architecture, Evolution Architecture and Observation Architecture
&lt;/h3&gt;

&lt;p&gt;When governance architecture, we usually focus on how to design, how to evolve, and observe the state of the architecture at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design Architecture.&lt;/strong&gt; Such a function cannot be understood. The difficulty is, how to provide an efficient design mechanism? Using UI drag and drop, or DSL, there are various games. Generally speaking, it will be more friendly to use the code. In order to visually display the design of the architecture, we will represent it through the architecture diagram, which is the core of the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evolving Architecture.&lt;/strong&gt; Its core is &lt;strong&gt;building an architecture governance model&lt;/strong&gt; and &lt;strong&gt;designing a fitness function of the architecture&lt;/strong&gt; to guide the system to make orderly changes. From the implementation level, it is to analyze the implemented software architecture (ie code, etc.), design metrics, and provide high-quality tools to guide the architecture back to a reasonable state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observation Architecture&lt;/strong&gt;. That is, to observe the running status of the application of the architecture, it mainly depends on various APM (application performance management, application performance monitoring) tools. In the cloud-native era, related tools are also very popular, such as Skywalking.&lt;/p&gt;

&lt;p&gt;A basic architecture workbench should consider the above three elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced: Building a Digital Twin of the Architecture
&lt;/h3&gt;

&lt;p&gt;The ideal architecture workbench should provide an interactive mapped version of the architecture. What it means: It's a virtual representation of a system or object throughout its life cycle that we can update based on real-time data and use &lt;strong&gt;simulation, machine learning, and inference&lt;/strong&gt; to help decision-making.&lt;/p&gt;

&lt;p&gt;Conceptually, it offers a very good future, the difficulty is how to implement such a system?&lt;/p&gt;

&lt;p&gt;We are designing a digital twin version of ArchGuard around these three architectural forms (from an implementation perspective):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design state. Focus on &lt;strong&gt;boundary&lt;/strong&gt;, &lt;strong&gt;concept&lt;/strong&gt; and &lt;strong&gt;interaction&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Development state. Focus on &lt;strong&gt;levels, dependencies&lt;/strong&gt; and &lt;strong&gt;modules&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Running state. Focus on &lt;strong&gt;performance&lt;/strong&gt;, &lt;strong&gt;link level&lt;/strong&gt; and &lt;strong&gt;resource usage&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This version is equivalent to the design state. When implemented, it will also be restricted by development capabilities and data. In the future, should we also have two-way binding of code and its architectural twin?&lt;/p&gt;

&lt;h3&gt;
  
  
  Core: Descriptive Programming vs Explicit Design
&lt;/h3&gt;

&lt;p&gt;There are many problems with the various architecture-related specifications that we are familiar with, such as: the specification is not intuitive, the specification is not automated, and so on. For an effective evolutionary architecture, we need to effectively combine specification, code, design, that is, explicit programming and explicit design, which are all concepts from PL (programming language) / DSL (domain specific language).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Illustrative programming&lt;/strong&gt; (illustrative programming) is used to enhance the interpretability of execution results, such as in the context of architecture governance, by &lt;strong&gt;generating architecture diagrams&lt;/strong&gt; to understand the results of DSL writing. Another type of visual way, such as tables and charts in Excel. For details, see Martin Fowler's related article at the end of the article.&lt;br&gt;
&lt;strong&gt;Explicit Design&lt;/strong&gt;. &lt;strong&gt;Explicit&lt;/strong&gt; is the manual method of accomplishing the desired changes by explicitly writing the instructions to be done. Explicit design is a description language that guides us on how to build a good system, such as a DSL in ADL (Architecture Description Language). In addition to using the language pasted into the architecture description, there is also tool support for supporting the DSL, such as editor intellisense.&lt;/p&gt;

&lt;p&gt;These two features are improved around the concept of &lt;strong&gt;architecture as code&lt;/strong&gt;, such as PlantUML, Graphviz and other diagrams as code (Diagrams as code) also have such characteristics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Traits
&lt;/h3&gt;

&lt;p&gt;Of course, in order for this system to work well, we need a series of other features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simulation verification of architecture evolution. After building the digital twin of the architecture, we can&lt;/li&gt;
&lt;li&gt;Easy to extend functionality. That is, the microkernel architecture is adopted, that is, plug-in, micro-front-end, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's still a lot to explore, and we'll talk about it after we've built the first version.&lt;/p&gt;

&lt;h2&gt;
  
  
  How should we design and implement it?
&lt;/h2&gt;

&lt;p&gt;We are now implementing such a system in ArchGuard and it is quite exciting. As an early version it barely worked, here are some ideas for how we built the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Big data workbench as inspiration
&lt;/h3&gt;

&lt;p&gt;Since the system is a system similar to data analysis, many of our flus come from the field of big data. On the workbench, at first, the idea was to build a compilable report that takes RStudio-like and provides a Jupyter-like interactive experience.&lt;/p&gt;

&lt;p&gt;However, due to the poor interactive experience of Jupyter, the downloaded files are not readable and cannot be easily edited + run. Therefore, we use Markdown as the data format, which is convenient for developers to write documents, and can also be opened and edited in any IDE. On the UI, the main editor of ProseMirror is used, that is, the editor of Markdown, and the Monaco Editor is used as the secondary editor, that is, the editor of code.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Building REPL-based abstractions
&lt;/h3&gt;

&lt;p&gt;With IDE support in mind, we adopted Kotlin to build the &lt;strong&gt;internal DSL&lt;/strong&gt;, so that no external DSL needs to be built with editor support. Then, Kotlin Scripting Compiler is used as the underlying REPL (read–eval–print loop, also known as &lt;strong&gt;interactive top-level component&lt;/strong&gt;), which is simply the command line mode of the Kotlin language. In terms of form, it is similar to the form of MySQL Workbench, or the CLI mode of Python.&lt;/p&gt;

&lt;p&gt;Then, there is the DSL of the abstract system (ArchGuard), the architecture of the design state, and the architecture fitness function.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Request and responder operation
&lt;/h3&gt;

&lt;p&gt;With the support of the compiler backend and the Kotlin DSL IDE, we need to build a bridge between the two. Therefore, we use WebSocket as the communication method, and the returned results are processed according to different types. such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Integrate the running result of the backend API.&lt;/li&gt;
&lt;li&gt;Graphical results. Mermaid, D3.js, Echart.js are for different graphic displays.&lt;/li&gt;
&lt;li&gt;Perform the corresponding scan.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is no different from the usual C/S structure development. Graphical results to support our &lt;strong&gt;Descriptive Programming and Explicit Design&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  other
&lt;/h2&gt;

&lt;p&gt;We are still designing and building such a workbench, feel free to hook us up: &lt;a href="https://github.com/archguard/archguard"&gt;https://github.com/archguard/archguard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reference content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Domain specific language"&lt;/li&gt;
&lt;li&gt;"Evolutionary Architecture"&lt;/li&gt;
&lt;li&gt;"Data Analysis with Python"&lt;/li&gt;
&lt;li&gt;"&lt;a href="https://martinfowler.com/bliki/IllustrativeProgramming.html"&gt;IllustrativeProgramming&lt;/a&gt;"&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>workstations</category>
    </item>
    <item>
      <title>ArchGuard: a open-source architecture governance platform</title>
      <dc:creator>Phodal Huang</dc:creator>
      <pubDate>Tue, 24 May 2022 13:20:25 +0000</pubDate>
      <link>https://dev.to/phodal/archguard-a-open-source-architecture-governance-platform-42ah</link>
      <guid>https://dev.to/phodal/archguard-a-open-source-architecture-governance-platform-42ah</guid>
      <description>&lt;p&gt;Over the past 10 years, software architecture has undergone tremendous changes, from the earlier popular monolithic MVC architecture to the so-called 5:5 split, meaning from distributed to monolithic. The fact is, there are a large number of software developers who cannot see the whole picture of the system or change from a single-minded approach. As a result, even when using microservices, the implementation is still monolithic, and they become "distributed monoliths."&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Architecture governance&lt;/em&gt; has become an urgent issue.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The challenges we face&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a software architect or developer, we face many challenges in architecture governance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Design and implementation mismatch. There is a huge difference between the designed software architecture and the actual implemented architecture. This difference often needs to be coded online or is onlydiscovered later.&lt;/li&gt;
&lt;li&gt;  No norms/non-compliance with norms. As a senior developer, we have a set of specifications,but many team members aren’t willing to abide by them&lt;/li&gt;
&lt;li&gt;  Huge amount of code, making it difficult to identify problems. In asystem created by a dozen or more microservices, it’s often difficult to quickly discover the intricate relationships between them.&lt;/li&gt;
&lt;li&gt;  Errors can occur at every level of the architectural model. Such as API coupling between services, coupling between codes, database coupling, etc.&lt;/li&gt;
&lt;li&gt;  Architectsand developers themselves lack extensive experience. “I know there is a problem, but I can't tell what is wrong, and I don't know how to fix it.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, we need a platform / tool to help us resolve these issues. So, using our past experience in software development and refactoring, we (DTO’ consultants) started developing ArchGuard, an architecture governance platform, in 2020/01.&lt;/p&gt;

&lt;p&gt;Now, it’s &lt;strong&gt;open source&lt;/strong&gt;&lt;strong&gt;:&lt;/strong&gt; &lt;a href="https://github.com/archguard/archguard"&gt;https://github.com/archguard/archguard&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What can it do?
&lt;/h2&gt;

&lt;p&gt;ArchGuard performs layered analysis according to the popular C4 architecture model. That is, on the four different architectural views of System Context, Container, Component, and Code, which are different levels of abstraction that correspond to different audiences, such as developers in the team who care about the code’s internal dependencies, and architects who care about dependencies between components and windows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9AsWX91b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6l6xhg8joesqxodxvua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9AsWX91b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6l6xhg8joesqxodxvua.png" alt="Image description" width="880" height="511"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;In its final implementation form, it exists in the form of codebases and documentation. ArchGuard is a code-based static analysis tool, which will also be provided by design in the future.&lt;/p&gt;

&lt;p&gt;In ArchGuard, we need to create a series of system components first, that is, to configure the corresponding language and GitHub address so we can just scan the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components / Modules
&lt;/h3&gt;

&lt;p&gt;In the component view, we can see the overall situation of a single project, according to the corresponding code submission history, and unstable code modules:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SRjwOWwk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtiad42jmb3nnb3w15ed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRjwOWwk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtiad42jmb3nnb3w15ed.png" alt="Image description" width="880" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;API declaration and usage:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BfyrPw1r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1mdxwkekw6ifohkswrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BfyrPw1r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1mdxwkekw6ifohkswrd.png" alt="Image description" width="880" height="782"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The architecture is evaluated through the five dimensions of volume, coupling, cohesion, redundancy, and testing. A series of indicators are used to analyze the system’s situation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OcrRUAdY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trj6r0wq6ezemqstfs1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OcrRUAdY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trj6r0wq6ezemqstfs1o.png" alt="Image description" width="880" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  System Dependency Analysis: Service Map
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note: This dependency analysis method depends on team developers having a unified coding standard.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For microservices, ArchGuard can automatically analyze the dependencies between different services and visualize the dependencies:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KOLv3WUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c1s42be5s3rvs9i6al2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KOLv3WUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c1s42be5s3rvs9i6al2x.png" alt="Image description" width="880" height="602"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Note: Since ArchGuard used to be microservice architecture, after being merged into a monolith, there can be a situation in which it calls itself.&lt;/p&gt;

&lt;p&gt;At the same time, the system can help you automatically analyze which APIs are used and which APIs aren’t (some APIs temporarily cannot be analyzed):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---GN-nhoE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8z1eeee27c2e4enl8tzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---GN-nhoE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8z1eeee27c2e4enl8tzj.png" alt="Image description" width="880" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, ArchGuard can support several limited API call identifications such as Spring, RestTemplate, Axios, UMI-Request, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Dependency Analysis: Database Maps
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Note: This dependency analysis method depends on team developers having a unified coding standard.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For inter-database dependencies, ArchGuard can parse the SQL calls in the code, and try to match the dependencies with different microservices, and then analyze which services are coupled at the database layer. Due to inconsistent coding standards, we could not identify all database tables in the code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jsaf-O4V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xaki6r2bnt7l2uv4o5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jsaf-O4V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xaki6r2bnt7l2uv4o5i.png" alt="Image description" width="880" height="634"&gt;&lt;/a&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EW2mpN1C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/136o2h73j15fw9gog2kl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EW2mpN1C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/136o2h73j15fw9gog2kl.png" alt="Image description" width="880" height="634"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xWvHA-fK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aet9eess0i4ks7ogzgzq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xWvHA-fK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aet9eess0i4ks7ogzgzq.png" alt="Image description" width="880" height="634"&gt;&lt;/a&gt;   &lt;/p&gt;

&lt;p&gt;With this dependency, we can see the most frequently used tables in our code. Combined with our functions in code analysis, you can view the call map of the database (in front-end implementation).&lt;/p&gt;

&lt;h3&gt;
  
  
  Code analysis
&lt;/h3&gt;

&lt;p&gt;For development teams, they can view the dependencies between the project’s modules, packages, classes, and methods on ArchGuard:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qa_x4jG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mhquynheoybf4mcukhud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qa_x4jG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mhquynheoybf4mcukhud.png" alt="Image description" width="880" height="487"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Through the above LoginModuleRepository, you can match the results corresponding to the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Impact Analysis (*&lt;strong&gt;&lt;em&gt;I&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;n development)&lt;/em&gt;*
&lt;/h2&gt;

&lt;p&gt;One of the features we are implementing is to analyze and configure the system for potential code modification points, and then analyze the impact of changes through dependencies. It can not only help architects analyze the impact of requirements, but also help testers test the content of the system more accurately.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does ArchGuard handle the functions above?
&lt;/h2&gt;

&lt;p&gt;ArchGuard has two built-in code analysis engines: Bytecode analysis + source code analysis.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Bytecode analysis. As the name implies, it analyzes the dependencies in the code by analyzing the bytecode in the JVM.&lt;/li&gt;
&lt;li&gt;  Source code analysis. Meaning generating a specific data structure by analyzing the syntax tree of the compiled language.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The source code analysis is mainly static analysis, combined with the Chapi code analysis engine (&lt;a href="https://github.com/modernizing/chapi"&gt;https://github.com/modernizing/chapi&lt;/a&gt;) previously open sourced under the refactoring automation open source organization Modernizing. Chapi is based on the syntax analysis implemented by Antlr and supports mainstream programming languages such as TypeScript/JavaScript, Kotlin, Java, C#, etc. As shown in the table below:&lt;/p&gt;

&lt;p&gt;Due to static code analysis, some content isn’t very accurate.&lt;/p&gt;

&lt;p&gt;Combined with several ArchGuard Scanner (&lt;a href="https://github.com/archguard/scanner"&gt;https://github.com/archguard/scanner&lt;/a&gt;) scanning tools to get the data to flow into the database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  scan_git, analyzes basic information such as Git commit history, line count, language, etc.&lt;/li&gt;
&lt;li&gt;  scan_jacoco, to analyze code test coverage&lt;/li&gt;
&lt;li&gt;  scan_bytecode, bytecode analysis&lt;/li&gt;
&lt;li&gt;  scan_sourcecode, source code analysis (including HTTP API analysis, database analysis)&lt;/li&gt;
&lt;li&gt;  scan_test_badsmell, test code for bad smells&lt;/li&gt;
&lt;li&gt;  collector_ci, collects history from CI/CD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Most&lt;/strong&gt;*&lt;em&gt;important thing *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You’re welcome to join the development of ArchGuard, GitHub: &lt;a href="https://github.com/archguard/archguard"&gt;https://github.com/archguard/archguard&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Componentless: a architecture pattern for low-code age.</title>
      <dc:creator>Phodal Huang</dc:creator>
      <pubDate>Tue, 21 Dec 2021 15:04:30 +0000</pubDate>
      <link>https://dev.to/phodal/componentless-a-architecture-pattern-for-low-code-age-4fed</link>
      <guid>https://dev.to/phodal/componentless-a-architecture-pattern-for-low-code-age-4fed</guid>
      <description>&lt;p&gt;PS: This is a very fun front-end architecture model that can create unlimited fun. I wrote this article mainly because it is fun, and &lt;strong&gt;there is nothing new&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When I create &lt;a href="https://github.com/phodal/quake/" rel="noopener noreferrer"&gt;Quake&lt;/a&gt; which is a meta-framework for knowledge management, with meta-data and quake component, you can combine any data to any component, like story in calendar with Transflow DSL &lt;code&gt;from('story').to(&amp;lt;quake-calendar&amp;gt;&lt;/code&gt;, story is build from meta-data:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjciwm6pnxp0o1zc53k9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjciwm6pnxp0o1zc53k9u.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I found &lt;code&gt;componentless&lt;/code&gt; is the pattern of Quake's low-code design principle, I decide to abstract the patterns of it. I call it Componentless:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Componentless architecture is an architectural pattern, it refers to a large number of rely on third-party components (runtime dependent components rather than compile-time dependent components, that is compilation as a service) or temporary storage of custom code running in the container Frontend application. The three-party components of the application, like the three-party API service, can be independently released and deployed independently, and the application does not need to be recompiled, built, and deployed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From the name Componentless, you can know that its target is the serverless-like back-end architecture pattern. Therefore, the definition is quite similar to that of the Serverless architecture. That's why, we define it as a componentless architecture. You don't need to write any components, you only need to write logic code or DSL to achieve their combination. Moreover, we can only provide a DSL + universal URL, and the browser will complete the automatic construction and operation of the application according to the DSL.&lt;/p&gt;

&lt;p&gt;Quake online demo: &lt;a href="https://quake-demo.inherd.org/" rel="noopener noreferrer"&gt;https://quake-demo.inherd.org/&lt;/a&gt;, try typing &lt;code&gt;from('stroy').to(&amp;lt;quake-calendar&amp;gt;)&lt;/code&gt;, the &lt;code&gt;&amp;lt;quake-calendar&amp;gt;&lt;/code&gt; can be any &lt;code&gt;quake-component&lt;/code&gt; (like &lt;code&gt;&amp;lt;quake-component&amp;gt;&lt;/code&gt;, we only have two components in 2021.12.21) or any &lt;code&gt;ionic&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Quake source code: &lt;a href="https://github.com/phodal/quake/" rel="noopener noreferrer"&gt;https://github.com/phodal/quake/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolution of front-end and back-end architecture
&lt;/h2&gt;

&lt;p&gt;Previously, it was quite interesting to often communicate with others about the application of domain-driven design (DDD) in the front-end. As a “nine and three-quarters”/10 DDD bricks, in the past, I always felt that domain-driven design is not suitable for the front-end. Clean front-end architecture is what people need, but design + getting started is slightly more difficult. &lt;/p&gt;

&lt;p&gt;In this year, I have used DDD design and planning for multiple back-end applications, and I have a new experience (although it still doesn't work). The front-end can have a DDD-like approach, but the approach is completely different from the back-end. The back-end uses model and function as the basis of two different programming styles, and the front-end uses components + events as the basis of the programming style. Components are destructible, and events are orchestrated by designing event streams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fclean-frontend.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fclean-frontend.png" alt="Clean Frontend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Therefore, you don't directly apply the idea of back-end DDD to front-end applications, unless the logic of your application is focus on the front-end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microservices and micro frontends
&lt;/h3&gt;

&lt;p&gt;For most of today's systems, they still remain in a state of "back-end microservices, front-end "big mudball"." The back-end microservices have been disassembled into individual microservices according to "Conway's Law" (of course, unreasonably splitting the microservices is another problem), while the front-end is still in a state of a big mud ball. Therefore, the micro-frontend is used as one of the (not the only) technologies to solve the organizational structure alignment and implement the architectural model of rapid release and online. It can split a single large application into multiple smaller autonomous applications, but they are still aggregated into one. It can be used to solve the migration of legacy systems, unify user experience, help multi-team collaboration, etc.&lt;/p&gt;

&lt;p&gt;When migrating back-end systems, we use DDD (Domain Driven Design) to find a reasonable basis for the design of microservice architecture. Microservices have become a way for us to transform the legacy system. We start with one module and one function, and gradually replace the old single application until the entire system is replaced. This replacement mode is quite similar for front-end applications.&lt;/p&gt;

&lt;p&gt;Therefore, after the transformation of the micro front end, the structure is aligned, and the personnel is aligned. Everyone is happy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fms-align.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fms-align.png" alt="MS Align"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going forward, how should we continue to evolve the system?&lt;/p&gt;

&lt;h3&gt;
  
  
  Serverless and ComponentLess
&lt;/h3&gt;

&lt;p&gt;In 2017, after learning about DDD and Serverless, and create the "Serverless Application Development Guide" (&lt;a href="https://serverless.ink/" rel="noopener noreferrer"&gt;https://serverless.ink/&lt;/a&gt;), I have been thinking about how to apply Serverless-like ideas in the front-end? So, there was an idea about the cross-frame component library: "The second half of the front-end: building a cross-frame UI library", but these domestic companies that write component libraries do not have such a bold idea, it is a pity-only the version number + 1, what others do follow? There is also an interesting story line. After experiencing the enthusiasm of low-code programming, I rethinked the future of front-end and back-end: "&lt;a href="https://www.phodal.com/blog/kill-frontend-backend/" rel="noopener noreferrer"&gt;Front-end and back-end integration: Will the front-end and back-end separation die?&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt;At first, I thought no-code programming was a ComponentLess direction, but a research found that it was not. Nocode programming tends to visualize programming, while Componentless tends to use DSL programming. At this point, I prefer to use Web Components + WASM technology to build a new front-end architecture.&lt;/p&gt;

&lt;p&gt;Until I recently reapplied this idea in the open source knowledge management tool &lt;a href="https://github.com/phodal/quake" rel="noopener noreferrer"&gt;Quake&lt;/a&gt;, I found it particularly interesting, so I wanted to write an article to introduce the related idea-after all , The market has accepted the Serverless concept and the micro front end concept. Then, the remaining questions become very simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Componentless architecture
&lt;/h2&gt;

&lt;p&gt;Continue back to the definition at the beginning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Componentless architecture is an architectural pattern, it refers to a large number of rely on third-party components (runtime dependent components rather than compile-time dependent components, that is, compilation as a service) or temporary storage of custom code running in the container Front-end application. The three-party components of the application, like the three-party API service, can be independently released and deployed independently, and the application does not need to be recompiled, built, and deployed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simply, what a componentless thing needs to do is to turn the component into a &lt;strong&gt;runtime service&lt;/strong&gt; instead of a compile-time dependency in the past. When all the components become a kind of infrastructure, we no longer need these components, and then let the components disappear from the application development side, and achieve a state where the application does not require components. In this way, it has also become a LowCode type system, with simple code generation, it can reach the state of NoCode.&lt;/p&gt;

&lt;p&gt;From a formal point of view, the use of micro-front-end related technologies can provide a series of basic technologies required by a componentless architecture. Among them, the simplest way is to use: Web Components. So, let us first look at an example of a Componentless architecture based on Web Components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: How to move towards a Componentless architecture?
&lt;/h3&gt;

&lt;p&gt;In terms of the process, it can be divided into three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Decompose the application using Web Component&lt;/li&gt;
&lt;li&gt;Split more components to eliminate components&lt;/li&gt;
&lt;li&gt;Build a generative low-code model&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The remaining part is fill-in-the-blank programming.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Use Web Component to decompose the application
&lt;/h4&gt;

&lt;p&gt;Let's look at an example first. For example, our front-end part has two micro-applications, A and B. The granularity is already very small, but it is still an application-level application. Application B is built using Web Components technology, and two tripartite Web Components components are introduced into micro-application B. In a conventional front-end application, if we update these two components, the corresponding application needs to be recompiled and released again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fcls-slot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fcls-slot.png" alt="CLS Slot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, with the support of Custom Element + Shadow DOM, we only need to update the link to the script tag of the component library, or the cache.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Split more components to eliminate components
&lt;/h4&gt;

&lt;p&gt;Next, let us further optimize, remove all the internal components of application A and application B, externally build these components into a set of components according to functional modules. These component sets can be divided by functional teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fcls-step-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fphodal%2Fcomponentless%2Fraw%2Fmaster%2Fimages%2Fcls-step-2.png" alt="Step 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are not important. Now there are very few "components" in our application-we still have some components for orchestrating these components + some additional business logic.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Build a generative low-code model
&lt;/h4&gt;

&lt;p&gt;Now, let’s review the "hello, world" function written in Serverless (AWS Lambda, they don’t pay for advertising):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello, world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using a framework like Serverless Framework, we only need to fill in our business logic on this function, that is, fill-in-the-blank programming. For the front end, the process is similar. We have data and our target components. Only a limited code generation function is needed. That is, we only need to generate an empty function to be improved, such as Transflow in Quake: &lt;code&gt;from('todo','blog').to(&amp;lt;quake-calendar&amp;gt;)&lt;/code&gt;, the generated function and logic (part of the code example ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tl_temp_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;quake-calendar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this time, you only need to ensure that the routing and functions are not modified, and the remaining part is to fill in the blanks for data processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migration to Componentless
&lt;/h3&gt;

&lt;p&gt;In addition to the above-mentioned direct decomposition method, there are other gradual migration methods.&lt;/p&gt;

&lt;p&gt;Migration method 2: new embedded in old&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use new technologies and frameworks to create application shelves.&lt;/li&gt;
&lt;li&gt;Extract the Web Component and insert it into the old component, and then change the public capabilities.&lt;/li&gt;
&lt;li&gt;Embed old wheels in new applications.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Migration method 3: old embedded in new&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build a new Web Component component. Cooperate with monorepo management&lt;/li&gt;
&lt;li&gt;Embed components into existing applications.&lt;/li&gt;
&lt;li&gt;Improve the componentless architecture mechanism.&lt;/li&gt;
&lt;li&gt;Build a low-code orchestration model.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Componentless architecture concept
&lt;/h3&gt;

&lt;p&gt;From the current personal understanding, its core concept is: &lt;strong&gt;Components are "services."&lt;/strong&gt; That is, components can be deployed and updated freely, just like services. After the component is updated, the application has also reached the update of the application in a sense.&lt;/p&gt;

&lt;p&gt;In addition, there are such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Automated environment isolation. Christmas is coming soon&lt;/li&gt;
&lt;li&gt;Generate low code. The real front end glue&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;More content remains to be explored.&lt;/p&gt;

&lt;h3&gt;
  
  
  Componentless architecture issues
&lt;/h3&gt;

&lt;p&gt;In addition to the many advantages mentioned above, it also has a series of shortcomings to be solved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Browser compatibility. Web Component2 compatibility issues&lt;/li&gt;
&lt;li&gt;Test difficulty. Free architecture often means the cost of testing, which is similar to microservices and serverless at this point. More end-to-end testing will be required to ensure the quality of the project.&lt;/li&gt;
&lt;li&gt;The division basis of component modularization. When we build a set of components, we need to find a way to plan rationally.&lt;/li&gt;
&lt;li&gt;Monorepo management. The more repo, the more complicated the management. Need to introduce tools such as nx and pnpm for management.&lt;/li&gt;
&lt;li&gt;Upgrade strategy. That is, the upgrade strategy of the application and the component set should remain inconsistent.
...&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Advantage scenario: combined with lowcode
&lt;/h3&gt;

&lt;p&gt;In a sense, componentless architecture is a generalized low-code implementation mode. Because of the more independent component model, the low-code system it builds is more interesting:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configuration is runtime. It is similar to the process-oriented style of Oracle DB, and realizes new features quickly on the line.&lt;/li&gt;
&lt;li&gt;Fill-in-the-blank programming for code generation. As mentioned in the above example, basic function codes can be generated, and then developers can add code logic.&lt;/li&gt;
&lt;li&gt;Low code based on stream orchestration. The same applies to the traditional low-code architecture model.&lt;/li&gt;
&lt;li&gt;DSL style low code. Such as Quake based on DSL to build.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's just that, in terms of mode, there is not much difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Componentless patterns
&lt;/h2&gt;

&lt;p&gt;None of the above is interesting. After we adopt Web Component as the implementation technology of componentless architecture, there will be more room for architectural display. Web Components is already a very good container similar to Docker, which can play various fancy containerization modes. We tried some patterns at Quake, which brought a series of challenges, but it was also very interesting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adapter: Compatible with existing components.
&lt;/h3&gt;

&lt;p&gt;Based on the features of WC, encapsulating the components of the existing mainstream frameworks such as Angular, React, Vue, etc., can quickly provide such capabilities. For example, the QuakeTimeline and QuakeCalendar we provide in Quake are all in this way. React components are packaged as Web Components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReactElement&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;quake-calendar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the WC components are exposed to the outside, it doesn't matter what front-end framework is used.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ambassador pattern
&lt;/h3&gt;

&lt;p&gt;In the cloud-native model, the Ambassador model can create services or applications on behalf of consumers and send help services for network requests. The same event can also be encapsulated by components,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchEl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch-api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;fetchEl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/action/suggest);
fetchEl.addEventListener(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;fetchSuccess&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, (res: any) =&amp;gt; {
let response = res.detail;
loading.onDidDismiss().then(() =&amp;gt; {});
callback(response);
})
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, I wrote this just for fun. I created a Loading component and inserted the &lt;code&gt;&amp;lt;fetch-api&amp;gt;&lt;/code&gt; component in Loading to initiate an HTTP request. After the request was successful, the DOM was destroyed.&lt;/p&gt;

&lt;p&gt;In this way, I only need to replace this request component to replace all request APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Infinite nesting "Dolls" patten
&lt;/h3&gt;

&lt;p&gt;In the normal pattenrn, we call the B component in the A component, then in theory, we don't need to call the A component in the B component, it will form a circular reference, but it becomes a function in Web Components.&lt;/p&gt;

&lt;p&gt;For example, in Quake's markdown rendering engine &lt;code&gt;&amp;lt;quake-render&amp;gt;&lt;/code&gt;, the &lt;code&gt;&amp;lt;embed-link&amp;gt;&lt;/code&gt; embedded in the page is rendered conditionally, and the embedded page of the  is also markdown, so we need a  , So you can "mock doll" infinitely, until the current page of the browser is hung up.&lt;/p&gt;

&lt;p&gt;In terms of usage, the two components A and B do not have such a mutual calling relationship.&lt;/p&gt;

&lt;p&gt;PS: Actually this is a bug. Later I thought it was a features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sidecar pattern
&lt;/h3&gt;

&lt;p&gt;In the cloud-native patterns, the sidecar model refers to the deployment of application components into separate processes or containers to provide isolation and encapsulation. In this regard, it is also very simple for Web Components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other parterns
&lt;/h3&gt;

&lt;p&gt;There are still many, you can play slowly when you have time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summarize
&lt;/h2&gt;

&lt;p&gt;Think outside the frame and think about the problem, and you will find all kinds of very interesting things.&lt;/p&gt;

</description>
      <category>componentless</category>
      <category>architecture</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Documentation as Code practises</title>
      <dc:creator>Phodal Huang</dc:creator>
      <pubDate>Mon, 20 Apr 2020 09:13:45 +0000</pubDate>
      <link>https://dev.to/phodal/document-as-code-practises-3a4l</link>
      <guid>https://dev.to/phodal/document-as-code-practises-3a4l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Documentation as Code. Documents are written in a domain-specific language like code, and are managed with reference to software development methods (such as source code management and deployment). It can be edited, previewed, viewed with the help of specific tools, or deployed to the server through a dedicated system. A common architectural pattern of document coding for non-technical personnel is: edit-release-development separation "&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the past month, I am developing a new document system based on Git + Markdown + DSL which is call &lt;a href="https://github.com/phodal/ledge"&gt;Ledge&lt;/a&gt;. I customized a markdown-based markup language to support the file system of radar charts, bar charts, mind maps and other charts. &lt;/p&gt;

&lt;p&gt;Also in the past few years, we have been discussing a variety of coding, infrastructure coding, design coding, requirements coding ... In my article "&lt;a href="https://github.com/phodal/cloud-dev"&gt;Cloud development: R &amp;amp; D as Code&lt;/a&gt;", I designed a fully coded software development process. And today we will discuss another interesting existence: document as code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction 1: Architectural Decision Record: Formatting Documents
&lt;/h2&gt;

&lt;p&gt;Three years ago, when I first came into contact with the concept of "architectural decision record", I was attracted by its concept:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use lightweight text formatting language to describe major decisions
Version along with the code&lt;/li&gt;
&lt;li&gt;Use a specific document format (title, context, decision, status, consequence)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Later, I wrote an &lt;a href="https://github.com/phodal/adr"&gt;ADR&lt;/a&gt; tool using Node.js + TypeScript. Now, in most of my open source recommendations, I will use it to manage some technical decisions. Because this document system designed based on this theory is really great, I can query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a technical decision occurs and the architecture changes, the corresponding modifier&lt;/li&gt;
&lt;li&gt;Backtrack all technical decisions and sort out the architecture development process&lt;/li&gt;
&lt;li&gt;All decisions are recorded in the version control system and can be recovered&lt;/li&gt;
&lt;li&gt;Easy to manage and maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a long-term development system, it is really very useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction 2: Static Site Generation: Data as Code
&lt;/h2&gt;

&lt;p&gt;Static site generation is a hybrid Web development method that deploys by deploying pre-built static files to allow developers to build server-based websites locally.&lt;/p&gt;

&lt;p&gt;When GitHub Pages became the programmer's preferred blog / content / document server, he / she also adopted the technique of static site generation. Static site generation has various advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better reliability, safety, stability, usability, etc.&lt;/li&gt;
&lt;li&gt;Version control&lt;/li&gt;
&lt;li&gt;Easy to test&lt;/li&gt;
&lt;li&gt;Easy to practice continuous deployment. Submit to go online&lt;/li&gt;
&lt;li&gt;Flexible and easy to customize&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, the most important thing that static site generation does is to code the data in the database. When using a CMS such as Wordpress, we store the data in the database to achieve CRUD for the data. An article becomes a fragment in the database binary file.&lt;/p&gt;

&lt;p&gt;Subsequently, the second thing the static site generation tool did was to visualize the text content for people to read. In this way, we have achieved release-development separation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction 3: Customized markup language: expansion
&lt;/h2&gt;

&lt;p&gt;When codify data, we faced a very big challenge: easy-to-write and readable markup languages ​​(such as markdown) only designed the form of the content, and lacked other information related to the content, such as creation time, author, modification time and many more.&lt;/p&gt;

&lt;p&gt;So each static site generator customized its own markdown and added some additional information, such as hexo adopts the form of: &lt;code&gt;year-:month-:day-:title.md&lt;/code&gt; to manage the date and title of the article. In this way, there is no need to read the Git information of this article to construct the entire information.&lt;/p&gt;

&lt;p&gt;The same is true of GitHub Flavored Markdown, which we are familiar with, extending the markdown data field through a compatibility mode that does not significantly disrupt the content format.&lt;/p&gt;

&lt;p&gt;In addition, we can customize charts and mind maps based on markdown data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction 4: Edit-Release-Development Separation: For Non-Technical Personnel
&lt;/h2&gt;

&lt;p&gt;Designing for non-technical personnel is a major challenge for code documentation. As a programmer, we think the markdown syntax can't be simpler, but it's not the case for non-technical people. He / she needs: an easy-to-use visual programmer. To achieve such a goal, we need to make some changes in the architecture, we can try to use the "edit-release-development separation" model to solve this problem.&lt;/p&gt;

&lt;p&gt;That is, we split the process into three steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Editors can use commonly used editors or customized editors&lt;/li&gt;
&lt;li&gt;Developers, writing content display&lt;/li&gt;
&lt;li&gt;When publishing, integrate the two parts of the code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can still choose to manage content with source code management. Just change the database interface to the Git server interface-of course they are slightly different. However, converting local Git to Git remote is basically the same.&lt;/p&gt;

&lt;p&gt;As a result, in the end our cost will be to transform a markdown editor based on Git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Document as code
&lt;/h2&gt;

&lt;p&gt;Perfect, I once again expressed the central idea in the introduction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do you need to document as code?
&lt;/h3&gt;

&lt;p&gt;The main reasons are: if the documentation is not coded, there is no possibility of refactoring.&lt;/p&gt;

&lt;p&gt;The remaining reasons are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Binary documents are difficult to manage version. Imagine &lt;code&gt;2020-02-30.docx&lt;/code&gt; and &lt;code&gt;2020-02-31.docx&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Can't accurately know who is the editor of the document, everyone may be admin, or Zhang San at the meeting&lt;/li&gt;
&lt;li&gt;Can't find which is the latest document&lt;/li&gt;
&lt;li&gt;The documentation is terrible, but you ca n’t reconstruct the binary&lt;/li&gt;
&lt;li&gt;Vendor binding&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There should be more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Documentation as Code?
&lt;/h2&gt;

&lt;p&gt;Back to the topic:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Documentation as Code. Documents are written in a domain-specific language like code, and are managed with reference to software development methods (such as source code management and deployment). It can be edited, previewed, viewed with the help of specific tools, or deployed to the server through a dedicated system. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It has such characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use markup language to write content. Such as markdown&lt;/li&gt;
&lt;li&gt;Version control can be performed through the version control system. Like git&lt;/li&gt;
&lt;li&gt;Programming experience consistent with programming (except that the content cannot be written for testing)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And an efficient document coding system also has such characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continuous deployment, that is, content can be automatically published after modification.&lt;/li&gt;
&lt;li&gt;Organize content indexes with specific forms. For example, to organize content in the form of knowledge base.&lt;/li&gt;
&lt;li&gt;Specific text format. Such as architecture decision records, static content generation, for use to provide a better user experience&lt;/li&gt;
&lt;li&gt;Supports REST API. To modify the content through the editor&lt;/li&gt;
&lt;li&gt;Can support multiple ways of output. Such as the standard HTML of the website, or Docx, Latex, etc.&lt;/li&gt;
&lt;li&gt;Support editing and proofreading workflow&lt;/li&gt;
&lt;li&gt;Support search&lt;/li&gt;
&lt;li&gt;Multiplayer collaboration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In fact, most of the teams do not need the advanced features mentioned above, and they already have mature solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to design a documentation as Code system?
&lt;/h3&gt;

&lt;p&gt;In fact, we have marked the elements we need in four primers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use formatted documents&lt;/li&gt;
&lt;li&gt;Release the system with the help of static site generation technology&lt;/li&gt;
&lt;li&gt;Expand capabilities through custom markup languages&lt;/li&gt;
&lt;li&gt;Implementation of the editor for non-technical personnel&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Design a markup language and its extended syntax, and then implement it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Establish key factors
&lt;/h3&gt;

&lt;p&gt;Considering that my colleagues and I have recently implemented such a system, I still endure the pain of my hands and briefly talk about how to make such a system. The main factors we considered are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chart rendering&lt;/li&gt;
&lt;li&gt;Flowchart rendering&lt;/li&gt;
&lt;li&gt;Visual display&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the chart converted from DSL is easy to modify and can be indexed. Since then, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Expand these capabilities through Markdown's Code syntax&lt;/li&gt;
&lt;li&gt;Use markdown tables and lists to provide data&lt;/li&gt;
&lt;li&gt;Use D3.js to support flowchart drawing&lt;/li&gt;
&lt;li&gt;Use Echarts for charting&lt;/li&gt;
&lt;li&gt;Try to use SVG images&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Implement an MVP
&lt;/h3&gt;

&lt;p&gt;We used Angular + GitHub to quickly implement an MVP:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We use Git as the database. It can achieve the purpose of multi-person collaboration, and can track all changes&lt;/li&gt;
&lt;li&gt;We use GitHub Pages as the server. As soon as the document or code is modified, the latest document is deployed.&lt;/li&gt;
&lt;li&gt;We use marked.js, which allows us to quickly expand the syntax.&lt;/li&gt;
&lt;li&gt;Using textarea combined with markdown to make a simple editor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Subsequently, we carried out a quick iteration on this basis.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Extended syntax
&lt;/h3&gt;

&lt;p&gt;We used the markdown code as the DSL of the chart, extending some of the syntax:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;echarts. Render Echarts charts directly&lt;/li&gt;
&lt;li&gt;mindmap. Markdown List becomes mind map&lt;/li&gt;
&lt;li&gt;radar. Markdown List to radar chart&lt;/li&gt;
&lt;li&gt;process-table. Chart with process&lt;/li&gt;
&lt;li&gt;process-step. Another chart with process&lt;/li&gt;
&lt;li&gt;pyramid. Pyramid graphics&lt;/li&gt;
&lt;li&gt;quadrant. Four-quadrant graph&lt;/li&gt;
&lt;li&gt;class. Directly call CSS class&lt;/li&gt;
&lt;li&gt;graphviz. Use Dot to render pictures&lt;/li&gt;
&lt;li&gt;mermaid. Use mermaid visualization&lt;/li&gt;
&lt;li&gt;webcomponents. Call the WebComponents component&lt;/li&gt;
&lt;li&gt;toolset. Call Toolset related components

&lt;ul&gt;
&lt;li&gt;slider. Trade-off slider&lt;/li&gt;
&lt;li&gt;line-chart. Chart
Therefore, for users, only need to write the following code:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\`\`\`radar
  -Quality maturity evaluation model
   -Built-in quality: 3-&amp;gt; 4
   -Optimize business value: 2-&amp;gt; 2
   -Uniform quality, visualization: 1-&amp;gt; 5
   -Full participation: 3-&amp;gt; 4
   -Fast delivery: 4-&amp;gt; 5
   -Test as an asset: 2-&amp;gt; 3
   -Quick feedback: 5-&amp;gt; 5

config: {"legend": ["Current", "Future"]}
    \`\`\`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can generate the corresponding chart:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hyckDGOm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.phodal.com/static/media/uploads/ledge-star.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hyckDGOm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.phodal.com/static/media/uploads/ledge-star.png" alt="Chart Example" width="880" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also input JSON through config and do some lazy processing (don't exhaust yourself).&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Rewrite the markdown renderer
&lt;/h3&gt;

&lt;p&gt;The biggest challenge we encountered in this process was that as we continued to expand the markdown syntax, the relevant code has become a big ball of mud. Therefore, we have to rewrite this part of the code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resolve token with the help of marked.js lexer&lt;/li&gt;
&lt;li&gt;Generate new token based on token modification&lt;/li&gt;
&lt;li&gt;Traverse the newly generated token and render the element&lt;/li&gt;
&lt;li&gt;Combine virtual scrolling to solve performance problems&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It has been open sourced on GitHub and the corresponding npm package has been released: &lt;code&gt;@ledge-framework/render&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Publish this project
&lt;/h3&gt;

&lt;p&gt;We have published this documented system on GitHub, and you can participate in its use and development.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/phodal/ledge"&gt;https://github.com/phodal/ledge&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project homepage: &lt;a href="https://devops.phodal.com/"&gt;https://devops.phodal.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Then, you become a Markdown engineer, D3.js designer, Echart configuration administrator.&lt;/p&gt;

</description>
      <category>everythingascode</category>
      <category>codify</category>
      <category>docsascode</category>
      <category>coding</category>
    </item>
    <item>
      <title>Clean Architecture for frontend in Action</title>
      <dc:creator>Phodal Huang</dc:creator>
      <pubDate>Sun, 13 Oct 2019 12:26:03 +0000</pubDate>
      <link>https://dev.to/phodal/clean-architecture-for-frontend-in-action-1aop</link>
      <guid>https://dev.to/phodal/clean-architecture-for-frontend-in-action-1aop</guid>
      <description>&lt;p&gt;中文版本（Chinese Version）：《&lt;a href="https://www.phodal.com/blog/clean-frontend-architecture-in-action/" rel="noopener noreferrer"&gt;Clean Architecture 实施指南&lt;/a&gt;》&lt;/p&gt;

&lt;p&gt;In the previous article &lt;a href="https://phodal.github.io/clean-frontend/" rel="noopener noreferrer"&gt;Clean Frontend Architecture&lt;/a&gt;, we introduced how to use Clean Architecture in the frontend. In the past few months, we have implemented the Clean Architecture architecture and have proven that Clean Architecture can also work very well on the frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Architecture + MVP + Componented-based Architecture
&lt;/h2&gt;

&lt;p&gt;Before we get started, let's take a look at the final architecture of Angular apps that use Clean Architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fphodal.github.io%2Fclean-frontend%2Fdocs%2Fimages%2Fclean-mvp-component-based.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fphodal.github.io%2Fclean-frontend%2Fdocs%2Fimages%2Fclean-mvp-component-based.jpg" alt="Clean MVP + Componet-based + MVP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the figure, we split the architecture for this part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data layer. That is, the processing layer of all frontend and backend interactions, from the request to the return result, only returns the value and field which &lt;strong&gt;required by the front end&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;MVP layer. MVP is not the focus of this article, but interestingly, in Angular applications, the module layer can correspond to the backend service. The page under the module layer can also be split according to this.&lt;/li&gt;
&lt;li&gt;The component layer in MVP. A reasonable planning of the component layer will make our componet layer clean, not just the domain layer. Components, the hard part is to meet the scene, not split, combine and package.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here, we have less part of the style layer. As a result, the use of various CSS preprocessors to organize code is very mature; second, CSS has not hurt so much in today's infrastructure.&lt;/p&gt;

&lt;p&gt;We have added more implementation details than our old architecture diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fphodal.github.io%2Fclean-frontend%2Fdocs%2Fimages%2Fclean-frontend-components.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fphodal.github.io%2Fclean-frontend%2Fdocs%2Fimages%2Fclean-frontend-components.jpg" alt="Clean Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the former is qualified and the latter is the architecture under general conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context of implementation
&lt;/h2&gt;

&lt;p&gt;Clean Architecture is not a silver bullet, it is suitable for us, it does not mean it is suitable for you. Especially if you are used to free style and autonomous project development, then the strong standardization of Clean Architecture + Angular is not necessarily for you. However, at the same time, if your team is large and there are more junior developers, then I think normalization can help you reduce problems - easy to maintain.&lt;/p&gt;

&lt;p&gt;So, let me introduce some contexts that are good for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implementation of DDD's microservice backend architecture.&lt;/li&gt;
&lt;li&gt;A member who is interested in implementing a full-stack team.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are other Angular frameworks that are more suitable for the enterprise (pursuing standardization), such as the junior developers, so the specification is more, but better maintained. However, the remaining factors, for our architecture: helpful, but not too big.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing DDD's microservice backend architecture
&lt;/h3&gt;

&lt;p&gt;DDD is just a set of software development methods, and different people understand the DDD self-differentiation. In a specific scenario, when DDD is used for microservice splitting, each subdomain is a specific microservice. Under this model, we need to have a naming pattern to distinguish each service, and one of them is a URL. Each service has its own unique URL prefix/path, and when these services are exposed, the corresponding front-end domain layer can be produced—even if it has not participated in an event storm or domain division.&lt;/p&gt;

&lt;p&gt;For example: &lt;code&gt;/api/payment/&lt;/code&gt;, &lt;code&gt;/api/manage/&lt;/code&gt; can clearly split the front &lt;code&gt;domain data&lt;/code&gt; layer.&lt;/p&gt;

&lt;p&gt;At the same time, if the backend then names the Controller according to the resource path, such as &lt;code&gt;/api/blog/blog/:id&lt;/code&gt;,&lt;code&gt;/api/blog/blog/category/:id&lt;/code&gt;, then the front end can Clearly divide them into the same &lt;code&gt;repository&lt;/code&gt;. Of course, once the backend design has problems, the front end can be clearly noticed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full-stack team
&lt;/h3&gt;

&lt;p&gt;In the past, we built our team as full-featured team in a ThoughtWorks, each team members excel in a particular area, but in other areas, such as good at the frontend and can do backend. It can reduce communication costs to some extent. And that means we have a lot of cost for knowledge transfer. Therefore, we used pair programming to let new people talk about project-related sessions.&lt;/p&gt;

&lt;p&gt;So, when you decide to become a full-featured team (front and back + business analysis), then you will encounter such problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find the front-end code of the app, how to find it quickly?&lt;/li&gt;
&lt;li&gt;Find the corresponding backend code,&lt;/li&gt;
&lt;li&gt;Front and back model corresponding&lt;/li&gt;
&lt;li&gt;......&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keeping the front and back ends as consistent as possible becomes a new challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Directory as layered architecture
&lt;/h2&gt;

&lt;p&gt;In a sense, Clean Architectute is an implementation of &lt;strong&gt;normalization&lt;/strong&gt; and &lt;strong&gt;templating&lt;/strong&gt;. At the same time, its three-layer mechanism in the data layer makes it exist in two layers of &lt;strong&gt;anti-corrosion layer&lt;/strong&gt;, usecase can be used as a buffer layer for services, and the repository layer can isolate back-end services and models.&lt;/p&gt;

&lt;p&gt;In many architectural designs, layered architecture is the easiest to implement because directories are layered. The catalog is a specification that you can see at a glance. Once misplaced, you can see it at a glance.&lt;/p&gt;

&lt;h3&gt;
  
  
  MVP Stratification (Directory Partitioning)
&lt;/h3&gt;

&lt;p&gt;From the catalog results, our division is not much different from the general Angular application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;core&lt;/span&gt;           &lt;span class="c1"&gt;// core code, including basic services and basic code&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;         &lt;span class="c1"&gt;// domain layer code, containing separate Clean schema content for each domain&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;elephant&lt;/span&gt;     &lt;span class="c1"&gt;// a specific domain&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;features&lt;/span&gt;       &lt;span class="c1"&gt;// public domain components&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;presentation&lt;/span&gt;   &lt;span class="c1"&gt;// domain logic page&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;         &lt;span class="c1"&gt;// public page&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;shared&lt;/span&gt;        &lt;span class="c1"&gt;// shared directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The business pages are placed in the &lt;code&gt;presentation&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;Public pages (such as 404) are placed in the &lt;code&gt;pages&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;The business components shared by the business page are placed in the &lt;code&gt;features&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;The remaining common parts are placed in the &lt;code&gt;shared&lt;/code&gt; directory, such as &lt;code&gt;pipes&lt;/code&gt;, &lt;code&gt;utils&lt;/code&gt;, &lt;code&gt;services&lt;/code&gt;, &lt;code&gt;components&lt;/code&gt;, &lt;code&gt;modules&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sample code can be found at: &lt;a href="https://github.com/phodal/clean-frontend" rel="noopener noreferrer"&gt;https://github.com/phodal/clean-frontend&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  domain + data Layer: Vertical + Horizontal Layered
&lt;/h3&gt;

&lt;p&gt;The domain layer in the above directory, the example structure is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;elephant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;       &lt;span class="c1"&gt;// Data entity, a simple data model used to represent the core business logic&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;elephant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;        &lt;span class="c1"&gt;// core business model&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="nx"&gt;elephant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;       &lt;span class="c1"&gt;// Mapping layer for core entity layer mapping, or mapping to core entity layer. Model conversion&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;elephant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;   &lt;span class="c1"&gt;// Repository for reading and storing data.&lt;/span&gt;
&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nx"&gt;usecases&lt;/span&gt;
    &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;elephant&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;by&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;usecase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usecase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt; &lt;span class="c1"&gt;// Use cases, built on top of core entities, and implement the entire business logic of the application.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The relevant explanation is as above, here is not Ctrl + V / Ctrl + C.&lt;/p&gt;

&lt;p&gt;It is worth noting that we are adopting a vertical + horizontal double layered model, and vertical response to domain services. It is suitable for microservices architectures without BFF, especially for microservices backend applications that use DDD.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapping Domain Services
&lt;/h2&gt;

&lt;p&gt;In the previous section, the front-end domain + layer layer actually mapped the backend services. When the current end initiates a request, its flow is generally like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Component / Controller -&amp;gt; Usecase -&amp;gt; Repository -&amp;gt; Controller (backend)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The corresponding return order is: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Controller (backend) -&amp;gt; Repository -&amp;gt; Usecase -&amp;gt; Component / Controller (front end)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To do this, we correspond the Repository to the Controller on the back end. And because of the simplification of the service, most of our usecase also corresponds to the naming in the repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  repository naming: URL naming
&lt;/h3&gt;

&lt;p&gt;To name it without looking at the backend code, we use URLs to name methods in the repository and repository. If there is one&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;th&gt;Abstract&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/api/blog/blog/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;/API/Micro Service Name/Resource Name/Resource ID&lt;/td&gt;
&lt;td&gt;HTTP Verb + Resource + Behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ever since, the corresponding &lt;code&gt;repository&lt;/code&gt; should be named &lt;code&gt;blog.repository.ts&lt;/code&gt;. The name of the corresponding repository is also &lt;code&gt;get-blog-by-id&lt;/code&gt;. Similarly, the repository corresponding to the URL &lt;code&gt;/api/blog/blog/:id/comment&lt;/code&gt; is &lt;code&gt;get-comment-by-blog-id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Well, yes, it is consistent with the access to the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  usecase naming
&lt;/h3&gt;

&lt;p&gt;Since we don't involve complex APIs, the common behavior is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;General verb: get / create / update / delete / patch&lt;/li&gt;
&lt;li&gt;Unconventional: search, submit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Haha, is it similar to the repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Architecture's MVP layer practice
&lt;/h2&gt;

&lt;p&gt;In fact, the MVP layer here, the main content is the component architecture. This part of the content has been in the previous article ( &lt;a href="https://en.phodal.com/2019/07/16/experience-design-component-based-architecture/" rel="noopener noreferrer"&gt;Component-based Architecture's patterns&lt;/a&gt; ) introduced, not detailed here. A brief introduction is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic component library, such as Material Design&lt;/li&gt;
&lt;li&gt;Encapsulation package components. Additional three-party component libraries, such as Infinite Scroller, must be used after encapsulation.&lt;/li&gt;
&lt;li&gt;Customize basic components.&lt;/li&gt;
&lt;li&gt;Domain specific components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above four parts build a common component library module for the entire system. This is followed by domain-related components and page-level components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain related components. Share logical components between different modules and pages.&lt;/li&gt;
&lt;li&gt;Page level components. Share pages between different modules and routes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, there are so many things in this part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clean Architecture Domain + Data Layer Practice
&lt;/h2&gt;

&lt;p&gt;Well, the other parts are not much different from normal project development. So we can focus on the Domain + Data layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  DDD ApplicationService vs Multiple Usecases
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;In DDD practice, it is natural to adopt a top-down implementation. The implementation of ApplicationService follows a very simple principle, that is, a business use case corresponds to a business method on the ApplicationService. &lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A little different is that the Clean Architecture recommended by us is: &lt;strong&gt;A business use case (usecase) corresponds to a business class&lt;/strong&gt;. That is, in the same business scenario, the frontend is a bunch of usecase files, and the back end is an applicationService. So, in this scenario, the frontend has them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;change-production-count.usecase.ts&lt;/li&gt;
&lt;li&gt;delete-product.usecase.ts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The backend is &lt;code&gt;OrderApplicationService.java&lt;/code&gt;, which has multiple methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  usecases + repository vs services
&lt;/h3&gt;

&lt;p&gt;If our usecases + repository does the same thing as a service, isn't it good to just use serivce? Using only service has this problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repeated API calls&lt;/li&gt;
&lt;li&gt;Calling context not clearly defined&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, use usecase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More templated code&lt;/li&gt;
&lt;li&gt;More stratification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reuse rate of Usecases is extremely low, and the project will dramatically increase the class and duplicate code. Therefore, we try to increase the maintainability of the architecture with more code. PS: More code, it may also reduce the maintainability of the code, but in today's intelligent IDE, this should not be a problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usecases as a logical layer / anti-corrosion layer
&lt;/h3&gt;

&lt;p&gt;However, Usecases brings a layer of anti-corrosion while bringing more code. It is responsible for the following responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business logic processing. Process the necessary content before the data is passed to the back end.&lt;/li&gt;
&lt;li&gt;Return to data management. From the data returned from the backend, build the results needed for the front end. This can be done in usecase when multiple APIs need to be called.&lt;/li&gt;
&lt;li&gt;Input parameter management.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, the Usecases layer is very useful when the current end is given too much business logic. Conversely, if the logic is placed in the BFF layer, the Usecases layer becomes a bit sloppy. But it is still a very good anti-corrosion layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model Management
&lt;/h2&gt;

&lt;p&gt;As we work with Usecase, we need to solve the frontend model problem. The backend has multiple microservices and multiple projects, each with its own model. And if there is only one project in the frontend, the frontend model management becomes a pain point. Because in different contexts, the backend model is different. That is to say, in different APIs, the models are different, and these models are customized according to the business, and finally aggregated together at the front end.&lt;/p&gt;

&lt;p&gt;At this time, it is possible to have multiple different models for the same resource. So either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frontend has a one-to-one model. It is more troublesome to manage.&lt;/li&gt;
&lt;li&gt;Use the same model. You cannot use type checking to reduce bugs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Currently, I can't figure out a better solution. We use the second way to manage model, after all, it is easier to manage.&lt;/p&gt;

&lt;p&gt;Here are a few of our types of classification and management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request Model / Response Model&lt;/strong&gt;. That is, the request parameters and the return model (modified, for frontend view) are placed in the corresponding &lt;code&gt;.model.ts&lt;/code&gt; directory of the service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response Entity&lt;/strong&gt;. When using the backend to return results directly, the name has &lt;code&gt;entity&lt;/code&gt;, otherwise &lt;code&gt;model&lt;/code&gt; is used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View Model / Component Model&lt;/strong&gt;. When applied to the encapsulation of business components, incoming parameters are passed in by model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you have better practices?&lt;/p&gt;

&lt;h2&gt;
  
  
  Question
&lt;/h2&gt;

&lt;p&gt;Is it clean? not yet&lt;/p&gt;

&lt;h3&gt;
  
  
  Framework dependent form validation
&lt;/h3&gt;

&lt;p&gt;Since the Angular framework itself provides powerful Reactive Form functionality, we use Reactive Forms in most of the form design, rather than through Entity. This allows us to interact in this part of the UI, relying on the Angular framework, rather than implementing it ourselves.&lt;/p&gt;

&lt;p&gt;If you use an Entity mode such as DDD, or use a validator. Later, we also need to develop our own form validation mode, similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;Validator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it means a lot of development costs. However, fortunately, we can try to generalize it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next step
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clean form&lt;/strong&gt;. As mentioned above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code generation&lt;/strong&gt;. Although we have already used Angular Schematics in our project to generate template code. But I believe that in the next step we can use tools to generate pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architectural Guardian&lt;/strong&gt;. With a hierarchical structure, it is easier to determine the hierarchical relationship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try Other frameworks&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://insights.thoughtworks.cn/backend-development-ddd/" rel="noopener noreferrer"&gt;https://insights.thoughtworks.cn/backend-development-ddd/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>frontend</category>
      <category>action</category>
    </item>
    <item>
      <title>Micro-frontend Architecture in Action with six ways.</title>
      <dc:creator>Phodal Huang</dc:creator>
      <pubDate>Wed, 26 Jun 2019 05:11:32 +0000</pubDate>
      <link>https://dev.to/phodal/micro-frontend-architecture-in-action-4n60</link>
      <guid>https://dev.to/phodal/micro-frontend-architecture-in-action-4n60</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Micro-frontends is a microservice-like architecture that applies the concept of microservices to the browser side. Transforming to a mono-like applications from a single, single application to an application that combines multiple small front-end applications. Each frontend application can also be &lt;strong&gt;standalone run&lt;/strong&gt;, &lt;strong&gt;independent development&lt;/strong&gt;, &lt;strong&gt;standalone deployment&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the same time, they can also be developed in parallel with &lt;strong&gt;sharing components&lt;/strong&gt; - these components can be managed via NPM or Git Tag, Git Submodule etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The front-end application here refers to a single-page application separated from the front and back. It is meaningful to talk about the micro-frontends on this basis.&lt;/p&gt;

&lt;p&gt;TOC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Thinking in Microfrontend
&lt;/li&gt;
&lt;li&gt;  Why micro-frontends be popular – aggregation of web applications

&lt;ul&gt;
&lt;li&gt;  Migration frontend legacy system
&lt;/li&gt;
&lt;li&gt;  Backend decoupling, frontend aggregation
&lt;/li&gt;
&lt;li&gt;  Compatible with legacy systems
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Six ways to implement a micro-frontends architecture

&lt;ul&gt;
&lt;li&gt;  Basic: Application Distribution Routing -&amp;gt; Route Distribution Application

&lt;ul&gt;
&lt;li&gt;  Backend: Function Call -&amp;gt; Remote Call
&lt;/li&gt;
&lt;li&gt;  Front End: Component Call -&amp;gt; Application Call
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Route-dispatch micro-frontends
&lt;/li&gt;

&lt;li&gt;  Create a container with iFrame
&lt;/li&gt;

&lt;li&gt;  Homemade micro-frontends framework
&lt;/li&gt;

&lt;li&gt;  Combined integration: Widging applications
&lt;/li&gt;

&lt;li&gt;  Pure Web Components technology build
&lt;/li&gt;

&lt;li&gt;  Build with Web Components

&lt;ul&gt;
&lt;li&gt;  Integrating existing frameworks in Web Components
&lt;/li&gt;
&lt;li&gt;  Web Components integrated into existing frameworks
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Compound type micro-frontends
&lt;/li&gt;

&lt;li&gt;  Microfrontend Quick Selection Guide
&lt;/li&gt;

&lt;li&gt;  Comparison of micro front-end solutions: a brief comparison
&lt;/li&gt;

&lt;li&gt;  Comparison of micro front-end solutions: complex ways
&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;  How to deconstruct mono front-end application - microservice splitting of front-end applications

&lt;ul&gt;
&lt;li&gt;  front end microservice

&lt;ul&gt;
&lt;li&gt;  Independent development
&lt;/li&gt;
&lt;li&gt;  Independent deployment
&lt;/li&gt;
&lt;li&gt;  Do we really need technology independently?
&lt;/li&gt;
&lt;li&gt;  Does not affect the user experience
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Micro-frontends design concept

&lt;ul&gt;
&lt;li&gt;  Design Concept 1: Centralized Routing
&lt;/li&gt;
&lt;li&gt;  Design Concept 2: Identification Application
&lt;/li&gt;
&lt;li&gt;  Design Concept 3: Life Cycle
&lt;/li&gt;
&lt;li&gt;  Design Concept 4: Independent Deployment and Configuration Automation
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Practical micro-frontends architecture design

&lt;ul&gt;
&lt;li&gt;  Independent Deployment and Configuration Automation
&lt;/li&gt;
&lt;li&gt;  Inter-Application Routing - Events
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;  Four to split large Angular application to micro-frontends

&lt;ul&gt;
&lt;li&gt;  1, front-end micro-services: routing lazy loading and its variants
&lt;/li&gt;
&lt;li&gt;  2, microservice solution: sub-application mode
&lt;/li&gt;
&lt;li&gt;  Solution comparison

&lt;ul&gt;
&lt;li&gt;  Standard LazyLoad
&lt;/li&gt;
&lt;li&gt;  LazyLoad Variant 1: Build-time integration
&lt;/li&gt;
&lt;li&gt;  LazyLoad variant 2: Post-build integration
&lt;/li&gt;
&lt;li&gt;  Front-end micro-service
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Total contrast
&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Why micro-frontends be popular – aggregation of web applications
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Adopting new technology, more is not because of advanced, but because it can solve the pain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the past, I have always had a doubt as to whether people really need microservices and whether they really need micro-frontends. After all, there is no silver bullet. When people consider whether to adopt a new architecture, in addition to considering its benefits, it still considers the large number of risks and technical challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration frontend legacy system 
&lt;/h2&gt;

&lt;p&gt;For past years, I have received some consultations on how to implement micro-frontends architecture. In the meantime, I found a very interesting thing: &lt;strong&gt;Resolving the legacy system is the most important reason people use the micro-frontends solution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In these consultations, the situation encountered by the developers is similar to the situation I encountered before. My scenario is: design a new front-end architecture. They began to consider frontend with micro-services because of the legacy system.&lt;/p&gt;

&lt;p&gt;In the past, single-page applications written using Backbone.js, Angular.js, Vue.js 1 and other frameworks have been running steadily online and have no new features. For such applications, there is no reason to waste time and paty effort to rewriting old applications. Applications in here, using old, no longer used technology stacks can be called legacy systems. However, these applications need to be combined into new applications. The more I've encountered is that the old app was written in Angular.js, and the new app started with Angular 2+. This is a very common technology stack for a business-stable IT team.&lt;/p&gt;

&lt;p&gt;Under the premise of not rewriting the original system, it is possible to extract manpower to develop new business. It is not only a very attractive feature for business people; it is also quite challenging for technicians not to rewrite old business and to make some technical challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend decoupling, frontend aggregation
&lt;/h2&gt;

&lt;p&gt;A selling point for front-end microservices is also here, to be compatible with different types of front-end frameworks. This reminds me of the benefits of microservices and the reasons why many projects fall into microservices:&lt;/p&gt;

&lt;p&gt;In the early, a big selling point for back-end microservices was that different technology stacks could be used to develop background applications. However, in fact, organizations and institutions that adopt a micro-service architecture are generally medium to large-scale. Compared with small and medium-sized, the selection of frameworks and languages ​​is more stringent, such as limiting the framework internally and limiting the language. Therefore, it is almost rare to fully utilize the different technology stacks to take advantage of microservices. In these large organizations, the main reason for adopting microservices is to &lt;strong&gt;use the microservices architecture to decouple inter-service dependencies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the frontend micro-services, it is exactly the opposite. The result people want more is &lt;strong&gt;aggregation&lt;/strong&gt;, especially those applications of To B(to Bussiness).&lt;/p&gt;

&lt;p&gt;In the past two or three years, mobile applications have shown a trend, users do not want to install so many applications. And often a large commercial company offers a range of applications. These applications also reflect, to some extent, the organizational structure of the company. However, in the eyes of users they are a company, they should only have one product. Similarly, this trend is also emerging on the desktop web. &lt;strong&gt;Aggregation&lt;/strong&gt; has become a technology trend, and the aggregation in the front end is the micro-service architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatible with legacy systems
&lt;/h2&gt;

&lt;p&gt;Then, at this time, we need to use new technologies and new architectures to accommodate and be compatible with these old applications. The front-end micro-services just fits the selling point that people want.&lt;/p&gt;

&lt;h1&gt;
  
  
  Six ways to implement a micro-frontends architecture
&lt;/h1&gt;

&lt;p&gt;Combined with my practice and research in the &lt;a href="https://github.com/phodal/microfrontends" rel="noopener noreferrer"&gt;micro-frontends&lt;/a&gt; in the past six months, the micro-frontends architecture can generally be implemented in the following ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use HTTP server routing to redirect multiple apps&lt;/li&gt;
&lt;li&gt;Design communication and loading mechanisms on different frameworks, such as &lt;a href="https://github.com/phodal/mooa" rel="noopener noreferrer"&gt;Mooa&lt;/a&gt; and &lt;a href="https://github.com/CanopyTax/single-spa" rel="noopener noreferrer"&gt;Single-SPA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Build a single application by combining multiple independent applications and components&lt;/li&gt;
&lt;li&gt;iFrame. Use iFrame and custom messaging mechanisms&lt;/li&gt;
&lt;li&gt;Build an app with pure Web Components&lt;/li&gt;
&lt;li&gt;Building with Web Components&lt;/li&gt;
&lt;li&gt;Seperate application in build-time (TBC)&lt;/li&gt;
&lt;li&gt;Seperate appliation in local build time (TBC)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Basic: Application Distribution Routing -&amp;gt; Route Distribution Application
&lt;/h2&gt;

&lt;p&gt;In a monoli front-end, mono back-end application, there is a typical feature that routing is distributed by the &lt;strong&gt;framework&lt;/strong&gt;, which assigns routes to corresponding components or internal services. What the microservice does in the process is to call the &lt;strong&gt;function call&lt;/strong&gt; into a &lt;strong&gt;remote call&lt;/strong&gt;, such as a remote HTTP call. The micro-frontends is similar, it is to change the component call** in the application into a more fine-grained &lt;strong&gt;inter-application component call&lt;/strong&gt;, that is, we just distribute the route to the application component execution. Now you need to find the corresponding application based on the route, and then distribute it to the corresponding component by the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend: Function Call -&amp;gt; Remote Call
&lt;/h3&gt;

&lt;p&gt;In most CRUD-type web applications, there are some very similar patterns, namely: Home -&amp;gt; List -&amp;gt; Details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Home page for displaying specific data or pages to users. These data are usually a finite number and are of multiple models.&lt;/li&gt;
&lt;li&gt;List, the aggregation of the data model, which is typically a collection of data of a certain type, can see as many ** data summaries** (such as Google only returns 100 pages), typically see Google, Taobao / Ebay, Amazon search results page.&lt;/li&gt;
&lt;li&gt;Details, showing as much content as possible for a single piece of data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's an example of a Spring framework for returning to the home page:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;Public&lt;/span&gt; &lt;span class="nc"&gt;ModelAndView&lt;/span&gt; &lt;span class="nf"&gt;homePage&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;
   &lt;span class="nc"&gt;Return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ModelAndView&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/WEB-INF/jsp/index.jsp"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For a detail page, it might look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/detail/{detailId}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;Public&lt;/span&gt; &lt;span class="nc"&gt;ModelAndView&lt;/span&gt; &lt;span class="nf"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpServletRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ModelMap&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
   &lt;span class="o"&gt;....&lt;/span&gt;
   &lt;span class="nc"&gt;Return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ModelAndView&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/WEB-INF/jsp/detail.jsp"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"detail"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So, in the case of microservices, it will look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;

&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/name"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;Public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;restTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getForObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://account/name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Return&lt;/span&gt; &lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="err"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the process, the backend has a service discovery service to manage the relationship between different microservices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Front End: Component Call -&amp;gt; Application Call
&lt;/h3&gt;

&lt;p&gt;Formally speaking, the routing of the single front-end framework and the single-end back-end application are not much different: &lt;strong&gt;Return the templates of different pages according to different routes&lt;/strong&gt;. An Angular examples:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IndexComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;detail/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DetailComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And when we micro-service it, it may become the route of application A:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IndexComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Plus the route of application B:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appRoutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;detail/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DetailComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The key to the problem is: &lt;strong&gt;How to dispatch routes to these different applications&lt;/strong&gt;. At the same time, it is also responsible for managing different front-end applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Route-dispatch micro-frontends
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;route-distributed micro-frontends&lt;/strong&gt;, which distributes different services** to different, independent front-end applications by routing. It can usually be implemented by a reverse proxy of the HTTP server, or by the routing that comes with the application framework.&lt;/p&gt;

&lt;p&gt;For the moment, the micro-frontends architecture through route distribution should be the most popular and easy-to-use "micro-frontends" solution. But this approach looks more like an aggregation of multiple front-end applications, that is, we just put together these different front-end applications to make them look like a complete whole. But they are not, every time a user applies from A to B, they often need to refresh the page.&lt;/p&gt;

&lt;p&gt;In a project a few years ago, we were working on a &lt;strong&gt;legacy system rewrite&lt;/strong&gt;. We have a migration plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, use &lt;strong&gt;static website generation&lt;/strong&gt; to dynamically generate the home page&lt;/li&gt;
&lt;li&gt;Second, refactor the details page using the React stack&lt;/li&gt;
&lt;li&gt;Finally, replace the search results page&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole system is not a one-time migration, but a step by step. So when we need to complete the different steps, we need to go online, so we need to use Nginx for route distribution.&lt;/p&gt;

&lt;p&gt;The following is an example of a Nginx configuration based on route distribution:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt;       &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt;  &lt;span class="s"&gt;www.phodal.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://http://172.31.25.15:8000/api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/web/admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://172.31.25.29/web/admin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/web/notifications&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://172.31.25.27/web/notifications&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this example, requests for different pages are distributed to different servers.&lt;/p&gt;

&lt;p&gt;Later, we used a similar approach on other projects, the main reason is: &lt;strong&gt;cross-team collaboration&lt;/strong&gt;. When the team reaches a certain size, we have to face this problem. In addition, there is the problem of Angluar cliff-style upgrade. So, in this case, the user foreground uses Angular rewrite, and the background continues to use Angular.js and so on to keep the technology stack. In different scenarios, there are some similar technical decisions.&lt;/p&gt;

&lt;p&gt;So in this case it works for the following scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The difference between different technology stacks is relatively large, and it is difficult to be compatible, migrated, and modified.&lt;/li&gt;
&lt;li&gt;The project does not want to spend a lot of time on the transformation of this system&lt;/li&gt;
&lt;li&gt;Existing systems will be replaced in the future&lt;/li&gt;
&lt;li&gt;System functions are perfect, there are no new requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the case of satisfying the above scenario, if it is for a better user experience, it can also be solved by using an iframe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a container with iFrame
&lt;/h2&gt;

&lt;p&gt;iFrame is a very old technology that everyone feels ordinary, but it has always worked.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;HTML Inline Framework Elements&lt;/strong&gt;  &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; represents a nested context being browsed that effectively embeds another HTML page into the current page.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Iframes can create a completely new, stand-alone hosting environment, which means our front-end applications can run independently of each other. There are several important prerequisites for using an iframe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website does not require SEO support&lt;/li&gt;
&lt;li&gt;Have the appropriate &lt;strong&gt;application management mechanism&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we are working on an application platform, we will integrate a third-party system in our system, or a system under a number of different department teams. Obviously this is a good solution. Some typical scenarios, such as traditional desktop applications, are migrated to web applications:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffofvity3a5ozvtyu96n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fffofvity3a5ozvtyu96n.png" alt="Angular Tabs example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this type of application is too complex, then it must be a split for microservices. Therefore, when using an iframe, we need to do two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design &lt;strong&gt;Management Application Mechanism&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Design &lt;strong&gt;Application Communication Mechanism&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Load mechanism&lt;/strong&gt;. Under what circumstances, we will load and unload these applications; in the process, what kind of animation transition is used to make the user look more natural.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Communication mechanism&lt;/strong&gt;. Creating a &lt;code&gt;postMessage&lt;/code&gt; event directly in each app and listening is not a friendly thing. It's inherently intrusive to the application, so getting the Window object of the iFrame element through &lt;code&gt;iframeEl.contentWindow&lt;/code&gt; is a much simpler approach. Then, you need to &lt;strong&gt;define a set of communication specifications&lt;/strong&gt;: what format the event name uses, when to start listening for events, and so on.&lt;/p&gt;

&lt;p&gt;Interested readers can look at the micro front-end framework that I wrote before: &lt;a href="https://github.com/phodal/mooa" rel="noopener noreferrer"&gt;Mooa&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Either way, iframe is afraid that we will not bring benefit to our KPI this year, so let's build a wheel. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Homemade micro-frontends framework 
&lt;/h2&gt;

&lt;p&gt;Whether it's Web Components-based Angular or VirtualDOM's React, existing front-end frameworks are inseparable from the basic HTML element DOM.&lt;/p&gt;

&lt;p&gt;Well, we only need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Introduce or create a DOM where appropriate on the page&lt;/li&gt;
&lt;li&gt;When the user operates, load the corresponding application (trigger the launch of the application) and uninstall the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first problem, creating a DOM is an easy problem to solve. The second problem is not easy at all, especially to remove the monitoring of the DOM and the corresponding application. When we have a different technology stack, we need to design a set of such logic.&lt;/p&gt;

&lt;p&gt;Although &lt;a href="https://github.com/CanopyTax/single-spa" rel="noopener noreferrer"&gt;Single-SPA&lt;/a&gt; already has startup and uninstallation processing for most frameworks (such as React, Angular, Vue, etc.), it is still not suitable for production. When I designed a micro front-end architecture application for the Angular framework based on Single-SPA, I finally chose to rewrite my own framework, &lt;a href="https://github.com/phodal/mooa" rel="noopener noreferrer"&gt;Mooa&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Although the difficulty of getting started in this way is relatively high, it is convenient to order and maintainability later. Regardless of the user experience issues caused by each application being loaded, the only possible risk may be: &lt;strong&gt;third-party libraries are not compatible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, no matter what, compared with iFrame, it is technically more &lt;strong&gt;savvy&lt;/strong&gt;, and more interesting. Similarly, similar to iframes, we still face a series of minor problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Need to design a mechanism to manage the application.&lt;/li&gt;
&lt;li&gt;For toC applications with high traffic, there will be a lot of requests when loading for the first time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we have to split the application again, and want to blabla..., what else can we do?&lt;/p&gt;

&lt;h2&gt;
  
  
  Combined integration: Widging applications
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Combined integration&lt;/strong&gt;, which is a step-by-step splitting and recombination of the application in the steps of pre-build, build-time, post-build, etc. by means of &lt;strong&gt;software engineering&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From this definition point of view, it may not be a micro-frontends - it can satisfy the three elements of the micro-frontends, namely: &lt;strong&gt;independent run&lt;/strong&gt;, &lt;strong&gt;independent development&lt;/strong&gt;, &lt;strong&gt;independent deploy&lt;/strong&gt;. However, with the Lazyload function of the component of the front-end framework - that is, when the required business component or application is loaded, it looks like a micro front-end application.&lt;/p&gt;

&lt;p&gt;At the same time, CSS styles don't need to be reloaded because all the dependencies and pollyfill have been loaded as much as possible for the first time.&lt;/p&gt;

&lt;p&gt;Common ways are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build components and applications independently, generate chunk files, build and then categorize the generated chunk files. (This approach is more similar to microservices, but at a higher cost)&lt;/li&gt;
&lt;li&gt;Develop components or applications independently at development time, merge components and applications when integrating, and finally generate single-body applications.&lt;/li&gt;
&lt;li&gt;At runtime, load the application's Runtime and then load the corresponding application code and template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The relationship between the applications is shown in the following figure&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmz4bl7ol5me8ug7hrzjl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmz4bl7ol5me8ug7hrzjl.jpg" alt="Combined integration comparison"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach seems quite ideal, that is, to meet the parallel development of multiple teams, but also to build a suitable deliverable.&lt;/p&gt;

&lt;p&gt;But first, it has a serious limitation: &lt;strong&gt;must use the same framework&lt;/strong&gt;. For most teams, this is not a problem. Teams that use microservices will not use different languages ​​and technologies to develop them because of the front end of microservices. Of course, if you want to use another framework, it is not a problem, we only need to combine the ** homemade framework compatible application in the previous step to meet our needs.&lt;/p&gt;

&lt;p&gt;Second, there is a limit to this approach, which is: &lt;strong&gt;specification!&lt;/strong&gt; &lt;strong&gt;specification!&lt;/strong&gt; &lt;strong&gt;specification!&lt;/strong&gt;. In adopting this approach, we need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unified dependencies. Keep these dependent versions and add new ones.&lt;/li&gt;
&lt;li&gt;Specification of the components and routes of the application. Avoid conflicts between different applications because these component names conflict.&lt;/li&gt;
&lt;li&gt;Build complex. In some scenarios, we need to modify the build system, and in some scenarios we need complex schema scripts.&lt;/li&gt;
&lt;li&gt;Share common code. This is obviously a problem that we must face frequently.&lt;/li&gt;
&lt;li&gt;Develop code specifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, this approach looks more like a software engineering problem.&lt;/p&gt;

&lt;p&gt;Now, we have four options, each with its own pros and cons. Obviously, combining them would be a more ideal approach.&lt;/p&gt;

&lt;p&gt;Taking into account the limitations of existing and commonly used technologies, let us look again in the long run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pure Web Components technology build
&lt;/h2&gt;

&lt;p&gt;In the process of learning Web Components to develop a micro-frontends architecture, I tried to write my own Web Components framework: &lt;a href="https://github.com/phodal/oan" rel="noopener noreferrer"&gt;oan&lt;/a&gt;. After adding some basic web front-end framework features, I found this technology to be particularly suitable for &lt;strong&gt;as the cornerstone of the micro-frontends&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Web Components is a different set of technologies that allow you to create reusable custom elements (their functionality is packaged outside of your code) and use them in your web applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It consists mainly of four technical components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom elements, allowing developers to create custom elements such as .&lt;/li&gt;
&lt;li&gt;Shadow DOM, the shadow DOM, usually attaches the Shadow DOM to the main document DOM and controls its associated functionality. This Shadow DOM cannot be directly controlled by other main document DOMs.&lt;/li&gt;
&lt;li&gt;HTML templates, the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt; elements, are used to write markup templates that are not displayed on the page.&lt;/li&gt;
&lt;li&gt;HTML Imports for introducing custom components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each component is introduced by the &lt;code&gt;link&lt;/code&gt; tag:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;link rel="import" href="components/di-li.html"&amp;gt;
&amp;lt;link rel="import" href="components/d-header.html"&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, in the respective HTML file, create the corresponding component elements and write the corresponding component logic. A typical Web Components application architecture is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb1lk3w8qemzu200n3hh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcb1lk3w8qemzu200n3hh.png" alt="Web Components Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that this is similar to the way we use iframes above. The components have their own separate &lt;code&gt;scripts&lt;/code&gt; and &lt;code&gt;styles&lt;/code&gt;, and the corresponding domain names for the individual deployment components. However, it is not as good as it is supposed to be. It is difficult to build front-end applications directly using &lt;strong&gt;Web Components&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewrite existing front-end applications. Yes, now we need to complete the use of Web Components to complete the functionality of the entire system.&lt;/li&gt;
&lt;li&gt;The upstream and downstream ecosystems are not perfect. There is a lack of support for some third-party controls, which is why jQuery is quite popular.&lt;/li&gt;
&lt;li&gt;The system architecture is complex. When an application is split into one component after another, communication between components becomes a particularly big problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ShadowDOM in Web Components is more like a new generation of front-end DOM containers. Unfortunately, not all browsers can fully support Web Components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build with Web Components
&lt;/h2&gt;

&lt;p&gt;Web Components are too far away from us, but combining Web Components to build front-end applications is an architecture for future evolution. Or in the future, we can start to build our application in this way. Fortunately, there are already frameworks to create this possibility.&lt;/p&gt;

&lt;p&gt;For now, there are two ways to build a micro front-end application with Web Components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build framework-independent components using Web Components and then introduce them in the corresponding framework&lt;/li&gt;
&lt;li&gt;Introducing an existing framework in Web Components, similar to the form of an iframe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The former is a component-based approach, or it is like migrating future “legacy systems” to future architectures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrating existing frameworks in Web Components
&lt;/h3&gt;

&lt;p&gt;Existing Web frameworks already have forms that support Web Components, such as createCustomElement supported by Angular, to implement a component in the form of a Web Component:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;platformBrowser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bootstrapModuleFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyPopupModuleNgFactory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyPopupElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCustomElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyPopup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;popup&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyPopupElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the future, there will be more frameworks that can be integrated into the Web Components application using a form like this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web Components integrated into existing frameworks
&lt;/h3&gt;

&lt;p&gt;Alternatively, it is similar to the form of &lt;a href="https://github.com/ionic-team/stencil" rel="noopener noreferrer"&gt;Stencil&lt;/a&gt;, which builds the component directly into a component in the form of Web Components, and then in the corresponding such as React or Direct reference in Angular.&lt;/p&gt;

&lt;p&gt;Here's an example of a Web Component generated by reference to Stencil in React:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;registerServiceWorker&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./registerServiceWorker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test-components/testcomponents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nf"&gt;registerServiceWorker&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this case, we can build a framework-independent component.&lt;/p&gt;

&lt;p&gt;The same Stencil still only supports recent browsers such as Chrome, Safari, Firefox, Edge and IE11.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compound type micro-frontends
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Composite type&lt;/strong&gt;, right in the above categories, just pick several combinations together.&lt;/p&gt;

&lt;p&gt;I am not nonsense :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Microfrontend Quick Selection Guide
&lt;/h2&gt;

&lt;p&gt;I still give the conclusion directly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmicrofrontends.cn%2Fimgs%2Fchoice-your-microservices-en.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmicrofrontends.cn%2Fimgs%2Fchoice-your-microservices-en.png" alt="Micro Front End Selection Guide"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The relevant explanations of the key points are as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frame restrictions&lt;/strong&gt;. In the back-end microservices system, people use libraries in other languages ​​to develop new services, such as Python for artificial intelligence. But at the front end, there is almost no such possibility. So when we have only one front-end framework, we have a wider range of options when using micro-front-end technology. Unfortunately, most organizations need to be compatible with legacy systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IE problem&lt;/strong&gt;. Whether it was a few years ago or this year, the first consideration we implemented in the micro front end was support for IE. In the projects I have encountered, basically I need to support IE, so there are certain restrictions on the technical selection. And on our projects that don't need to support IE, they can use WebComponents technology to build micro-front-end applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standalone Independence&lt;/strong&gt;. That is, the dependencies of each micro front-end application are to be managed in a unified manner, or to be managed by themselves in each application. Unified management can solve the problem of repeated load dependencies, and independent management brings additional traffic overhead and latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison of micro front-end solutions: a brief comparison
&lt;/h2&gt;

&lt;p&gt;If you are still not familiar with the above aspects, please read the "Six and Seven Ways of Implementing Front-End Microservices."&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ways&lt;/th&gt;
&lt;th&gt;Development Costs&lt;/th&gt;
&lt;th&gt;Maintenance Costs&lt;/th&gt;
&lt;th&gt;Feasibility&lt;/th&gt;
&lt;th&gt;Same Framework Requirements&lt;/th&gt;
&lt;th&gt;Difficulties in Implementation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Route Distribution&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iFrame&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application Microservices&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Micro-Widget&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Micro-apps&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure Web Components&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web Components&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;★★&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Similarly, some complex concepts are explained as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application micro-services&lt;/strong&gt;, that is, each front-end application is a separate service-oriented front-end application, and is equipped with a unified application management and startup mechanism, such as micro-front-end framework Single-SPA or &lt;a href="https://github.com/phodal/mooa" rel="noopener noreferrer"&gt;mooa&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Micro-Widget&lt;/strong&gt;, that is, through the hack of the build system, different front-end applications can use the same set of dependencies. It basically improves the problem of repeatedly loading dependent files in &lt;strong&gt;Apps Microservices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Micro-apps&lt;/strong&gt;, also known as &lt;strong&gt;combined integration&lt;/strong&gt;, that is, through software engineering, splitting single applications in the development environment, and combining the applications into one in the build environment application. For detailed details, you can look forward to the following article "Disassembly and Micro-Service of a Single Front-End Application"&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison of micro front-end solutions: complex ways
&lt;/h2&gt;

&lt;p&gt;I saw a micro-service related &lt;a href="https://www.softwarearchitekt.at/post/2017/12/28/a-software-architect-s-approach-towards-using-angular-and-spas-in-general-for-microservices-aka-microfrontends.aspx" rel="noopener noreferrer"&gt;article&lt;/a&gt;, introduces the difference between different microservices, which uses a more interesting comparison method in detail, here is the same way to show:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Architectural goal&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;a. Independent development&lt;/td&gt;
&lt;td&gt;Independent development without being affected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;b. Standalone deployment&lt;/td&gt;
&lt;td&gt;Can be deployed as a single service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;c. Support different frameworks&lt;/td&gt;
&lt;td&gt;Can use different frameworks at the same time, such as Angular, Vue, React&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d. Shake tree optimization&lt;/td&gt;
&lt;td&gt;Can eliminate unused code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;e. Environmental isolation&lt;/td&gt;
&lt;td&gt;The context between applications is undisturbed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;f. Multiple applications running simultaneously&lt;/td&gt;
&lt;td&gt;Different applications can run simultaneously&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;g. Shared dependencies&lt;/td&gt;
&lt;td&gt;Whether different applications share the underlying dependency library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;h. Dependency conflict&lt;/td&gt;
&lt;td&gt;Whether different versions of dependencies cause conflicts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;i. Integrated Compilation&lt;/td&gt;
&lt;td&gt;The application is finally compiled into a whole, not built separately&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Then, for the table below, a~j in the table represent several different architectural considerations above.&lt;/p&gt;

&lt;p&gt;(PS: Considering the length of several words of Web Components, temporarily refer to it as WC~~)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Way&lt;/th&gt;
&lt;th&gt;a&lt;/th&gt;
&lt;th&gt;b&lt;/th&gt;
&lt;th&gt;c&lt;/th&gt;
&lt;th&gt;d&lt;/th&gt;
&lt;th&gt;e&lt;/th&gt;
&lt;th&gt;f&lt;/th&gt;
&lt;th&gt;g&lt;/th&gt;
&lt;th&gt;h&lt;/th&gt;
&lt;th&gt;i&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Route Distribution&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iFrame&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application Microservices&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Widget&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Micro-application&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pure WC&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Combine WC&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;O&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O in the figure indicates support, blank indicates no support, and - indicates no effect.&lt;/p&gt;

&lt;p&gt;Combine the previous selection guide:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqxsjbkx6ghvvvdcr2ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqxsjbkx6ghvvvdcr2ri.png" alt="Micro Front End Selection Guide"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How to deconstruct mono front-end application - microservice splitting of front-end applications
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Refresh the page? Route splitting? No, dynamically load components.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article is divided into the following four parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to front-end micro-services&lt;/li&gt;
&lt;li&gt;Micro front end design concept&lt;/li&gt;
&lt;li&gt;Practical micro front-end architecture design&lt;/li&gt;
&lt;li&gt;Front-end microservices based on Mooa&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  front end microservice
&lt;/h2&gt;

&lt;p&gt;For front-end microservices, there are some options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web Component obviously has a very good infrastructure. However, we are not likely to rewrite existing applications in large numbers.&lt;/li&gt;
&lt;li&gt;iFrame. Are you serious?&lt;/li&gt;
&lt;li&gt;Another micro front-end framework, Single-SPA, is obviously a better way. However, it is not Production Ready.&lt;/li&gt;
&lt;li&gt;Split the application by routing, and this jump will affect the user experience.&lt;/li&gt;
&lt;li&gt;and many more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, when we consider front-end micro-services, we hope that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent deployment&lt;/li&gt;
&lt;li&gt;Independent development&lt;/li&gt;
&lt;li&gt;technology independently&lt;/li&gt;
&lt;li&gt;Does not affect the user experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Independent development
&lt;/h3&gt;

&lt;p&gt;In the past few weeks, I spent a lot of time learning the code for Single-SPA. However, I found it really too cumbersome to develop and deploy, and I couldn't reach the standard of independent deployment. According to the design of Single-SPA, I need to name my application in the entry file before I can build it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;declareChildApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inferno&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/inferno/inferno.app.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;pathPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/inferno&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At the same time, in my application, I still need to specify my life cycle. This means that when I develop a new application, I have to update two pieces of code: the main project and the application. At this time we are also very likely to work in the same source.&lt;/p&gt;

&lt;p&gt;When there are multiple teams working in the same source, it obviously becomes quite unreliable - for example, the other team is using Tab, and we are using 2 spaces, the next door is used by Pharaoh. 4 spaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  Independent deployment
&lt;/h3&gt;

&lt;p&gt;The biggest problem with a single front-end application is that the js and css files built are quite large. The micro front end means that the file is split into multiple files independently, and they can be deployed independently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do we really need technology independently?
&lt;/h3&gt;

&lt;p&gt;Wait, do we really need &lt;strong&gt;technology independently&lt;/strong&gt;? If we don't need technology, the micro front-end problem is easy to solve.&lt;/p&gt;

&lt;p&gt;In fact, for most companies and teams, technology has nothing to do with an irrelevant speech. When several founders of a company use Java, it is highly likely that Java will continue to be used in future selections. Unless, there are some extra services to implement artificial intelligence using Python. Therefore, in most cases, it is still the only technology stack.&lt;/p&gt;

&lt;p&gt;This is especially true for front-end projects: basically only one framework is selected in a department.&lt;/p&gt;

&lt;p&gt;So we chose Angular.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does not affect the user experience
&lt;/h3&gt;

&lt;p&gt;Using route jumps for front-end micro-services is a very simple and efficient way to split. However, during the route jump, there will be a white screen process. In this process, the application before the jump and the application to be jumped lose control of the page. If there is a problem with this application, then the user will be overwhelmed.&lt;/p&gt;

&lt;p&gt;Ideally, it should be controllable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Micro-frontends design concept
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Design Concept 1: Centralized Routing
&lt;/h3&gt;

&lt;p&gt;Is the nature of the Internet decentralized? No, DNS has decided that it is not. FLAG / TAB , decided that it is not.&lt;/p&gt;

&lt;p&gt;In essence, microservices should be decentralized. However, it cannot be completely decentralized. For a microservice, it requires a &lt;strong&gt;service registry&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The service provider wants to register the notification service address, and the caller of the service should be able to discover the target service.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For a front-end application, this thing is routing.&lt;/p&gt;

&lt;p&gt;From the page, only when we add a menu link on the page, the user can know that a page is available.&lt;/p&gt;

&lt;p&gt;From the code point of view, that is, we need to have a place to manage our application: &lt;strong&gt;find out which applications exist and which application uses which route&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managing our routes is actually managing our applications&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Concept 2: Identification Application
&lt;/h3&gt;

&lt;p&gt;When designing a micro front-end framework, the problem of getting a name for each project lingered me for a long time - how to normalize this thing. Until, I once again thought of Conway's law:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;System design (product structure is equivalent to organizational form, the organization of each design system, which produces a design equivalent to the communication structure between organizations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, it is impossible to have two projects with the same name under the same organization.&lt;/p&gt;

&lt;p&gt;Therefore, this problem is solved simply.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Concept 3: Life Cycle
&lt;/h3&gt;

&lt;p&gt;Single-SPA has designed a basic lifecycle (although it is not managed uniformly) and it contains five states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;load, decide which application to load and bind the lifecycle&lt;/li&gt;
&lt;li&gt;bootstrap, get static resources&lt;/li&gt;
&lt;li&gt;mount, install the application, such as creating a DOM node&lt;/li&gt;
&lt;li&gt;unload, delete the life cycle of the application&lt;/li&gt;
&lt;li&gt;unmount, uninstall the application, such as deleting the DOM node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I basically followed this life cycle in design. Obviously, things like load are superfluous to my design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Concept 4: Independent Deployment and Configuration Automation
&lt;/h3&gt;

&lt;p&gt;In a sense, the entire system is built around the application configuration. If the configuration of the application can be automated, the entire system is automated.&lt;/p&gt;

&lt;p&gt;When we only develop a new component, then we only need to update our components and update the configuration. And this configuration itself should also be automatically generated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical micro-frontends architecture design
&lt;/h2&gt;

&lt;p&gt;Based on the above premise, the workflow of the system is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnq125sa5ld4wxup3mysh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnq125sa5ld4wxup3mysh.png" alt="System Workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The overall engineering process is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the main project is running, it will go to the server to get the latest application configuration.&lt;/li&gt;
&lt;li&gt;After the main project gets the configuration, it will create the application one by one and bind the lifecycle to the application.&lt;/li&gt;
&lt;li&gt;When the main project detects the route change, it will find out if there is a corresponding route matching to the application.&lt;/li&gt;
&lt;li&gt;When the matching pair corresponds to the application, the corresponding application is loaded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Therefore, its corresponding structure is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwd8m280xqg6f9s8t2t7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwd8m280xqg6f9s8t2t7.jpg" alt="Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The overall process is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmmhtorl2qkfya4kb744m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmmhtorl2qkfya4kb744m.png" alt="Workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Independent Deployment and Configuration Automation
&lt;/h3&gt;

&lt;p&gt;The deployment strategy we made is as follows: The configuration file used by our application is called &lt;code&gt;apps.json&lt;/code&gt;, which is obtained by the main project. Every time we deploy, we just need to point &lt;code&gt;apps.json&lt;/code&gt; to the latest configuration file. The configured file class is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;96a7907e5488b6bb.json&lt;/li&gt;
&lt;li&gt;6ff3bfaaa2cd39ea.json&lt;/li&gt;
&lt;li&gt;dcd074685c97ab9b.json&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The configuration of an application is as follows:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;help&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;help-root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;baseScriptUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/assets/help&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styles.bundle.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prefix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;help&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline.bundle.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;polyfills.bundle.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main.bundle.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here &lt;code&gt;selector&lt;/code&gt; corresponds to the DOM node required by the application, and prefix is ​​used for URL routing. These are automatically generated from the &lt;code&gt;index.html&lt;/code&gt; file and &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inter-Application Routing - Events
&lt;/h3&gt;

&lt;p&gt;Because the current application has become two parts: the main project and the application part. There will be a problem: &lt;strong&gt;Only one project can capture routing changes&lt;/strong&gt;. When the primary route of the application is changed by the main project, it cannot be effectively communicated to the sub-application. At this time, the sub-application can only be notified by means of an event, and the sub-application also needs to monitor whether it is the route of the current application.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;urlPrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urlPrefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;urlPrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mooa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;urlPrefix&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urlPrefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Similarly, when we need to jump from application A to application B, we also need a mechanism like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mooa.routing.navigate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Const&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;
  &lt;span class="nc"&gt;If &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;navigateAppByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The rest of the animations like Loading are similar.&lt;/p&gt;

&lt;h1&gt;
  
  
  Four to split large Angular application to micro-frontends
&lt;/h1&gt;

&lt;p&gt;In 2018, we spent a lot of time designing a solution to split a large Angular app. A series of discussions took place from the use of Angular's Lazyload to front-end microservices. Finally, we finally got the result, using the Lazyload variant: &lt;strong&gt;the way to integrate code&lt;/strong&gt; when building.&lt;/p&gt;

&lt;p&gt;As a “professional” consultant, I have been busy designing an Angular split service solution for my clients. Mainly to achieve the following design goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a plug-in web development platform to meet the needs of rapid business change and distributed multi-team parallel development&lt;/li&gt;
&lt;li&gt;Build serviced middleware to build a highly available and highly multiplexed front-end microservice platform&lt;/li&gt;
&lt;li&gt;Support independent delivery and deployment of front ends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simply put, it is to support &lt;strong&gt;application plug-in development&lt;/strong&gt;, and &lt;strong&gt;multi-team parallel development&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application plug-in development&lt;/strong&gt;, the main problem to be solved is: the split problem of bloated large-scale applications. Large front-end applications face a lot of ** legacy code when developing, and code of different services are coupled together. When uploading online, they also face slow loading and low operating efficiency.&lt;/p&gt;

&lt;p&gt;Finally, it falls on two schemes: routing lazy loading and its variants and front-end micro-services&lt;/p&gt;

&lt;h2&gt;
  
  
  1, front-end micro-services: routing lazy loading and its variants
&lt;/h2&gt;

&lt;p&gt;The route is lazy loaded, that is, the application is cut into different codes through different routes, and the corresponding component is loaded when the route is accessed. In the framework of Angular and Vue, it can be implemented by routing + Webpack. And, inevitably, some problems will be needed:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is difficult to develop multiple teams in parallel.&lt;/strong&gt; Route splitting means that we still work in a source repository. You can also try splitting into different projects and compiling them together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every release needs to be recompiled&lt;/strong&gt;, yes, when we just update the code of a submodule, we have to recompile the entire application and republish the application. Instead of building it independently, release it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unified Vendor version&lt;/strong&gt;, it is a good thing to unify third-party dependencies. The key to the problem is that whenever we add a new dependency, we might need to have a meeting to discuss it.&lt;/p&gt;

&lt;p&gt;However, the biggest problem with the standard Route Lazyload is that it is difficult to develop multiple teams in parallel. The reason why it is said is “difficult” because there is still a way to solve this problem. In daily development, a small team will always be developed in a code base, while a large team should be developed in a different code base.&lt;/p&gt;

&lt;p&gt;So, we did some experiments on the standard route lazy loading.&lt;/p&gt;

&lt;p&gt;For a team of 20 or 30 people, they may belong to different departments in the business, and there are technically inconsistent specifications, such as 4 spaces, 2 spaces or Tab. Especially when it is a different company and team, they may have to abandon a series of questions such as testing, code static detection, code style unification and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  2, microservice solution: sub-application mode
&lt;/h2&gt;

&lt;p&gt;In addition to routing lazy loading, we can also use the sub-application mode, that is, each application is independent of each other. That is, we have a pedestal project. When the user clicks on the corresponding route, we load the ** independent ** Angular application; if it is the route under the same application, it does not need to be reloaded. Moreover, these can all be done by relying on the browser cache.&lt;/p&gt;

&lt;p&gt;In addition to routing lazy loading, you can also use an application embedding solution similar to Mooa. The following is an example of HTML generated based on the Mooa framework + Angular development:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;app-root&lt;/span&gt; &lt;span class="na"&gt;_nghost-c0=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;ng-version=&lt;/span&gt;&lt;span class="s"&gt;"4.2.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  ...
  &lt;span class="nt"&gt;&amp;lt;app-home&lt;/span&gt; &lt;span class="na"&gt;_nghost-c2=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;app-app1&lt;/span&gt; &lt;span class="na"&gt;_nghost-c0=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;ng-version=&lt;/span&gt;&lt;span class="s"&gt;"5.2.8"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display: none;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;_ngcontent-c0=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/app-app1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;frameborder=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"100%"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"100%"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:4200/app/help/homeassets/iframe.html"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"help_206547"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/app-home&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/app-root&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Mooa provides two modes, one is based on Single-SPA experiments, loading and rendering two Angular applications on the same page; one is based on iFrame to provide a separate application container.&lt;/p&gt;

&lt;p&gt;Solved the following problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Home page loading faster&lt;/strong&gt;, because only the features needed for the home page need to be loaded, not all dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple teams are developing in parallel&lt;/strong&gt;, each team can be independently developed in their own projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular update independently&lt;/strong&gt;, now we only need to update our application separately without having to update the entire complete application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, it still contains the following issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeated loading of dependencies, ie the modules we use in the A app, will also be reused in the B app. Some can be solved automatically by the browser's cache.&lt;/li&gt;
&lt;li&gt;It takes time to open the corresponding app for the first time, of course ** preloading** can solve part of the problem.&lt;/li&gt;
&lt;li&gt;Running in non-iframe mode, you will encounter unpredictable third-party dependency conflicts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So after summarizing a series of discussions, we formed a series of comparisons:&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution comparison
&lt;/h2&gt;

&lt;p&gt;In this process, we have done a lot of program design and comparison, and I want to write an article to compare the previous results. Look at the picture first:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmz4bl7ol5me8ug7hrzjl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmz4bl7ol5me8ug7hrzjl.jpg" alt="Angular code split comparison"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Table comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;/th&gt;
&lt;th&gt;Standard Lazyload&lt;/th&gt;
&lt;th&gt;Build-Time Integration&lt;/th&gt;
&lt;th&gt;Post-Build Integration&lt;/th&gt;
&lt;th&gt;Application Independent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Development process&lt;/td&gt;
&lt;td&gt;Multiple teams are developing in the same code base&lt;/td&gt;
&lt;td&gt;Multiple teams are developing in different code bases&lt;/td&gt;
&lt;td&gt;Multiple teams are developing in different code bases&lt;/td&gt;
&lt;td&gt;Multiple teams are developing in different code bases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build and publish&lt;/td&gt;
&lt;td&gt;Build only need to take this code to build, deploy&lt;/td&gt;
&lt;td&gt;integrate the code of different code bases, and then build the application&lt;/td&gt;
&lt;td&gt;will be compiled directly into each project module, the runtime will be merged through lazy loading&lt;/td&gt;
&lt;td&gt;will be compiled directly Into several different applications, the runtime is loaded by the main project&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applicable scenarios&lt;/td&gt;
&lt;td&gt;Single team, less dependent library, single business&lt;/td&gt;
&lt;td&gt;Multiple teams, less dependent libraries, single business&lt;/td&gt;
&lt;td&gt;Multiple teams, less dependent libraries, single business&lt;/td&gt;
&lt;td&gt;Multiple teams, relying on multiple systems, complex business&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance mode&lt;/td&gt;
&lt;td&gt;Development, construction, operation integration&lt;/td&gt;
&lt;td&gt;Development separation, construction integration, operation integration&lt;/td&gt;
&lt;td&gt;development separation, construction separation, operation integration&lt;/td&gt;
&lt;td&gt;development, construction, operation separation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The detailed introduction is as follows:&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard LazyLoad
&lt;/h3&gt;

&lt;p&gt;Development process: Multiple teams are developed in the same code base, and only need to use this code to deploy.&lt;/p&gt;

&lt;p&gt;Behavior: development, construction, and operation&lt;/p&gt;

&lt;p&gt;Applicable scenarios: single team, less dependent libraries, single business&lt;/p&gt;

&lt;h3&gt;
  
  
  LazyLoad Variant 1: Build-time integration
&lt;/h3&gt;

&lt;p&gt;Development process: Multiple teams are developed in different code bases. When building, integrate the code of different code bases and build the application.&lt;/p&gt;

&lt;p&gt;Applicable scenarios: multiple teams, less dependent libraries, single business&lt;/p&gt;

&lt;p&gt;Variant-build integration: development separation, integration when building, running one&lt;/p&gt;

&lt;h3&gt;
  
  
  LazyLoad variant 2: Post-build integration
&lt;/h3&gt;

&lt;p&gt;Development process: Multiple teams are developed in different code bases, compiled into different pieces of code at build time, and merged together by lazy loading.&lt;/p&gt;

&lt;p&gt;Applicable scenarios: multiple teams, less dependent libraries, single business&lt;/p&gt;

&lt;p&gt;Variant - post-build integration: development separation, construction separation, operation integration&lt;/p&gt;

&lt;h3&gt;
  
  
  Front-end micro-service
&lt;/h3&gt;

&lt;p&gt;Development process: Multiple teams are developed in different code bases, compiled into different applications at build time, and loaded by the main project at runtime.&lt;/p&gt;

&lt;p&gt;Applicable scenarios: multi-team, relying on Kudo, business complexity&lt;/p&gt;

&lt;p&gt;Front-end micro-services: development, construction, and operation separation&lt;/p&gt;

&lt;h2&gt;
  
  
  Total contrast
&lt;/h2&gt;

&lt;p&gt;The overall comparison is shown in the following table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;x&lt;/th&gt;
&lt;th&gt;Standard Lazyload&lt;/th&gt;
&lt;th&gt;Build-Time Integration&lt;/th&gt;
&lt;th&gt;Post-Build Integration&lt;/th&gt;
&lt;th&gt;Application Independent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dependency Management&lt;/td&gt;
&lt;td&gt;Unified Management&lt;/td&gt;
&lt;td&gt;Unified Management&lt;/td&gt;
&lt;td&gt;Unified Management&lt;/td&gt;
&lt;td&gt;Independent Management of Applications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment Method&lt;/td&gt;
&lt;td&gt;Unified Deployment&lt;/td&gt;
&lt;td&gt;Unified Deployment&lt;/td&gt;
&lt;td&gt;Can be deployed separately. Full deployment when updating dependencies&lt;/td&gt;
&lt;td&gt;Fully independent deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First screen loading&lt;/td&gt;
&lt;td&gt;Depends on the same file, slow loading&lt;/td&gt;
&lt;td&gt;Depends on the same file, slow loading&lt;/td&gt;
&lt;td&gt;Depends on the same file, slow loading&lt;/td&gt;
&lt;td&gt;Depends on their own management, home loading fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loading applications, modules for the first time&lt;/td&gt;
&lt;td&gt;Loading modules only, fast&lt;/td&gt;
&lt;td&gt;Loading modules only, fast&lt;/td&gt;
&lt;td&gt;Loading modules only, fast&lt;/td&gt;
&lt;td&gt;Loading separately, loading slightly slower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pre-build cost&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Design build process&lt;/td&gt;
&lt;td&gt;Design build process&lt;/td&gt;
&lt;td&gt;Design communication mechanism and loading method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance costs&lt;/td&gt;
&lt;td&gt;A code base is not well managed&lt;/td&gt;
&lt;td&gt;Multiple code bases are not uniform&lt;/td&gt;
&lt;td&gt;Late need to maintain component dependencies&lt;/td&gt;
&lt;td&gt;Low maintenance costs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Package optimization&lt;/td&gt;
&lt;td&gt;Shake tree optimization, AoT compilation, delete useless code&lt;/td&gt;
&lt;td&gt;Shake tree optimization, AoT compilation, delete useless code&lt;/td&gt;
&lt;td&gt;Application dependent components can not be determined, can not delete useless code&lt;/td&gt;
&lt;td&gt;Shake tree optimization, AoT compilation, Delete useless code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;origin post at &lt;a href="https://github.com/phodal/microfrontends/blob/master/english.md" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>microfrontends</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
