Several ways to realize front-end microservices

What is the front-end micro service, a lot of online introduction, I will not be verbose, in short, is the integration of various sub-projects together.

According to the book Front-end Architecture: From Getting Started to Micro Front-end, micro front-end architecture can be implemented in one of the following ways:

  1. Redirect multiple applications using HTTP server routing (link hops)
  2. Design communication and loading mechanisms on top of different frameworks such as Mooa and single-SPA
  3. Build a single application by combining multiple independent applications and components
  4. The iFrame. Use iFrame and custom messaging mechanisms
  5. Build applications using pure Web Components
  6. Build with Web Components

More common are iframe and single-SPA, both of which have their strengths.

Advantages and disadvantages of iframe and single-SPA

Advantages and disadvantages of iframe

disadvantages

  1. Page loading problem: affecting the loading of the main page, blocking the onload event, loading itself is also very slow, too much page cache will lead to computer lag. (Can’t be solved)

  2. Layout problem: Iframe must be given a specified height or it will collapse. Solution: The subsystem calculates the height in real time and sends it to the home page via postMessage. The home page dynamically sets the height and modifs the subsystem or proxy insertion script. In some cases, multiple scrollbars appear and the user experience is not good.

  3. Problem with pop-ups and masks: you can center only iframe vertically, not the entire page horizontally.

    • Solution 1: Solve the problem by synchronizing the message with the frame page. Send the pop-up message to the main page, and the main page will pop up, which will greatly change the original project and affect the use of the original project.
    • Solution 2: Modify the style of the popover: Hide the mask layer and modify the position of the popover. The modification is done by inserting CSS styles through proxy servers.
    • Supplement:iframeContent inside cannot be displayed in full screen pop-ups (not full screen), it can only be displayed in full screen within the iframe range, and cannot be displayed in full screen on the home page outside the iframe limit, but this is rare.
  4. Browser forward/Backward problem: Iframe and the main page share the same browsing history, iframe will affect the page forward and backward, most of the time normal, iframe multiple redirection will cause the browser forward and backward function can not be used properly, not all pages, can be ignored. But the iframe page refresh resets (such as jumping from the list page to the details page, and then refreshing, returning to the list page) because the browser’s address bar has not changed.

  5. If the iframe page fails to be redirected to another page, for example, two IFrames can be redirected only within the iframe range. Therefore, the main page must be used for redirecting. However, iframe jumps are rare

  6. The communication between systems with different sources needs to be through postMessage, which has a certain degree of security

advantages

  1. We’re in complete isolation.cssandjs, avoiding styles and styles between systemsjspollution
  2. The subsystem can be embedded without modification at all

Advantages and disadvantages of single-SPA

disadvantages

  1. cssandjsThere needs to be norms and isolation. Otherwise it is easy to cause global pollution, especiallyvueGlobal component, global hook.
  2. Need subsystem cooperation modification. However, it does not affect the independent development and deployment of the subsystem. The routing part has some changes to the subsystem, but it does not affect the function.

advantages

  1. Fast loading, you can extract all the modules shared by the system to achieve on-demand loading, one load, and other reuse.
  2. Modify the style of the subsystem, without proxy server, because both belong to the same systemdocument.
  3. User experience is good, fast, content changes do not need to reload the entire page, avoiding unnecessary jumps and repeated rendering
  4. httpFewer requests, less server stress.

Single-spa versus Iframe

Compare the item single-spa iframe supplement
Loading speed Single-spa can extract vUE/VUex/VUE-Router files shared by all systems and load them only once, which can be reused by different systems. The loading speed is fast, but the file version must be uniform Iframe occupies the HTTP channel of the primary system, affecting the loading of the primary system and causing slow loading Both can improve loading speed through HTTP caching, but you can’t do CDN for general purpose files like VUE, because internal systems probably can’t access the Internet
compatibility Single-spa only works with vue, React, angular written systems, and some older jQ-written systems Iframe can be embedded in any page
Technical difficulties Single-spa requires a certain amount of technical reserve, and there are some learning costs The iframe threshold is low, requiring no additional study
limitations Single-spa can be embedded into any part Iframe can only be embedded in a page, but you can also write a widget as a page
Modification cost Single-spa had to rework the subsystem, but it wasn’t much and could be done in half an hour Iframe can not be modified on the original system, but must use the proxy server to insert scripts and CSS, increasing the proxy server also increases the instability of the system (the failure of either of the two servers will lead to the system unavailable), the server also needs cost. If the original system is modified, the workload is similar to that of single-SPA Iframe can only be used if the source file of the project is missing or if the source file cannot be modified

Supplement:

  1. forSEO.iframeIt can’t be solved, butsingle-spaThere is a solution (Google can support single page appsSEOBaidu doesSSR), but internal systems, SEO needs less.
  2. iframeIt’s a security risk. TwoiframePage references lead to infinite nestingbug, which causes the page to be stuck and can only be checked by the proxy serveriframePage content to handle
  3. Pages can be passed by some code that does not allow itself to beiframeEmbedded. In this case, you can only choose other solutions. Taobao, JD.com, Tencent and others have set the code as follows:
if(window.top ! = =window.self){ window.top.location = window.location; }Copy the code

Implementation and simple principle of IFrame and single-SPA

Iframe is simple, implemented in a single tag. Single-spa is strange, I will introduce it in detail.

Single – spa

Take vue as an example. The index. HTML file generated by vuE-cli4 contains the following contents (some irrelevant contents are simplified) :


      
<html lang=en>
<head>
  <meta charset=utf-8>
  <title>my-app</title>
  <link href=/js/about.6b1cbb89.js rel=prefetch>
  <link href=/css/app.c8c4d97c.css rel=preload as=style>
  <link href=/js/app.6a6f1dda.js rel=preload as=script>
  <link href=/js/chunk-vendors.164d8230.js rel=preload as=script>
  <link href=/css/app.c8c4d97c.css rel=stylesheet>
</head>
<body>
  <noscript>
    <strong>We're sorry but my-app doesn't work properly without JavaScript enabled. Please enable it to
      continue.</strong>
  </noscript>
  <div id=app></div>
  <script src=/js/chunk-vendors.164d8230.js> </script>
  <script src=/js/app.6a6f1dda.js> </script>
</body>
</html>
Copy the code

The most important part is:

<link href=/css/app.c8c4d97c.css rel=stylesheet>
<div id=app></div>
<script src=/js/chunk-vendors.164d8230.js> </script>
<script src=/js/app.6a6f1dda.js> </script> 
Copy the code

Can I get the index. HTML of the subsystem with the help of node server, then read the HTML, get these tags, and return them to the main system. The main system is directly inserted into the body, can I present the subsystem?

Node proxy code implementation, DOM manipulation using cheerio plug-in:

const http = require('http')
// Introduce the Cheerio module
const cheerio = require('cheerio')
const axios = require('axios')
const server = http.createServer(function (request, response) {
  // Request the subsystem server to get the index.html file
  axios.get('http://localhost/').then(res= > {
    response.writeHead(200, { 
      'Content-Type': 'application/xml' ,
      'Access-Control-Allow-Origin': The '*'
    })
    // Load the HTML string
    const $ = cheerio.load(res.data)
    $('link').each(function () {$(this).attr('href'.'http://localhost' + $(this).attr('href'The $()})'script').each(function () {$(this).attr('src'.'http://localhost' + $(this).attr('src'))})const resp = $('body').prepend($('link[rel=stylesheet]')).html();
    response.end(resp)
  }).catch(e= > {
    console.log(e)
  })
})
server.listen(8080)
Copy the code

Note that:

  1. The introduction of thisjs/cssFile paths are relative and need to be prefixed with subprojects.
  2. v-htmlInsert theDOMFragment, outer chainscriptIt does not take effect and needs to be manually inserted

The result is that the subsystem can be rendered in #app, but the paths of the HTML, img/video/audio files generated in #app are relative, so they will be requested to the main system, but these files are not in the main system, so they will be 404. The JS/CSS file corresponding to the route page loaded on demand is also a relative path, which may cause errors. This problem does not exist if the route is not loaded on demand

Conclusion: The link/script in index. HTML can be added manually, but img/video/audio in the dynamically generated HTML and JS/CSS corresponding to the route page loaded on demand cannot be solved by proxy server.

Solution:

  1. Js/CSS /img/video are relative paths. Can we pack them all into absolute paths through Webpack? This solves the problem of failed file requests.

  2. Can like CDN, a server hung up, will go to other servers to request corresponding files. Or file sharing between servers, a failed file request on the primary system is automatically found on the child server and returned.

  3. Can you copy all the files of the subsystem to the main project server manually (or with The help of Node)? Node listens for the update of the subsystem files, automatically copies them and merges them into the js/ CSS /img folder

After checking webpack and VUE-CLI3 official website:

By default, the Vue CLI assumes that your application is deployed at the root of a domain name, such as https://www.my-app.com/. If the application is deployed on a subpath https://www.my-app.com/my-app/ and you use a route in history mode, for urls: https://www.my-app.com/my-app/page1, vue cannot tell whether my-app is the real path and page1 is the route parameter. In this case, publicPath must be set to /my-app/ so that Vue can correctly request file resources and match routes.

You can set the publicPath of vue-cli3 to https://www.my-app.com/my-app/, and then the js/ CSS /img/video paths in the code will become absolute paths. The prefix is https://www.my-app.com/my-app/, which solves the URL path problem.

This allows for a simple single-SPA application, but the loaded Vue subsystem will not be unloaded when switching to the next system, and too many subsystems will cause stuttering and increase the possibility of CSS/JS contamination, making it impractical.

The last

If you have any questions or mistakes, please comment. Next article: Implementing a single-SPA front-end microservice from 0 (middle), including the complete packaging/development debugging process, how to retrofit old projects, etc.