Time flies, and 2019 is fleeting. This year was bumpy and full for the students in the front end of PLUS member program. As Bai Yansong said, they were both happy and painful. Looking back, with the continuous access of the cooperation rights and interests of different industries, the demand of the 6.18 big promotion and Double 11 activities, and the trouble of the white page of the first screen of some models, we gradually stabilized after a period of confusion. While fulfilling the daily requirements, based on the original framework, the stability, loading, experience, development efficiency and other aspects of the project have been strengthened.

In 2019, nearly 90 size requirements were supported. It is mainly divided into four categories: product upgrading, inter-industry cooperation, promotional activities and urgent needs. Among these demands is the demand for new user rights of classic cards, such as health, reading, express coupons, and 95 percent discount commodity rights. It has also greatly expanded its alliances with other different industries, such as Tencent Video, Ctrip travel, and Kool Music. In addition, performance optimization and user experience optimization initiated by the R&D side are also included.

PLUS member program spans three workplaces, r&d and project side in Beijing (2 workplaces), product team in Shanghai. Communication is particularly important, any small problem, may be magnified in the user, each operation online need to be careful, walking on thin ice.

The project functions are complex, the state is cumbersome, and the business logic often contains mystery. A change may affect dozens of states, affecting the whole body. The interactive logic of a popover can’t fit on a whole page, so change one place and collapse the whole thing. In addition, there are often dozens of concurrent requirements, merging features several times a week, and the dreaded curse of frequent all-nighters

However, breaking the cocoon into a butterfly, nirvana rebirth, which is not the need for extreme pain after the sublimation. After experiencing crazy growth, PLUS membership program is like a rampaging child, we are determined to reorganize, change the status quo, let him grow up healthily. This paper will elaborate from three aspects of performance optimization, development efficiency and process optimization, as shown in the figure:

What is PLUS membership

First of all, please allow me to briefly introduce PLUS. In order to provide better shopping experience for core customers, JD has specially launched JD PLUS membership, which includes more than ten rights and interests:

  • 10 times of shopping return: PLUS members can return up to 220 yuan worth of jingdou per year, a year to buy a few large electrical appliances membership fees back.
  • Self-support free shipping: you can get 5 shipping coupons per month and 60 shipping coupons per year. In addition, there are annual 36 yuan express coupons.
  • Member price products: You can enjoy 5 million member prices of jingdong Mall products, and buy products at lower prices.
  • Door-to-door return and exchange: members enjoy self-operated commodity after-sales service (return, exchange, maintenance) free freight and free door-to-door “double free” service.
  • Massive life privileges: eat dessert buy one get one free, watch a movie 50% off, sing KTV 2 hours free, eat a hot pot also give you a plate of mutton roll for free, there are a lot of privileges, all! Series! No! Want to! Money!
  • .

I’m not going to tell you more, but I’m going to put more here

In addition, if you buy jd PLUS co-branded membership card, you will have more than two members’ rights. SHH ~ low-key, after all, everyone is a member ~ ~

Child: Mom, I want to buy a MEMBER of JD PLUS ~ Mom: Yes, I want to buy a co-branded card. One card is worth two. Is that enough? Child: That’s enough. Thanks, Mom. Mom is so nice!

Let’s take a look at the page of PLUS members:

OK, that’s it. Let’s move on.

The front-end architecture

PLUS member projects have been choosing the Vue technology stack since 18 years ago, using the team’s own Gaea building tool and NutUI component library, as well as introducing Carefree, SMock, Vuex, TS, PWA, etc.

Gaea build tool is a set of Vue technology stack build tools independently developed by our team. It is a complete solution of Vue technology stack based on Node.js and Webpack template engineering, including a complete workflow of development, debugging and packaging online. The work efficiency was greatly improved, and the scaffolding is now used by all Vue businesses in the team.

NutUI component library is a set of jd.com style lightweight Vue component library for mobile terminals, which has been polished by our team for several years. Currently, it is used by 30+ JD mobile terminal projects and has got 1.5K + star on Github. The Vue component library provides a large number of reusable Vue base components, which greatly facilitates the development of the PLUS project.

Carefree, a one-stop-stop solution for mobile Web reality testing that does not rely on wifi hotspots, is a pain point that our team found in daily development that the reality machine relies on computer hotspots to debug. Let mobile Web real machine test free and independent research and development of a set of solutions.

SMock is independently developed by the team. Aiming at the problem that there is no data in the early stage of the project, SMock analyzes the documents that need to be mock, outputs the corresponding mock data, and starts node services for debugging in the front-end development to improve the efficiency of front-end development and support cross-domain access.

In addition, we introduced Vuex for state management, PWA for data caching and offline applications, and tried to develop in TypeScript.

Performance optimization

Improving page rendering performance and improving user experience has been the focus of the team. The home page has used a number of methods to optimize performance, including using skeleton screens to reduce user waiting experience, core data directly out to reduce request interface time, lazy scrolling inside floors, using Webp to reduce image size, and so on. So at first we stood as if on the shoulders of giants, motionless, lest we should accidentally slip and fall

Improve page rendering performance

The reason for this was that half a year ago, the problem of page stuck and white screen would come up from time to time, haunting us like a ghost. And is a random accident, tens of millions of users there will always be a few mobile phones selected by the god of luck ———— let it appear white screen, card dead, gas with the mobile phone hit the wall! But the same phone, the same configuration, the same APP version, is always safe on our side. In the meantime, we tried a lot of things, like

Sleep, drink tea, talk

Funny. How is that possible? We return to the user to consult the reappearance steps, combined with WebView research and development to investigate the cause, according to the user PIN query crash information, investigation buried point report, and so on, but the problem occasionally has little effect, and only through a white screen picture, it is difficult to locate the problem where? Even if you modify code suspected to have an impact, you can’t verify that it’s fixed.

So the tea does not want to think rice, puzzled. Could this be schrodinger’s cat of quantum mechanics? Is the end result of the change of things based on human observation? Is it possible to win the next Nobel Prize in physics after solving the problem? It’s a little exciting to think about…

Stage 1: Initial problem solving

Fortunately, god pays off, in the switch of a variety of network speed, simulation of various environments under the attempt, found that in the case of page stuck, often reported an error, is the dependent variable is not defined.

We know that projects based on The Webpack scaffolding and Vue framework will be packaged to generate a dependency JS file and a business JS file. To make it easier to go online, links to static resources were generated dynamically. Browsers often download multiple external static resources in parallel. If the business JS file is executed before the dependent JS file, the dependent variable cannot be found, and the result is only one: the page is stuck!

Since dynamic generation of static resource links can cause uncertainty in JS execution order, we have changed back to the form of automatic injection of static resource links in Webpack. But is this really the end of the matter?

Stage two: New questions

Sure enough, after the white screen like a ghost, still occasionally appear! Although fewer than before, but still sporadic from time to time a few cases. And as time went on, there were more and more requirements, many of them developed in parallel at a time. In order not to conflict the parallel development code and to avoid the client caching the old file each time it goes online, the file with the new version number is used each time it goes online. However, even if you change a little bit of code, both the front end and the back end have to go online together. In the case of rapid iteration requirements, each change requires back-end r&d to modify the version number of more than a dozen static resources, which makes the front and back end r&d unbearable. Therefore, we decided to use the company’s head and tail system, and put the static resource path in the head and tail system. Every time after launching a new file, the front end pushes the head and tail, and deploys static resources to each server with one key. However, this is not always the case. Because you maintain multiple pages, there are two static files for each page: a JS file and a CSS file, which are placed at the end of and . Lead to each change of the first and last files are involved in the revision of more than a dozen files (ah, good miss that year back end students help to modify the version number of the day ~), maintenance costs skyrocketed, and with the increase of the page, this phenomenon is increasing;

In addition, skeleton screens have been added to the returned HTML to ease the user’s anxiety while waiting for the page to be rendered. Unfortunately, we found that in IOS, the skeleton screen doesn’t appear, but instead presents the final rendered page.

In order to solve the above problems, instead of escaping like ostriches burying their heads in the sand when faced with dangers, we decided to take the initiative to optimize and conquer this hard bone!

The third stage: at the end of one’s tether there is no way out

In a normal browser rendering mechanism, after the client requests back the HTML from the server, the HTML parser traverses the nodes one by one from the header to the tail of the HTML file. When these nodes are normal, the HTML parser adds them to the DOM tree. When these nodes are JS code, the HTML parser gives control to the JS parser. If these nodes are CSS code, the HTML parser gives control to the CSS parser. However, when the external JS and CSS code has not been transferred from the server to the browser, the browser will usually choose to pre-render some content to the screen if there are visual elements in the DOM tree. The problem is that the WebView in IOS doesn’t show the HTML that comes out straight from the first screen. The HTML DOM structure will wait for external CSS and JS to load before rendering.

To test this hypothesis, we can simplify the HTML code to a minimum of code: just put a red div inside the mount element and a green div outside it.

<! DOCTYPE html> <html lang="zh-cmn-Hans">
    <head>
        <meta content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover" name="viewport"> <title>PLUS member </title> <link rel="stylesheet" type="text/css" href="/ / static.360buyimg.com/exploit/mplus/4.3.2/v4/css/index.css"> < script > document. The documentElement. Style. + fontSize = 320/7.5"px"</script>
    </head>
    <body>
    <div id="app">
        <div style="width:100%; height: 200px; background:red;"></div>
    </div>
    <div style="width: 100%; height: 200px; background:green;"></div>
    <script type="text/javascript" src="/ / static.360buyimg.com/exploit/mplus/lib/4.1/vendor.dll.js"></script>
    <script type="text/javascript" src="/ / static.360buyimg.com/exploit/mplus/4.3.2/v4/js/index.js"></script>
    </body>
</html>Copy the code

And in IOS, it looks like this:

As you can see, since the red div is inside the mount element, it is directly replaced by the generated Vue page; The green div is rendered together with the Vue page and is displayed later because the complete page requires many interface judgments to be called. However, neither div will be displayed before Vue’s initial page rendering.

The skeleton screen on IOS is in the same situation. If you put it inside a mounted element, it doesn’t show at all. If it is placed outside the mount element, it will appear at the same time as the Vue rendered page, thus losing the meaning of the skeleton screen.

In order to avoid using external downloads of CSS and JS, which may cause IOS system to affect the rendering of the skeleton screen on the first screen, we still need to dynamically introduce JS and CSS after the skeleton screen is loaded. Since the skeleton screen on the home page has a small amount of code itself, static resources can be dynamically introduced after it is loaded. Time has little effect (experimental data below). But back in the first phase, dynamic generation of static resources caused JS execution order problems.

So, around a circle, no solution, the end of the play ~

Wait, are you kidding? This is easy! After many attempts, we adopted the method of introducing event listener, the core idea is to wait until all the dependent files are loaded before executing the business code. The benefits:

  1. To ensure the static resources of parallel download, does not affect the original download mode;
  2. Ensure the order of code execution;

In this process, note:

  1. Do not write ES6 syntax code in HTML to avoid incompatibilities with earlier versions of browsers because they are not compiled with Babel.
  2. Generate multiple JS tags, first mount them to the virtual node object and then mount them to the body in a unified way to reduce page redrawing;
    var oFragment = document.createDocumentFragment();
    var indexScript1 = document.createElement('script');
    var indexScript2= document.createElement('script');
    oFragment.appendChild(indexScript1);
    oFragment.appendChild(indexScript2);
    body.appendChild(oFragment);Copy the code
  1. Compatible with local development, local development still uses Webpack to automatically introduce static resources in the form of packaging and online reuse dynamically generated static resources:
<script type="text/javascript">
    var staticVersion = 'dev';
</script>
<script type="text/javascript"Parameter Description Value staticVersion var staticVersion ='1.0.0';
</script>
<script type="text/javascript">
    window.onload = function() {if(staticVersion ! ='dev'){// generate code dynamically}} </script>Copy the code

Through experiments, under normal network conditions, although the page rendering in IOS system is 266ms slower on average, the skeleton screen no longer waits for the loading of CSS and JS, but appears about 1000ms in advance. In the weak web case, the page rendering time is about the same, and the skeleton screen can still be rendered quickly after the HTML returns.

The following problems are solved:

  1. Optimize the execution sequence of static resources to avoid the problem of white screen stuck because the business code is earlier than the execution of dependent files;
  2. On both IOS and Android, the skeleton screen is displayed immediately after the HTML is returned;
  3. Reduced skeleton screen rendering time without waiting for external static resources to download;
  4. As shown in the figure below, due to dynamic generation of static resource path, each page in the past to introduce two header and tail files (including JS and CSS path files), after optimization only need to maintain 3 header and tail files, after the version further migration, the whole project only need to maintain 1 header and tail files!

Optimize floor lazy loading

Page floor lazy loading, can be very effective to improve the home page loading speed, reduce unnecessary requests. In the PLUS membership homepage, the long floor at the bottom is a good fit for lazy loading, and users don’t see the floor when they come in. In previous projects, only one page of data was requested for each sliding merchandise floor, reducing unnecessary requests and rendering. However, the space needs to be optimized. If the first screen of the user’s phone does not show the commodity floor, we do not need to load the JS code for this part as soon as they come in. Look at the size of this file, after the compression of JS file 11.7k, CSS size 16.8k, add up to a total of 28.3k, so it seems to be not small.

In order to further reduce unnecessary loading of the home page, we use the vue-Lazyload plug-in to realize the lazy loading function of components, and use the pre-loading technology, so that the browser idle time to download the file down, to avoid the user sliding to the commercial building to download the corresponding static resources.

The @babel/ plugin-syntag-dynamic-import and Vue-Lazyload plugins based on WebPack make it easy to pack asynchronously loaded code independently.

Pay special attention to the area above the commodity floor in the page. If there is no fixed height of the floor, be sure to ensure that the rendering is complete, and then to trigger the calculation of whether the commodity floor is in the visible area. Finally, after the lazy loading component is exposed, load the merchandise floor again. Disable Cache in the Network panel. The effect is as follows:

As you can see, the page merchandise floor is loaded to the floors-feed.js file, and it has already been preloaded, so it is fetched from the cache, and the time is 2ms.

As shown in the figure above, with a small screen phone, the entry page does not load floors-feed.js, but only from the Prefetch when the page slides down. Finally, considering the user experience and performance, the product floor under the big-screen phone will appear under the first screen, and it makes little sense to set the lazy loading function at this time, because the user will reveal the product floor with a little swipe of the screen, and it will take time to render the product floor. Under some small screen phones, the commodity floor is far away from the first screen, and the lazy loading of the commodity floor is very important.

The introduction of PWA

PWA stands for Progressive Web App, which is a Progressive Web application. Is a more popular technology in the past two years, often used to achieve offline caching function, users can quickly access the page has been visited, PLUS members for the first time to use the technology, the specific code does not say, online examples a search a sack, here a chat less mentioned pit.

  1. Try to put sw.js in the same directory as the page HTML, otherwise registering serviceWorker is invalid; At first, the template code was sent to SRC /template/index.html. I put sw.js in the root directory, which is the same path as SRC.

  2. The configuration file has been changed again and again, the cache has been deleted again and again, and the Disable cache in the Network has been desselected. Finally, the environment configuration problem has been found! As shown in the figure below:

Open the browser console, select the Application TAB, and select the Service Workers TAB on the left. Be sure to pay attention to these three options:

  1. Offline: The network is shut down after selected, and the Offline state can be simulated.
  2. Update on reload: reload the sw.js file every time the page is refreshed.
  3. Bypass for netWork: After this parameter is selected, the request only goes through the netWork and does not load from the cache.

My initial Bypass for netWork is selected by default, so the page requests will always go through the netWork requests.

It should be noted that this time we only added PWA as an attempt to update the abnormal status page with few iterations. Other states will go online at least twice a week, and dozens of requirements will be paralleled at the same time. Each page corresponds to a sw.js file. I feel the back end of children’s shoes to carry five meters long knife to find me to play ~ ~ ~

Introducing the TypeScript

TypeScript is a superset of JavaScript that provides the type system and support for ES6. It allows developers to detect most errors at compile time, increasing the readability and maintainability of code. However, in the face of the PLUS membership project with tens of millions of users, we have been slow to start. Considering the wide scope of the PLUS membership project, the complex business logic and the continuous addition of new business demands, small changes may produce serious and unexpected consequences.

In the spirit of careful proof before expanding the idea. We’re trying to introduce TypeScript into the new page requirements, running a little experiment with Vue + Webpack + Vuex + TypeScript on the new page. For the sake of security and without making any changes to the original project code, we took a very careful approach to the infamous Vue + typescript pit:

With the steps above, you can build TypeScript on top of your original JavaScript project, and then develop with TypeScript syntax. The development process is no different from the Vue project development, but there are a few problems that we encountered during the development.

1, the background image path problem

If you have a project that includes images like this:

.weixin {
  background: url(".. /img/weixin-pay.png") no-repeat center; Background - size: 0.46 rem 0.41 rem; }Copy the code

And in the TS file is the CSS file imported by import

<style lang="scss">@import '.. /asset/css/pay-method.scss'; </style>Copy the code

In this case, the background image may not be accessed when the service is started. This problem is preliminarly judged to be the problem of path resolution error. After trying to write the style directly to the page, or write it to common. CSS, or use @ to introduce the path, it was impossible to solve the problem by introducing the CSS file in the entry file.

2. Import components

Introducing components in an old project we might look like this:

import Dialog from "@/component/dialog/index.js";
Dialog.install(Vue);Copy the code

But if we quote TS, we need to rewrite it like this or we’ll get an error:

import Dialog from '@/component/dialog/index.js';
(Dialog as any).install(Vue);
Copy the code

3, the use of this

In TS we want to use this to introduce a global component, but the context it points to is not global, so to use a global component we need to define this:

(this as any).$toast.text('Processing, please try again later ~');
Copy the code

Declaration of global variables

After TS is introduced, if you want to use global variables such as window in a project, you need to declare them at the beginning of the code

declare var wx;
declare var MPing;
declare var window;Copy the code

The above is the problem encountered in the development project, and our current treatment method, may not be the best solution, welcome to leave a message to discuss and learn ~ ~

Optimize performance from CodeReview

As iteration requirements increase, code becomes more redundant and verbose, and maintainability deteriorates over time. In addition, developers write code level, style is different, there may be hidden dangers, this, in general before the project online, it is best to carry out CodeReview, easy to modify after the discovery of problems, taking advantage of the arranged test resources check is correct after the online…

However, for the PLUS team members, it is not easy to achieve the requirements on time due to the overwhelming demand pressure and the deadlocked launch date of each demand. Therefore, CodeReview can only be carried out after the project goes online, which leads to the awkward situation of no project schedule and no testing resources after modification. But in order to push the issues found in CodeReview to go live, we did the following after each CodeReview:

  1. Comb the problems found after CodeReview, analyze which problems need to be modified and optimized;
  2. Organize the problems that each change point might cause;
  3. Send email to project manager, product manager, test, etc.
  4. After the schedule is determined, the research and development modification will be arranged to avoid the modification in advance, because the daily demand development in the middle may lead to the hidden trouble caused by the later code merging;
  5. After testing and checking, go online again;

At this point, we from code to enhance robustness, optimizing the user experience and improve the page rendering performance, optimize the code structure, improve the efficiency of developers from several aspects, this paper emphatically cleared some optimization problems, and carries on the carding of these problems, apply for project scheduling and valuable test resources, promote optimization needs online.

Development efficiency

How to improve development efficiency? While improving performance and user experience, this is the direction we are thinking hard about. Sharpening does not mistakenly cut wood, only to solve the development process of research and development personnel pain points, in order to let the research and development personnel more quickly into the development of business.

Automatic file import

For the Vue framework development project, the idea of componentization has been deeply rooted in people’s hearts. However, with the deepening of the project complexity, we found that every time a new component was created, the file path should be introduced on the home page and the component should be added in components:

If you have more than a dozen components, you need to import more than a dozen components. Similarly, if you have a single page application, you need to import a large number of routes every time you add a route. Faced with this situation, in order to improve the work efficiency of developers and reduce the process of developing components, we use the method of automatic import of components in the folder to avoid the page to introduce too much import and mechanical monotonous introduction steps;

  1. First, classify all the files to be imported into folders and create a new export file, myindex.js
const files = require.context('/'.false, /\.vue$/); // Import all vue files in the current pathlet configRouters = {};
const modules = {};
files.keys().forEach(key => {
    const handleKey = key.replace('.vue'.' ').replace('/'.' '); // extract the vue file name const newName = handlekey.split (The '-'); // Change floor-coupon. Vue to ['floor'.'name'.'defal']
    let newString = ' ';
    newName.forEach((item, index) => {
        let newStr = ' ';
        if( index ! == 0) { newStr = item.substring(0, 1).first.toLocaleUpperCase() + item.substring(1); }else{ newStr = item; } newString += newStr; }) configRouters[newString] = files(key).default; // Connect the files file to the configuration file configRouters.exportdefault configRouters; // Export the configuration fileCopy the code
  1. In the business code index.vue file, import the above entry file:
import configRouters from '@/component/myIndex.js';
exportDefault {components: configRouters, // Assign the component configuration file to components for these routers. }Copy the code

In this way, each new component can be directly created in the folder, to achieve the automatic introduction of components. The advantages of the above optimization are:

  1. Reduce the number of components introduced into business code;
  2. Optimize the process of adding a component by automatically importing the component by developing the component code in the relevant folder.

Enabling local Services

He that would do a good job must sharpen his tools. An efficient development process is the pursuit of every r & D person. For easy and fast development, it is common to start the project locally using Webpack-dev-server. However, once entering the subsequent iteration, due to the cross-domain interface and the limitation of login information, the page cannot be opened locally for development. Append (” whistle dder “); append (” fildder “);

plus.m.jd.com/index               https://localhost:8080/index.html
plus.m.jd.com/js/                 https://localhost:8080/js/
plus.m.jd.com/css/                https://localhost:8080/css/
plus.m.jd.com/img/                https://localhost:8080/img/
plus.m.jd.com/vendordev.dll.js    https://localhost:8080/vendordev.dll.jsCopy the code

Because each page corresponds to a set of configuration agent files, multiple pages have different configuration agent files. Switching configuration agents and operations is a tedious configuration process. To solve this problem, how can I invoke the interface from a locally enabled environment? You need to solve the request cross-domain and landing information two obstacles.

  1. How to solve cross-domain problems?

At present, the common method to solve cross-domain is to use Webpack-dev-server and proxy interface proxy or use Nginx to configure cross-domain proxy. Since webpack-dev-server is configured locally, all project members can use it once and for all. We use the interface proxy to configure webpack-dev-server proxy, and configure webpack-dev-server in webpack.config.js file as follows:

proxy: [
    {
        context: ['/user'.'/apis'], // Use the context attribute to put multiple proxies under the same target:'https://rsp.jd.com/'// proxy interfaces starting with user and apis to https://rsp.jd.com/ domain secure:false// Back end servers that run over HTTPS and use invalid certificates are not supported by defaulttrueTo support changeOrigin:true// If the interface is cross-domain, this parameter needs to be configured. PathRewrite: {'^/apis': ' '},// Remove the apis headers because the path at the beginning of the apis is added manually to make it easy to distinguish which interfaces to proxy.'https://plus.m.jd.com'// The request interface limits the source, so change the request source host:'rsp.jd.com'// Set the host referer for the request header:'https://plus.m.jd.com/index'// Set the referer of the request header, because the backend interface will be limited}}]Copy the code

After the above configuration, the interface is requested and all the interface prefixes in the project are set to start with user and apis. If the prefixes are newly added for local development, you need to change the interface prefixes according to the development environment and delete the prefixes from the online environment.

If there is an error in the status code, you need to ask the backend if there is any restriction.

  1. How to solve the interface to pass login information?

The cross-domain problem is solved, and the interface can be accessed, because the request interface also needs to carry cookie information to determine whether the user is logged in. We know that after a user logs in, the browser will save the id value corresponding to the current user information in the cookie, and then each request will carry the cookie under the domain name to determine the login status of the user. However, the locally developed project cannot carry the cookies under the PLUS domain name, so the local access interface will return that the user is not logged in, so the relevant data cannot be obtained.

The browser said: all do not give the login cookie to want to data behavior is playing rogue! Well, this kind of behavior is understandable, after all, can not be empty handed for nothing, we have to curve to save the country. In order to prevent XSS attacks, the server sets the httpOnly attribute for the ID value of the user information in the cookie, avoiding the use of JS to obtain. However, as a result, we have no way to use JS to obtain the cookie of user information, so we have to visit the online Plus page in the browser first. Then look up the id of the user information on the dev-tool panel and place that value in the local cookie. This starts the local webpack-dev-server service and carries the cookie with it in subsequent requests:

Through the above two core steps, developers can achieve a local one-key command can start the project, which provides great convenience for developers. If you want to simulate users in different states, you only need to replace the corresponding cookie variable in JS.

Automatic formatting code

Diversity makes the world so wonderful, but when it comes to code formats, it’s a disaster! In team development, I believe most of you will encounter the following embarrassing scenarios:

  1. Different code styles can only be modified when the Lint tool detects a problem. Usually, such errors are semicolons, TAB indentation, Spaces, quotes, etc.
  2. When you need to do secondary development on the basis of another colleague’s branch, you find that his code style is different from your own, so you are not used to reading and developing.

In order to avoid this situation, we use the most popular automatic formatting tool Prettier, which can automatically help you complete the code formatting according to the configured specifications, which not only saves time and effort, but also improves your code reading, is a team collaboration development Gospel!

The advantages of the Prettier

  • It can be used in the editor or on the command line and is very simple to configure.
  • It can not only format the current file when saving the code, but also format all files with one key;
  • It supports HTML/JS/JSX/TS/JSON/CSS/SCSS/LESS mainstream/VUE file format;

The procedure for installing Prettier is as follows:

This will automatically format the file when you save it every time you change the code. If you want to format all files in your project with one click, you can also use the command line. Here, it is recommended to configure the scripts command in package.json:

"prettier:check": "prettier -l src/**/*.{js,vue,scss}", / /"prettier:check"Check whether any js, vue, SCSS files in the SRC directory of the project exist format problems;"prettier:fix": "prettier --write src/**/*.{js,vue,scss}"
//"prettier:fix"Format all js, vue, SCSS files in SRC directory.Copy the code

This way, we can check the code format and automatically fix the format by executing commands, and reduce the disadvantages of different code styles and individual code format changes, once and for all.

Improve Git normalization

The rapid iterative requirements and parallel development pace of multiple requirements in PLUS project lead to new branches for development each time, but often after the carnival, the code is submitted for temporary convenience, and the original modification purpose is often unable to be remembered at the end. Git version management system has made outstanding contributions to the order and stability of the code, but it needs to be standardized and optimized at the same time to make Git show more value.

Standardizing Git commit

All submissions are suggested to be in the form of an identifier: content that states the purpose of the submission and makes each submission worthwhile

logo instructions
feat New features
fix Fix the bug
docs Documentation
style Format (changes that do not affect code running)
refactor Refactoring (that is, code changes that are not new functionality or bug fixes)
test Increase test
chore Changes to the build process or ancillary tools

Submit information optimization

Above is a paragraph of submission information in the PLUS project, several identical submissions in a row, such that the value of the submission is diminished. In general, the Commit Message should be clear about the purpose of the commit. For this to happen, there are the following scenarios:

  1. If the current branch is in the middle of development, you need to switch to another branch. If you do not commit, you may not be allowed to switch the branch or bring the current changes to the new branch.
  2. The current branch opening function has been developed, a version is submitted, a problem is found later, may be just a line of code, in the submission of a time. The code was submitted back and forth several times;

For both cases:

  1. You can use Git Stash apply. You can save it temporarily but not commit the code until you switch back to branching.

  2. In the second case, you can use git commit –amend to undo the previous commit to the staging area and resubmit the content.

Note: This method must be performed before the commit has been committed to the remote. Do not execute this command after the commit has been committed to the remote.

Process optimization

When I think back to 2019, I have a special taste in my heart ~ ~ after going online all night long, I saw my colleagues coming to work the next day with blurred eyes. I’ve also been awakened by a weekend morning call to support an urgent need. Sometimes just after work, but was notified that there is a need to review immediately. There have been times of stress, confusion and mood swings. Although we have no regrets, but a standardized process, should not be so exhausting. Work is a process of constantly encountering problems and solving them. Taking the initiative to promote the standardization of projects and improve human efficiency is a positive attitude towards problems. So we actively pushed in the following direction:

Formulate development specifications

The turnover of the team and the need for rapid iteration left new members unsure of how to start the PLUS project. At the same time, a qualified project also needs to formulate development specifications, which can not only let the development members quickly understand into the project, but also let the old members clearly standardized development process. Therefore, our team mainly summarized from the following aspects:

  1. Comb the state distribution of each branch
  2. Develop the project development process
  3. Summarize project debugging methods
  4. Standardize the on-line process
  5. Summary plus member related information links

Including but not limited to the above directions, by formulating and summarizing project specifications and problems encountered during development, the team developers can be effectively promoted to be familiar with the project, avoiding the status quo of new members crossing the river by feeling stones, which is conducive to the rapid integration of PLUS project and the smooth undertaking of development work.

Optimizing the review mechanism

The rapid development of PLUS business, frequent requirements review, anytime and anywhere meeting, bothered the whole PLUS project team members. Planned things often have to be interrupted, and the work at hand has to be digested overtime. In the long run, not only will the team members be overwhelmed, but also the schedule of the whole project will be disrupted, which will seriously cause the butterfly effect, and the subsequent demand may be affected. Therefore, it is urgent to solve this problem.

At the project review meeting, it called for the establishment of a more reasonable review mechanism and the standardization of the requirements review meeting. Fortunately, with the strong cooperation of various teams, we have passed the system of a collective requirement review every two weeks. For urgent needs, assess whether to organize separate reviews according to their urgency.

After the confirmation of the demand review mechanism, unless the 6.18 Promotion, Double 11 activities and other festivals have intensive review, other times have been greatly improved. The reasonable review mechanism enables people to better arrange the work at hand, and greatly alleviates the headache of demand chaos.

Promoting new technology learning

Learning is like rowing upstream; not to advance is to drop back. In an environment where front-end technology is increasingly updated, if only business needs are met, team members will not only slowly get into their comfort zone, but they will also gradually fall behind in technology. However, with multiple parallel requirements to support every week, proactively initiated project optimization by the front end, and team members to learn some new knowledge, time is often limited. So we should not aimlessly learn new knowledge. The PLUS membership program must be targeted. The new techniques learned can then be put to use in the PLUS project, whether it’s to improve the code or optimize the user experience.

So based on the above goals, we began to consciously explore. Since the project was developed in Vue, we have been looking at the source release of Vue 3, which uses TypeScript technology. I find TypeScript has many advantages, especially in terms of code readability and maintainability for collaborative projects. No rules can be achieved, so our team made a study plan, and everyone used their spare time to study. When the project demand was not tight, we organized some members to share technology and discuss knowledge about the technology. In addition, there is an attempt to introduce TypeScript into the new page, which leads to the practice of TypeScript section above.

Collaboration with the visual side

Since PLUS members have a lot of iterative needs, most of which involve updating visual sketches, close communication with designers is the norm. In this process we found two relatively prominent problems.

  1. The designer uses the company’s product collaboration tool RELAY (blue Lake), but some pictures are not given to the cut map, or when we find some cut map does not meet the research and development expectations, so we contact the visual designer to get the corresponding cut map, because everyone is busy, may not reply in time. The problem can block, and in serious cases, such as when the page is refactoring without a lot of graphics, or when the relevant size, color, and other information is not available, the project can get stuck. Increases the cost of communication invisibly.

  2. The requirement on-line needs to go through the visual designer’s style check, check the problem needs to be modified. However, for a variety of reasons, many times the project is online in the evening, the afternoon of the visual check. Lead to research and development without time to change, and once the change is easy to lead to other style problems.

After a few sessions, we sat down with visual designers to figure out how to solve these problems.

  • For Question 1: Increasing r&d confirm draft link vision, visual designers, after finalized or r&d development before, the visual version of this needs to go first to check it again, will need to use in the process of cutting figure feedback to visual designers, unified provide cut figure, in addition, the thoughtful fashion designers added PS manuscripts, convenient we contact less than the person, to leak fill a vacancy.
  • For problem 2: Every time the R&D side sends the test email, the relevant @ visual designer should be copied to promote the visual inspection in the test stage first. In addition, the test students should inform the product in advance when the visual walk-through is needed. The product side should apply for visual resources in advance. The application for walk-through and the walk-through results should be sent through the email.

Through the above methods, to the maximum extent to ensure that the R and D in the development of the project to get their desired visual information, to avoid the last-minute, to the development of the problem of communication, reduce the cost of communication. In addition, the visual designer was informed in advance to conduct a style check, so as to avoid the potential problems easily brought by changes before the launch.

Advance the migration of older versions

For historical reasons, the PLUS membership program has three branches with nine pages in different states. The first pages were developed two years ago, and some of the technology and development code used at the time was not very standard, mixed with some code from the JDF + Zepto technology stack. In the following development process gradually extended to a total of three main development branches: V2, V3, V4.

  • V2/V3, developed in the first half of 2017, not based on Webpack, influenced by JDF, not reasonable. Home calculator and my PLUS calculator are not reused, use the old version interface
  • V4, the new version of the first half of 19 years, based on Gaea4 modified to a Vue multi-page page application, including many new features, performance has been greatly improved

New features in V4 include

  • Upgrade Webpack to 4.0 and Vue-Loader to 15
  • Integrates carefree and NutUI2.0 on-demand loading plug-ins
  • Babel has been upgraded to 7.0 to enable on-demand loading of Polyfills
  • In combination with code and floor data lazy loading, Tree-shaking, Scope reactive, DllPlugin to eliminate unused CSS and other technical means to reduce the code volume
  • Part of THE H5 links in JD APP are opened by pulling up new WebView through OpenApp protocol to improve user experience and the success rate of burying site reporting
  • Comprehensive application of WebP and DPG image format, reduce image volume, improve the image rendering speed
  • The introduction of Vuex for centralized data management, immersive, skeleton screen

  • The loading speed bottleneck in older versions was serial requests: page scripts → user information interface → floor information interface → floor data → rendering.
  • V4 version through the back end of the user information interface and floor information interface data directly on the page, to avoid the serial waiting interface, improve the home page rendering speed: page script → each floor data → rendering

Chrome’s built-in automated test evaluation tool Audits new pages in V4 with higher performance ratings

The introduction of skeleton screen can shorten the waiting time of white screen. As shown in the figure, the skeleton screen is displayed during the 200ms-600ms white screen test, and the white screen time is shortened by 2/3, which is helpful to improve the subjective loading speed of the page and improve the user experience.

This makes the move to V4 particularly important for performance and development efficiency. Especially when multiple parallel requirements come along, involving development based on a series of new subbranches pulled from three main branches, the drawbacks of maintaining multiple versions become apparent. Therefore, we take the initiative to speak out, to improve the effectiveness of the starting point of reason and facts. First of all, I won the understanding and support from the product side (special thanks), so that the project can be set up and the needs can be met, and then I will get the resource support from the project manager and the test. Push the product side to focus on code version migration, gradually migrating older versions of code to the latest V4 branch in subsequent iterations of requirements.

So far, the season pass expired home page, year pass expired home page, Prime product page [later changed to money saving strategy page], my PLUS page (officially expired, trial status), trial expired within 30 days are migrated to V4 on V2 branch. The exception page with few changes in V2 and the code in trial and within 30 days of trial expiration in V3 are left. This process is not yet complete; the ultimate goal is to migrate all user state and page code to the latest technology stack architecture branch.

Standardization of schedule

With the emphasis on the PLUS project, we arranged a separate r&d to follow up all requirements and schedules, so that everyone would not have to support the development while being interrupted to attend various meetings. All requirements are reviewed and sorted out to determine which can be developed in parallel and which need to be developed in serial. Work with the project manager to work out the schedule for the front end team. This way, everyone’s work for the next week is defined, with a clear division of labor that is not disrupted by temporary and urgent needs.

In addition, all urgent needs, new inserted needs and online problems shall be sorted out and investigated by the docking person, depending on the demand situation:

  1. Arrange for more idle R&D support for emergency needs;
  2. Not particularly urgent needs to arrange the next schedule;
  3. For online problems, if they can be fixed quickly, they usually go online with the next online demand; If it can’t be repaired quickly, reschedule.

In this way, the time of the whole team can be better arranged, and they will not be led by the nose by the project requirements. The weekly work is arranged, and everyone’s work is clear, so they can adjust the pace of their work appropriately and avoid the insertion of various urgent needs.

After the above measures, team members can quickly enter the project development, the division of labor is clear, and what to do at each node becomes clear. At the same time, it also improves the communication and collaboration with other teams, and reduces buck-passing. Mencius once said, without rules, no square or square can be formed. You can’t correct five notes without six tones. I think so!

conclusion

On The Singles’ Day of 2019, the number of PLUS members exceeded 1500W, ushering in a new historic moment. One PLUS member spent 467,000 yuan on a single purchase, making it the highest single purchase on JD.com. We feel the achievements of the team at the same time, but also feel a great responsibility. Looking back on 2019, it was an extraordinary year for the PLUS front end team members. On the premise of ensuring the completion of numerous iterative requirements, the PLUS member project is gradually improved from aspects such as optimizing user experience, improving development efficiency and promoting the improvement of system and process.

At the moment, the cold winter wind whistling outside the window, blowing away the haze of the past, blowing the sun, clear skies. Quietly grasp the tail of 2019, full of hope for the upcoming 2020. Just like the challenges encountered by THE MEMBERSHIP program of JD PLUS, we will eventually cross the past and usher in a new journey. Goodbye in 2019, come on!