In my front-end development team, the adoption of the front – end separation was done after the entire line of business was stabilized. In the early stage of the business, it mainly adopts the back-end set template method, and at the present stage, it adopts the single-page development mode based on Vue.

This will lead to a situation that in the process of continuous iteration of the product, since the front-end code before is not an engineering project, the new requirements in the future are mostly coded and put online by another Vue project. There is no unified project for the front-end in the whole business line, and the projects are too scattered and difficult to optimize management. A project refers to a project code created based on a new requirement. An engineering code refers to a set of code containing multiple projects. This agreement follows.) In view of this situation, we have made some attempts to integrate multiple existing projects into one project and unify the entrance.

Of course, we hope that the integration into a unified project can achieve painless access to follow-up new needs. Here are some possible solutions to some of the problems encountered during the integration process. This article briefly introduces code hierarchy, component processing, routing, data state maintenance, and other optimizations.

1. Code hierarchy

How to divide the whole project catalog reasonably?

In front end development we first face the problem of how to place code and static resources at the directory level. For example, in the early days, directories were usually named img, CSS, and JS. So in the context of combining Vue related technology stack and multi-project integration scenario, how to divide the directory to ensure a reasonable code level?

While talking about this problem, we can first think about what the overall project needs to be related to the function. Apart from the internal structure of the specific source code, there are build scripts, build configurations, Mock data, project documentation, project source code, and so on. In the absence of a specific technology stack, this is also a rough list of the engineering aspects of the front-end.

Specific to the internal directory structure of the project source code, according to different functional modules, mainly made the following level division:

  1. Static resources split directories by project
  2. The routing component splits the directory by project
  3. Child components split directories by project and parent routing component
  4. The routing layer splits different files by project
  5. The data layer splits directories by project
  6. Mixins mix code to split different files
  7. The configuration layer splits different files by project

Take component related directory under project SRC source code as an example, as shown in the figure below:

├ ─ ─ pages / / routing component │ ├ ─ ─ the README. Md │ ├ ─ ─ base based routing component / / global directory │ │ └ ─ ─ SuccessPage. Vue │ ├ ─ ─ period_process / / project level of A routing components directory │ │ ├ ─ ─ ChooseTime. Vue / / project A choice time routing component │ │ ├ ─ ─ XXX │ └ ─ ─ period_suborder / / project level of routing component B │ └ ─ ─ XXX | ├ ─ ─ the components / / Child components directory │ ├ ─ ─ the README. Md │ ├ ─ ─ base / / global based subcomponents │ │ ├ ─ ─ AddressInfo. Vue │ │ └ ─ ─ XXX │ ├ ─ ─ period_process / / project A subcomponent │ │ ├ ─ ─ base / / project based A subcomponent │ │ │ ├ ─ ─ Picker. Vue │ │ │ └ ─ ─ XXX │ │ ├ ─ ─ choose_time / / project A choice time routing component subcomponents directory │ │ │ ├ ─ ─ the Cleaner. The vue │ │ │ └ ─ ─ XXX │ │ ├ ─ ─ XXX │ └ ─ ─ period_suborder / / project subcomponents B │ └ ─ ─ XXXCopy the code

Of course, the project directory structure is not the same layer, can be flexibly handled according to the business scenario and technology stack. However, in principle, long code should be avoided when a file is written from beginning to end, resulting in poor readability and maintenance problems in subsequent iterations. Good code hierarchy can be summarized as aggregating the same functional modules into the same directory and splitting them into separate files.

2. Component maintenance

How do you control component separation granularity?

When it comes to component parts, component separation granularity is always an issue. First, the big aspects are divided into routing components (page components) and corresponding page face components. A routing component is a component during route configuration. A component is separated and referenced by its subcomponents. Routing components and subcomponents split corresponding service components and basic components respectively.

In the process of page component splitting, we split the relevant functional module code into sub-components. Divide the page into sub-components (functional modules), each of which performs a sub-function. As shown below:

How can business components be promoted to base components?

In component partitioning, we split the sub-components into business components and base components. In the process of project integration, business sub-components need to be promoted to basic components because they are used by multiple subsequent projects. However, in the initial coding process, it was only considered as a sub-component of the business, and the internal data source was mostly dependent on Vuex. When it was promoted to a basic component, a lot of work was needed to change the data source to props object, and modify the data source operation to emit triggering event mechanism.

A better approach here is to want the internal data source to rely as much as possible on the props object passed by the parent component when writing the child component. Promote the behavior of the data source that needs to be modified to the parent component via emit.

3. Route related processing

How to handle multi-entry routing configuration?

Single-page Web applications put forward the concept of front-end Router when dealing with different views. For a single project, we can easily set the default route entry to solve the problem. However, for multi-entry multi-project projects, some consideration is required. At the same time, since the APP of the company where the author works does not contain hash by default when processing URL redirects, there is no way to redirect the corresponding view by attaching hash route in URL access.

The solution we adopted was to use URl access without hash, and the back end would place the PAGE_TYPE variable in the entry HTML files of different projects, and the front end would jump to the corresponding routing components based on the PAGE_TYPE variable. The PAGE_TYPE variable corresponds to the route currently to be accessed. By combining the amount of route markers rendered by the back end in the page, the access path problem is solved.

On this basis, also need to consider the page refresh and jump out of the chain back. Refreshing the non-entry routing page resets the entry routing page based on the PAGE_TYPE variable. In this case, you need to check whether the current URL has the hash route flag, and obtain the hash value of the current link first. The specific pseudocode is as follows:

let routeType = window.PAGE_TYPE  // Get the initialization route variable
let routeName = getHashRouter()   // Get the current route name

if (routeName) {
  router.push({path: ` /${routeName}`})}else {
  switch (parseInt(routeType)) {
    case 0:
      router.push({path: '/index'})   
      break
    case 1:
      router.push({path: '/projectB'})   
      break
    default:
      router.push({path: '/index'})  // Default route entry}}Copy the code

How to optimize asynchronous component loading?

Another issue worth considering is that as the project grows and the application is packaged and built, js files become larger and larger, affecting page loading speed. Asynchronously loading non-entry routing components is a relatively efficient solution. Lazy loading of routing components can be easily achieved by combining Vue’s asynchronous components with Webpack’s code Splitting feature. For details about the syntax, see the official vue-router document.

Non-entry routing components load asynchronously, reducing the size of the JS file that is loaded for the first time. However, the subsequent problem is that if the user chooses to click the button to redirect, it needs to asynchronously obtain the JS file and wait for the completion of the loading of the asynchronous component before jumping. In particular, before the jump also need to call the asynchronous interface verification, the user waiting time is undoubtedly increased. We prefer to be able to preload asynchronous components for subsequent jumps during the user’s idle time.

You can manually load asynchronous components in Mounted during the component life cycle. You can also aggregate preload operations into mixin files and register them as global mixins. Buried data shows that the hop time of subsequent routing components is about 300ms, which is in the open range of seconds. The following is an example:

mounted() {// preload subsequent asynchronous routing components import(/* webpackChunkName:'chooseTime'* /'@/pages/period_process/ChooseTime.vue'// Use webpack-specific require.ensure syntax // require.ensure(['@/pages/period_process/ChooseTime.vue'], null, 'chooseTime')}Copy the code

Load the non-entry routing components asynchronously and preload the following routing components during the user’s idle time. Reduce the user wait time and the user experience will be better.

How to gracefully handle route jump effects?

The route jump effect mentioned here refers to the transition effect added when different routing components jump. The default router-view jump of Vue has no dynamic effect and feels a little stiff. Adding Transition to router-View is a good choice.

However, in the process of transition, the transition effect is initially added to the root node of the routing component, but there will be an obvious blinking screen phenomenon when jumping from some Android models. The solution is to move the Transition component outside of the router-View component.

4. Data status maintenance

How do I maintain the state of data in my project?

The main data interaction behaviors that can be expected are:

  • Parent and child component data sharing
  • Sibling component data sharing
  • User behavior data store
  • Back-end interface data caching

In addition, we also want all data layer models and asynchronous interfaces to be extracted for uniform maintenance, so we introduced Vuex.

Vuex is a state management mode for Vue applications. It uses centralized storage to manage all application component states. Common problems in Vuex are not introduced. Multiple views depend on the same state and need to change the same state for multiple views. In both cases, parameters are passed between components or event synchronization state is adopted. After Vuex is introduced, component sharing state is extracted into singleton mode for management. Define and agree to comply with certain state management rules, code structure is clearer and easier to maintain. Of course, using Vuex can be cumbersome if you don’t develop complex single-page applications.

We also need to consider that since Vuex data state is stored in JS variables, the entire application state is lost when the page is refreshed. Local persistence operations need to be added to state, mutations read, and storage. Encapsulates the local persistent storage layer cache. js. SessionStorage, localStorage, and indexedDB storage modes are optional. Choose the corresponding method in the mutations file to do local persistence operation according to the business situation.

Vuex + Cache is used to maintain data status and separate corresponding codes into independent data layers to reduce the degree of coupling with business codes. In business processes, only mapState and mapActions are required to obtain the corresponding data status or update the corresponding data status.

How to ensure that data state is not contaminated in multiple projects?

In the integration of multiple projects, it is inevitable that variable names of state in each project will conflict and multiple state variables will pollute each other. Meanwhile, actions and mutations operation are also exposed in the global state. This will be a ticking time bomb as projects are integrated.

The good news is that Vuex has a solution. Vuex proposes the concepts of module and namespace. Vuex allows us to split the Store into modules, and make it a namespace module by adding Namespaced: True. Multiple projects use their own state objects, reducing the degree of data coupling and the possibility of contamination.

In combination withVuexWhat else can you do for fun?

According to Vuex’s rules for data state storage and modification, it is easy to split the data layer into corresponding layers. In this case, asynchronous requests can be uniformly aggregated and encapsulated into fetchDataaction methods in the global state. In unified asynchronous requests, we do the following:

  • Preventing duplicate submissions
  • Unified handling of network exceptions
  • Caching interface data (optional)
  • Automatic processing of data returned by the interface with code not 0 (optional)
  • Displaying the Loading State (Optional)
  • Automatically reporting interface request time (Optional)

As a result, our business components no longer need to worry about repeated commits, network exceptions, and so on in asynchronous requests. The single Vue file component focuses only on the implementation of process logic.

5. Other optimizations

How do I split the business-independent logic code in a component?

To clarify, irrelevant logic here refers to code that has little relevance to the business. For example, when the front-end router switches to different views, you need to consider switching to the corresponding view to set the page title of the current view or send the PV burying point of the current view. Almost every routing-level component will write code similar to this, unrelated to business logic. So how do you extract the split?

Mixins are a flexible way to distribute reusable functionality in components. Accepts a mixed object or an array of mixed objects via mixins or vue.mixin () syntax. The blended object can contain any component option, and the hook function of the same name will be blended into an array. The blended object’s hook will be called before the component hook.

Combined with the mixin syntax in Vue, it is easy to split the base business-neutral code into different mixin files and register them as global mixin objects with vue.mixin (). Write corresponding component life cycle functions in different mixin files to preload components, set page title, send PV and other operations.

How to combine septo divisional projects?

In a nutshell, while we were integrating the project, we found that the previous build script had combined multiple project images into one while processing the Sprite image merge. In this case, users will download Sprite map resources of the whole project in the process of accessing Project A, occupying traffic and wasting resources. So how to combine Sprite art by project?

Here we use the Webpack-Spritesmith module to merge Sprite images. By instantiating webpack-Spritesmith objects and passing custom templates, CSS and SCSS files are constructed respectively (please refer to official documents for details). In fact, building different Sprite images by project is similar to webpack building multiple HTML pages. Push multiple instances of Webpack-Spritesmith in plugins configuration array of Webpack, and each instance builds Sprite graphs under different projects. Different project business components can then reference the corresponding Sprite diagram style file.

conclusion

In the process of integrating multiple projects with related requirements into a single project, we have been stepping on pits and filling pits from the detailed design in the early stage to the subsequent access of multiple projects online. This article is also for some of the more typical problems we encountered to share.

Today, the front-end is increasingly pursuing engineering, how to make the project clear, simple code, lower coupling and better performance on the basis of engineering is the direction we need to think about.

Finally, this paper mainly focuses on the integration and unified engineering practice solutions of multiple related projects based on Vue.

Hasty written, if there are mistakes, improper wording, please be corrected 🙂