preface

Recently, I am reworking the company’s scaffold bucket. Although I have done some small scaffolders before, most of them are based on download-Git-Repo and can only be done with commander+ Inquirer operation. But the whole bucket task involved not only a set of CLI, but also the core basic components, such as the Request library. In fact, the development time of this library was far beyond my schedule. Here are some of the reconsiderations during the process of encapsulation.

I. Determine design principles

The design principle here is component features. A good request library usually has the following characteristics:

  • Cross platform: For example, supports browser, Node, and wechat applet
  • Simple: Indicates that the API is simple and configuration friendly. Zero configuration is preferred and out of the box
  • Promise: Based on promise, it facilitates asynchronous programming
  • Cancelable: A request that has been sent can be cancelled
  • Interceptor: This is an easy way to set up request and response interceptors
  • Instantial: Provides instantiation so that multiple instances can be configured independently and shared globally to facilitate scenarios where a project sends requests to multiple services
  • Alternative: It can support the replacement of request client. For example, the underlying replacement of XHR and FETCH is insensitive

So many of the above can refer to the actual situation of the project to choose, or develop the route, step by step

Second, the selection of

Request library selection

$. Ajax, Axios, or encapsulate XHR or FETCH yourself?

The benefits of Axios are obvious: promises and various configurations, interceptors, cancel tokens, etc. But there are also many disadvantages. Cancellations are abort based on cancelable promises rather than XHR. Unable to configure global interceptors to be shared by multiple instances; Cannot change the underlying to FETCH and so on.

The benefits of FETCH are also obvious. It can bring a lot of operation convenience based on Promise and stream, and can also be used in worker. However, compared with XHR, it lacks many configurations, such as timeout, which needs to be implemented by itself

In my opinion, a secondary encapsulation transition based on Axios is a better solution when time is limited, since it provides all the major requirements.

Technology selection for Lib development

Language, ES or TS? For better development and use experience, ts is often chosen.

Packaging: Webpack? A rollup? TSDX or something else or even just TSC? While both can be done, this technical decision affects subsequent packaging, release time, configuration complexity, costs for others to take over, etc., and also needs to be thought out in advance.

If you use TS development, personally feel TSDX is very convenient.

Iii. API design

Determine the final use of the core API

Using Swagger or other mock platforms, it is very convenient to generate interface code with parameters and return value types defined based on swagger.json or other API. Writing these generated scripts is not the goal of the library, but the library needs to provide a very concise API to support these scripts, such as this one

The decorator @http. post is responsible for sending the POST request, and OpsHttpRequest is responsible for defining the parameter types. The consumer does not care how the request is sent. Decorators can also accept multiple parameters to meet configuration requirements, such as

To meet more configuration requirements, you can design constructors, instance methods, and static apis

Determining the overall architecture

Based on the scheme above, it can be divided into three modules:

HttpDecorator: Responsible for the decorator logic

Adapter: Responsible for compatibility with different clients, such as XHR and FETCH, and even other third-party request clients

Request: The client that actually sends the request, encapsulating the use of XHR, FETCH, or AXIos as a request object

The httpDecorator overwrites the property descriptor, accepts parameters, and passes them to the Adapter. The Adapter finds the corresponding request client. Request Sends requests and processes responses

In addition to this, you can also design middleware modules that are responsible for logging, time monitoring, encryption, etc. If the requirements are not complex or variable, they can be implemented directly in the request

And when it comes to monitoring requests, it often leads to a lot of work

4. Determine the built-in processing

Default log output, id for all requests, download processing for content-disposition headers, and so on. It’s harder to decide what to do than what to do.

Fifth, determine dependence

What third-party libraries does the library depend on, what version does the library use, and is the PATCH version of these dependencies fixed? Answering these questions often requires a close look at the versions of Changelog ~ for these dependencies

Vi. Determine the test plan

As a core library, automated tests must have, test scenarios must be comprehensive, often need to write a simple server test various scenarios: 404,500,200, error handling and so on

Seven, documentation,

It wasn’t the development problem that held us back, it was the documentation

Readme and Changelog are certainly a part of it, as are the design architecture, implementation principles, and often future iteration plans. More often, you need to provide a small demo for user reference