Preface
Using Node to separate front and back end development model brings some performance and development process advantages, but also faces many challenges. Under Taobao's complex business and technical architecture, the backend must rely on Java to build the infrastructure and provide relevant business interfaces for the front-end to use. One of the most important tasks of Node in the entire environment is to proxy these business interfaces to facilitate the integration of data on the front-end (Node side and browser side) for page rendering. How to do a good job in agency work so that after the front and back end development can still be seamlessly connected in the process, is a problem we need to consider. This article will discuss this issue and propose solutions.
Since the backend provides a variety of interfaces, developers may also have a variety of ways to write Node-side code to access these interfaces. If we do not perform unified architecture processing in interface access methods and usage, it will bring about the following problems:
1. Each developer uses his own code style to write interface access code, causing confusion in the project directory and coding style, which makes it relatively difficult to maintain.
2. Every developer writes his own mock data method. After the development is completed, he needs to manually modify the code to remove the mock.
3. In order to realize the switching of different environments of the interface (daily, pre-issue, online), each developer may maintain some configuration files.
4. The data interface call method cannot be easily reused by various business models.
5. The description agreement for the data interface is scattered in every corner of the code, which may be inconsistent with the interface documents agreed by the backend personnel.
6. After the entire project is distributed, the cost of connecting interfaces or testing regression is still very high, and it needs to involve each interface provider and user.
So we hope to have such a framework that uses the mechanism provided by this framework to describe all external interfaces dependent on in engineering projects, manage them in a unified manner, and provide flexible interface modeling and calling methods, as well as convenient online environment and production environment switching methods to seamlessly combine front-end and back-end development. ModelProxy is a lightweight framework that meets such requirements. It is one of the core components of the Midway Framework and can also be used alone. Using ModelProxy can bring the following advantages:
1. Different developers have unified interface access code writing methods, clear meaning, and reduce maintenance difficulty.
2. The framework adopts factory + singleton mode to realize multiple multiplexing of interface configuration at one time. And developers can customize and assemble their own business models (dependency injection).
3. It can easily switch online, daily, and pre-issue environments.
4. Built-in mock engines such as river-mock and mockjs, providing mock data is very convenient.
5. Use interface configuration files to manage the interface dependency descriptions uniformly to avoid being scattered in various codes.
6. Supports model sharing on the browser side, which can be used to render front-end data. The entire proxy process is transparent to the browser.
7. The interface configuration file itself is a structured description document, and the document can be automatically generated using the river tool collection. It can also be used for related automation interface testing to form a closed loop in the entire development process.
ModelProxy working principle diagram and related development process diagram
In the above figure, the developer first needs to describe all the dependencies of the backend interface in the project and write it to the interface.json configuration file according to the specified json format. If necessary, a rule file needs to be written for each interface, that is, the interface rules part of the figure. This rule file is used to mock data during the development stage or to use the River tool set to verify the interface during the joint debugging stage. The content of the rule file depends on which mock engine is used (such as mockjs, river-mock, etc.). After the configuration is completed, you can create your own business model in the code according to your needs.
Here is a simple example:
【Example 1】
The first step is to create the interface configuration file interface.json in the project directory, and add the main search interface json definition.
The code copy is as follows:
{
"title": "pad Taobao project data interface collection definition",
"version": "1.0.0",
"engine": "mockjs",
"rulebase": "./interfaceRules/",
"status": "online",
"interfaces": [ {
"name": "Main search interface",
"id": "Search.getItems",
"urls": {
"online": "http://smtaobao.com/client/search.do"
}
} ]
}
Step 2 Create and use model in the code
The code copy is as follows:
//Introduce module
var ModelProxy = require( 'modelproxy' );
// Global initialization introduces interface configuration files (note: initialization work only once)
ModelProxy.init( './interface.json' );
// For more creation mode, please refer to the following article
var searchModel = new ModelProxy( {
searchItems: 'Search.getItems' // Custom method name: The interface ID defined in the configuration file
} );
// Use model, note: The parameters required for calling the method are the parameters required for the actual interface.
searchModel.searchItems( { q: 'iphone6' } )
// !Note that you must call the done method to specify the callback function to obtain the data obtained by calling searchItems asynchronously above!
.done( function( data ) {
console.log( data );
} )
.error( function( err ) {
console.log( err );
} );
The feature richness of ModelProxy is that it supports various forms of profiles to create business models that require business:
Create an object using interface ID > will take the word after the last '.' number of ID as the method name
The code copy is as follows:
ModelProxy.create( 'Search.getItem' );
Use key value JSON object > Custom method name: Interface ID
The code copy is as follows:
ModelProxy.create( {
getName: 'Session.getUserName',
getMyCarts: 'Cart.getCarts'
} );
Use array form > take the word after the last. number as the method name
The method call names generated in the following example are: Cart_getItem, getItem, suggest, getName
The code copy is as follows:
ModelProxy.create( [ 'Cart.getItem', 'Search.getItem', 'Search.suggest', 'Session.User.getName' ] );
Prefix form > All interface IDs that satisfy the prefix will be introduced into the object and the latter part is taken as the method name
The code copy is as follows:
ModelProxy.create( 'Search.*' );
At the same time, using these models, you can easily implement merge requests or dependency requests and render related templates
[Example 2] Merge request
The code copy is as follows:
var model = new ModelProxy( 'Search.*' );
// Merge request (the model method called below is specified when configuring the interface id except for done)
model.suggest( { q: 'female' } )
.list( { keyword: 'iphone6' } )
.getNav( { key: 'Popular Clothing' } )
.done( function( data1, data2, data3 ) {
// The order of parameters is consistent with the order of method calls
console.log( data1, data2, data3);
} );
[Example 3] Dependency request
The code copy is as follows:
var model = new ModelProxy( {
getUser: 'Session.getUser',
getMyOrderList: 'Order.getOrder'
} );
// Get the user id first, and then get the order list based on the id number
model.getUser( { sid: 'fdkaldjfgsakls0322yf8' } )
.done( function( data ) {
var uid = data.uid;
// Secondary data request depends on the first obtained id number
this.getMyOrderList( { id: uid } )
.done( function( data ) {
console.log( data );
} );
} );
In addition, ModelProxy can be used not only on the Node side, but also on the browser side. Just introduce the modelproxy-client.js provided by the official package into the page.
[Example 4] Using ModelProxy on the browser side
The code copy is as follows:
<!-- Introduced the modelproxy module, which itself is a standard module encapsulated by KISSY-->
<script src="modelproxy-client.js" ></script>
<script type="text/javascript">
KISSY.use( "modelproxy", function( S, ModelProxy) {
// !Configure the basic path, which is consistent with the intercept path configured in the second step!
// And there is a global configuration and only once!
ModelProxy.configBase( '/model/' );
// Create a model
var searchModel = ModelProxy.create( 'Search.*' );
searchModel
.list( { q: 'ihpone6' } )
.list( { q: 'shangchao' } )
.suggest( { q: 'i' } )
.getNav( { q: 'skateboard' } )
.done( function( data1, data2, data3, data4 ) {
console.log( {
"list_ihpone6": data1,
"list_shocksuit": data2,
"suggest_i": data3,
"getNav_skateboard": data4
} );
} );
} );
</script>
At the same time, ModelProxy can be used with Midway-XTPL, another core component of Midway, to realize full sharing of data, templates and related rendering processes on the browser and server side. For detailed tutorials and documentation on ModelProxy, please move to https://github.com/purejs/modelproxy
Summarize
ModelProxy exists as a configured lightweight framework, providing friendly interface model assembly and usage methods, and at the same time it solves the interface usage specification problem in the separation of front-end and back-end development modes. During the entire project development process, the interface always needs to be defined and described once, and the front-end developers can reference it. At the same time, the River tool is used to automatically generate documents, form a contract with the back-end developers, and conduct related automated tests, greatly optimizing the entire software engineering development process.
【Note】River is a general term for the front-end unified interface specifications and related tools developed by Alibaba Group and developed by Alibaba Group.