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:
- Redirect multiple applications using HTTP server routing (link hops)
- Design communication and loading mechanisms on top of different frameworks such as Mooa and single-SPA
- Build a single application by combining multiple independent applications and components
- The iFrame. Use iFrame and custom messaging mechanisms
- Build applications using pure Web Components
- 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
-
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)
-
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.
-
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:
iframe
Content 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.
-
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.
-
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
-
The communication between systems with different sources needs to be through postMessage, which has a certain degree of security
advantages
- We’re in complete isolation.
css
andjs
, avoiding styles and styles between systemsjs
pollution - The subsystem can be embedded without modification at all
Advantages and disadvantages of single-SPA
disadvantages
css
andjs
There needs to be norms and isolation. Otherwise it is easy to cause global pollution, especiallyvue
Global component, global hook.- 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
- Fast loading, you can extract all the modules shared by the system to achieve on-demand loading, one load, and other reuse.
- Modify the style of the subsystem, without proxy server, because both belong to the same system
document
. - User experience is good, fast, content changes do not need to reload the entire page, avoiding unnecessary jumps and repeated rendering
http
Fewer 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:
- for
SEO
.iframe
It can’t be solved, butsingle-spa
There is a solution (Google can support single page appsSEO
Baidu doesSSR
), but internal systems, SEO needs less. iframe
It’s a security risk. Twoiframe
Page references lead to infinite nestingbug
, which causes the page to be stuck and can only be checked by the proxy serveriframe
Page content to handle- Pages can be passed by some code that does not allow itself to be
iframe
Embedded. 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:
- The introduction of this
js/css
File paths are relative and need to be prefixed with subprojects. v-html
Insert theDOM
Fragment, outer chainscript
It 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:
-
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.
-
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.
-
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.