As the old saying goes, quote depends on the moment, quote straight.

In the process of developing a project, we often need to reference a large number of third-party node modules. Indeed, the use of third-party modules can greatly simplify the development process and improve the quality of the project. But inevitably, it also brings up the issue of “volume”. The author once developed a simple website project with simple functions and business logic just for viewing information. But after the confusion compression, it still reaches more than 1M. B: Yes, this project is an unquestionable failing grade. Because even in today’s era of casual 100m networks, due to the impact of multiple factors such as servers and access, the entire project often takes seconds to load. Here’s how someone on the Internet described those seconds:

About a quarter of people give up if a page takes longer than four seconds to load. If a page takes more than 10 seconds to load, 50 per cent of mobile users abandon the page and around three-fifths do not return to the site.

So, to the extent that we can, in addition to increasing our access speed on the physical level, we should also start from the root of the project and reduce the access time as much as possible. In this article, I summarize some of the ways in which previous projects have been streamlined in the hope that you will find it helpful.

Analyze your project

In general, WebPack is the perfect choice for a VUE project. So, how do you analyze package files packaged with WebPack? This is where webPack-bundle-Analyzer, the package analysis tool at the heart of this article, is introduced.

Webpack, as you know, is a tool for packaging web elements. A JS file contains not only javascript code, but also elements such as “HTML”, “CSS”, and so on. It would be impractical to analyze the package directly, or the WebPack configuration (even in Vue Cli 3, Angular Cli 3, there is no WebPack configuration file). Webpack-bundle-analyzer provides graphical package analysis.

In WebPack-Bundle-Analyzer, we can see the percentage of each module in the project, and the size of the module in the Stat, Parsed, and Gzipped states. Well, yes, so we can find out who is making the project bloated!

2. Introduce/open the analysis function of the project

  • Project using Vue Cli 3

    For projects managed using Vue CLI 3, package analysis has been built in. You just need to add parameters at compile time--reportAnalysis reports can be generated.
  • To use Vue Cli 2 or other Webpack projects first, you need to installwebpack-bundle-analyzer
# NPM 
npm install --save-dev webpack-bundle-analyzer
# Yarn 
yarn add -D webpack-bundle-analyzer
Copy the code

Then, add it to the project’s configuration file:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}
Copy the code

Once compiled, an analysis report is generated.

  • Off topic: Angular projects

    Similar to Vue Cli 3, the NG Cli also includes package analysis. At compile time, parameters are added--stats-jsonA JSON file will be generated.

    You can do this via ““ webpack-bundle-Analyzer orwebpack.github.io/analyseAnalysis package structure

3. Streamlining dependency

Now that we know who the culprit is, we should deal with it. For different third-party modules, we have different methods to solve it:

1. General method: Import on demand (minimal import)

The most common form of import is this:

import crypto from 'crypto-js'. crypto.HmacSHA1() ...Copy the code

This approach will introduce the entire Crypto (third party module). However, we often only need one or two of these methods. This is a very uneconomical behavior and is the most common cause of bloat in projects. By locally introducing the required methods, we can greatly reduce project bloat:

import HmacSHA1 from 'crypto-js/hmac-sha1'. HmacSHA1() ...Copy the code

As for how to find locally imported files, there is no standard answer because the project structure varies from module to module. However, the most common approach is to look at the entry files of third-party modules or consult official documentation to find a way to minimize the introduction.

2. Compromise: asynchronous loading

What affects the loading speed of the first screen are the JS files that are “synchronized” with the HTML files. There are quite a few third-party modules that are not used in the first screen load, and they can’t be effectively reduced in size by “minimal introduction”. At this point, consider asynchronously loading content that doesn’t need to be loaded with the first screen when it needs to be. Those of you who are familiar with Vue are probably familiar with the writing of Vue asynchronous components

. components: {asyncComponent: (a)= > import('./asyncComponent.vue')
    // function(){
    // return import('./asyncComponent.vue')
    // }}...Copy the code

For starters, however, this might be mistaken for the way asynchronous components are loaded as provided in Vue. But really, this is how WebPack does asynchronous module loading. Import can be used in various ways, such as loading Echarts

const Echarts = (a)= > import('echarts')... Echarts().then(echarts= > {
     echarts.xxx()
 })
...
Copy the code

This method can also be used in Angular 8

3. Introduction of some UI libraries on demand

Many popular UI libraries do not directly introduce the required components on demand (many of them do, but a few have problems). Examples include Element, Ant-Design-Vue, iView, Mint UI, etc. But they tend to be very “huge”, most measuring 2 to 3M. For web apps, this is definitely unacceptable. Fortunately, they can all be imported on demand (or directly) via the babel-plugin-Component. You can refer to their official documentation for specific methods. Note that since CSS files are introduced globally, you need to be aware of style contamination.

4. Streamlined schemes for some special modules

For some specific modules, they may not be able to slim down using an “on demand” approach. Moment.js, for example, comes with a full set of multilingual modules along with its own ontology. But that’s often what we don’t need.

webpack ContextReplacementPlugin

The ContextReplacementPlugin can achieve this by ignoring certain files of imported third-party modules through regular expressions or other filtering conditions.

In the official webpack documentation, moment.js is used as an example.

new webpack.ContextReplacementPlugin(
  /moment[\/\\]locale$/,
  /de|fr|hu/
)
Copy the code

Since this is a big fat man. Why don’t you go get a skinny guy?

When all approaches fail to meet the functional requirements > file size, why not try another module? NPM is full of modules with similar functions, such as queryString, qs\ query-String \ queryStringify… Most of them have similar functions, but there are many differences between them due to different methods of implementation, different forms of consideration and so on. Therefore, in order to reduce unnecessary file size, we can try to select modules that are similar or not as powerful but fit our needs exactly. As “moment.js” can be replaced by “dayjs” in most cases. The latter claims it takes up only 2KB of space.

Of course, when choosing a third-party module, you also need to consider whether the module is mature enough.

5. Ultimate Solution: Do it yourself

Third-party modules can help us solve a lot of problems. But not all “complex” features need to be solved by introducing third-party modules. A simple example: you don’t need to import a Vue Router or XXX Router if you only need to get the parameters in the URL. All you need is qs.parse(location.search). Not even the QS library:

Object.fromEntries(
  location.search
    .slice(1)
    .split('&')
    .map(v= > v.split('=')))Copy the code