Preface
In recent years, web-based multi-terminal adaptation of various sites has been in full swing, and solutions relying on various technologies have also been developed among the industries. Such as the responsive design based on browser native CSS3 Media Query, the "cloud adaptation" solution based on cloud intelligent re-arrangement, etc. This article mainly discusses multi-terminal adaptation solutions based on the separation of front and back ends.
About front-end separation
Regarding the solution of front-end separation, there is a very clear explanation in "Thinking and Practice of Front-end Separation Based on NodeJS (I)". We introduced NodeJS as the rendering layer between the server interface and the browser. Because the NodeJS layer is completely separated from the data and does not need to care about a lot of business logic, it is very suitable for multi-terminal adaptation work at this layer.
UA Detection
The first thing to solve in multi-terminal adaptation is the UA detection problem. For a request over, we need to know the type of this device to output the corresponding content to it. There are now very mature User Agent feature library and detection tools compatible with a large number of devices on the market. Here is a list compiled by Mozilla. Among them, there are both those running on the browser side and those running on the server side code layer. Some tools even provide Nginx/Apache modules, which are responsible for parsing the UA information for each request.
Actually we recommend the last one. The solution based on front-end separation determines that UA probe can only run on the server side, but it is not a sufficiently friendly solution if the probe code and feature library are coupled in the business code. We move this behavior forward and hang it on Nginx/Apache. They are responsible for parsing the UA information for each request and then passing it to the business code through HTTP Header.
There are several benefits to doing this:
Our code no longer needs to pay attention to how UA parses, just take out the parsed information from the upper layer. If there are multiple applications on the same server, the UA information parsed by the same Nginx can be used together, saving the resolution loss between different applications.
UA detection solution based on Nginx shared by Tmall
Taobao's Tengine Web server also provides a similar module ngx_http_user_agent_module.
It is worth mentioning that when choosing UA detection tools, the maintainability of the feature library must be considered. Because there are more and more new equipment types on the market, each device will have an independent User Agent, so the feature library must provide good update and maintenance strategies to adapt to changing equipment.
Several adaptations built into MVC mode
After obtaining the UA information, we need to consider if the terminal adaptation is performed based on the specified UA. Even in the NodeJS layer, although most of the business logic is missing, we still divide the internals into three models: Model/Controller/View.
Let’s first use the above diagram to analyze some existing multi-terminal adaptation solutions.
Adaptations built on Controller
This solution should be the simplest and most rude way to deal with it. Pass the same URL to the same control layer through the router. The control layer then distributes data and model logic to the corresponding display (View) through UA information for rendering, and the rendering layer provides templates that adapt to several terminals according to pre-conventions.
The advantage of this solution is that it maintains the unity of data and control layers, and business logic can be applied to all terminals only once. However, this scenario is only suitable for low-interactive applications such as display pages. Once the business is more complex, the controllers of each terminal may have their own processing logic. If they still share a controller, it will make the controller very bloated and difficult to maintain, which is undoubtedly a wrong choice.
Adaptations built on Router
In order to solve the above problems, we can distinguish devices on the Router and distribute them to different controllers for different terminals:
This is also one of the most common solutions, mostly manifested in using a separate set of applications for different terminals. For example, when the PC Taobao homepage and the WAP version of Taobao homepage, when different devices visit www.taobao.com, the server will redirect to the WAP version of Taobao homepage or the PC version of Taobao homepage through Router control. They are two completely independent sets of applications.
However, this solution undoubtedly brings about the problem that data and part of the logic cannot be shared. Various terminals cannot share the same data and business logic, resulting in a lot of repetitive work and is inefficient.
In order to alleviate this problem, someone proposed an optimized solution: in the same set of applications, each data source is still abstracted into each model, and provided to the controllers of different terminals for combination:
This solution solves the problem that the previous data cannot be shared. On the Controller, each terminal is still independent of each other, but can use the same batch of data sources together. At least there is no need to develop independent interfaces for terminal types in the data.
In the above two Router-based solutions, due to the independence of Controller, each terminal can implement different interactive logic for its own pages, ensuring sufficient flexibility for each terminal itself, which is also the main reason why most applications adopt this solution.
Adaptations built on the View layer
This is the solution used for Taobao ordering pages, but the difference is that the ordering page places the overall rendering layer on the browser side, rather than the NodeJS layer. However, whether it is a browser or NodeJS, the overall design idea is still the same:
In this solution, Router, Controller and Model do not need to pay attention to device information, and the judgment of terminal type is completely left to the display layer for processing. The main module in the figure is "View Factory". After the Model and Controller pass the data and rendering logic, they use the View Factory to grab specific components from a bunch of preset components based on device information and other states (not just UA information, but also network environment, user area, etc.) and then combine them into the final page.
This solution has several advantages:
The upper layer does not need to pay attention to device information (UA). The videos of multiple terminals are still handled by the View layer that ultimately shows the greatest relationship. It is not just multi-terminal adaptation, but in addition to UA information, each View Component can also determine which template it outputs according to the user's status, such as hiding pictures by default at low network speeds and outputting activity banners in designated areas. Different templates of each View Component can decide whether to use the same data and business logic at your own discretion, providing a very flexible implementation method.
But it is obvious that this solution is also the most complex, especially when considering some interactive application scenarios, Router and Controller may not be able to remain so pure. Especially for some businesses with relatively strong integrity, which cannot be split into components themselves, this solution may not be applicable; and for some simple businesses, using this architecture may not be the best choice.
Summarize
The above solutions are each reflected in one or more parts of the MVC model. If one solution does not meet the needs in business, multiple solutions can be adopted at the same time. Or it can be understood that the complexity and interactive attributes in the business determine which multi-terminal adaptation solution the product is more suitable for.
Compared with the browser-based responsive design scheme, because most terminal detection and rendering logic is migrated to the server, adapting at the NodeJS layer undoubtedly brings better performance and user experience; in addition, compared with the conversion quality problems caused by some so-called "cloud adaptation" schemes, they will not exist in the "customized" scheme based on front-end separation. The adaptation solution for the separation of front and back ends has natural advantages in these aspects.
Finally, in order to adapt to more flexible and powerful adaptation needs, adaptation solutions based on front-end separation will face more challenges!