While traditional modularization is conducive to development, there are many inconveniences, such as:
- When the component library used in the front-end multi-page project scenario is updated, all used pages need to be compiled and online, which increases the cost of going online, and there is a risk of missing pages or missing pages when they are rolled back;
- When using the CDN resource management component library, the CDN resource update can realize the browser-side update, but the server-side rendering scene node side loads the resources and executes it cannot be guaranteed to be consistent with the CDN resource version loaded in the browser-side rendering, which will bring rendering differences Cause re-rendering problems;
- When the packaging tool is used to extract public resources, the chunk extraction of the packaging tool is limited to the current build batch. If a project only builds part of the page at a time, it is impossible to extract all the public resources in the project. Different resource hash values will cause the efficiency of loading CDN resources on the client side to be greatly reduced when rendering.
Committed to solving the above problems, we developed the concept of web modules to solve the problems that plagued the business from the architectural level.
Vision
Based on known issues, our concerns are:
- The web module can be compiled and launched separately, and it can also be rolled back separately;
- After the web module goes online, all project pages that use the module take effect immediately;
- Supports isomorphic projects for server-side rendering.
In the actual business scenario, we hope to use web module extension to solve the cross-page resource sharing of the internal UI component library, tool library (lodash, moment), request library (axios), etc. of multi-page projects. You need to build and publish the web module extension separately. After publishing, we can achieve the effect of real-time update of shared resources on multiple pages through the capabilities we provide.
In addition, we hope that when the business party uses the extension of the web module, the grammar of quoting other resources is the same, using native import or require, and not introducing special grammar, so as to avoid increasing the learning cost of the business line.
Realization ideas
This solution is based on . You can go to 1618db5a009050 "Revealing the Big Front-end Architecture Ada of Recruitment" 1618db5a009054. The following will directly use Ada for description.
Ada uses the manifest service for parsing and rendering from development to construction. The build tool packaging will generate a manifest file, which contains information such as the url and packaging resources packaged this time.
Using the convention of the checklist, we implemented the micro-front-end landing solution Widget. This design also made some conventions for the checklist to implement dynamic loading at runtime.
First, we agreed on a new type of artifact called "web module extension", which needs to be written in a fixed folder during development before it will be recognized and compiled by the scaffolding.
Like normal entry files, the files written in the specified folder will be compiled into a separate bundle file, which is convenient for referencing. Choose the method of packaging into one bundle only, that is, there is only one file each for js and css.
At this point, we have got the web public module and wrote it into the manifest file. Take axios as an example as shown in the figure:
Next is the axios extraction in the project. Since it is a public web resource, the import needs to be slightly modified, namely:
import axios from 'axios' // 原引用
import axios from 'extensions/web-modules/axios' // 新引用
What needs to be done at this time is to change the path of'extensions/web-modules/axios' into a dynamically loaded code. Each packaging tool provides Externals. With this feature, you can customize the loading method of excluded construction resources.
Take webpack as an example, the simple implementation is as follows:
{
externals: [
({ request }, callback) => {
// ...
if (!matched) return callback() // 未match到web模块扩展路径直接返回
const url = path.posix.join(projectKey, WEB_MODULES_SCOPE, matched.name) // 真实URL路径
const name = target === 'node'
? `ada.webModules.require('${url}')` // 由Ada server内部实现此方法
: url
return callback(null, name, scope)
}
]
}
The static path reference is changed to dynamic acquisition, the browser side uses the window global variable method, and the node side uses the self-implemented require method.
As shown in the figure, the compiled web module URL corresponds to the resources in the web and node attributes in the list. The next step is to mount the resources to the service to achieve the closed loop.
On the browser side, we have implemented the template placeholder for the template. We mount the web-related resources to the ctx of the current request context. When using:
async function GET (ctx) {
const html = `
...
<script src="${ctx.template.placeholders.webModules.axios.js}"></script>
...
`
ctx.response.set(html, 200)
}
The server has a release module to provide a listener. When the web module extension is online, it will pull the latest list and update the resource file to the local cache, so that the next request will get the ctx.template.placeholders.webModules.axios .js is the newest resource after replacement.
In the same way, the ada.webModules.require method is a tool method that is exposed to the global on the node side. It performs resource loading proxy for the web extension module on the server side. When the resource is updated, the require cache will be cleared and the latest js bundle will be re-required. .
I will not introduce the mechanism of publishing, registration and discovery in depth here, because it is more inclined to the content distributed synchronously on the server side, which has nothing to do with the design ideas that I want to express at the center of this article.
At this point, the web module extension mechanism has been completed, achieving our vision at the beginning of the design.
Summarize
Modularity and dynamics bring convenience to development, but also increase the impact and risk of going online. After all, going online will affect all pages used, and there is also a certain threshold for developers' risk control capabilities.
The front-end team of Zhilian has released the web module extension for more than a year, and the internal response has been relatively positive, indicating that they are more willing to save time and cost and try new capabilities than conservative people.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。