background

If the user has to reload all the resources (JS, CSS) from the server after the version update iteration and the new code comes online, it will definitely make the page open slower, which is not necessary.

In order to optimize user experience and improve page opening speed, JS can be divided into multiple modules. Each time there is an update, the user only needs to load the updated business code, which is subcontracting.

plan

In general, front-end projects, regardless of the framework, are Webpack-based packages, such as umi, next, nuxt, and vue-cli, so this article only presents solutions based on Webpack packaging tools.

Webpack4 provides the splitChunks plug-in, which is used for splitting code into runks. You can check the official documentation for details on how to perform runks.

A common subcontracting strategy is to repartition our packages based on size, share rate, and update frequency to make them as accessible as possible to the browser cache.

According to this strategy, a general subcontracting scheme is presented, and JS is divided into the following three modules:

  1. Third-party dependencies (node_modules)
  2. UI libraries (ANTD, ELEMent-UI, Cube-UI)
  3. Business code

As a result, the only ones that usually need to be updated after each code release are 3, and 1 and 2 are simply read from the browser cache.

The implementation of

Take Phoenix project as an example, the current situation of online pages after packaging is as follows:



Use the analysis tool to see what each module is:

  • Umi.js: Frame JS
  • Verdors.async.js: Third-party dependencies
  • Js and p_discountDetail_Index.Async.js: Business code
  • (ignore bundle.min.js, this is the sentry script)

By default umi subcontracts without doing anything, because its built-in Webpack provides the default subcontract policy:

  • Whether the new chunk is shared or is a module from node_modules
  • Is the new chunk volume greater than 30KB before compression
  • The number of concurrent Chunk requests loaded on demand is less than or equal to 5
  • The number of concurrent requests on the initial page load is less than or equal to 3

Use the above scenario to optimize the default subcontracting policy, extract the UI library, and add the custom subcontracting code in the configuration file (umirc.ts) :

config.optimization.splitChunks({
  chunks: 'async',
  minSize: 30000,
  maxSize: 0,
  minChunks: 1,
  maxAsyncRequests: 5,
  maxInitialRequests: 3,
  automaticNameDelimiter: '~',
  name: true,
  cacheGroups: {
      vendors: {
        name: 'vendors',
      test: /[\\/]node_modules[\\/]/,
        priority: -10,
        },
    antdesigns: {
      name: 'antdesigns',
      test: /[\\/]node_modules[\\/]antd-mobile[\\/]/,
      priority: -9,
        }
  }
})

The meaning of the representation of each field is not repeated here, please check the official documentation. Look mainly at cacheGroups and extract antd.

Now let’s see what the package looks like:



Added an antdesign.js, successfully extracted antd.

Q: In fact, we can think about whether it is appropriate to extract ANTD.

A: Phoenix project is a multi-page application, the number of pages is not large at present, and ANTD also supports importing on demand. Packaging the ANTD code into the business code of each page or node_modules will not add much volume, while the ANTD code is not large, so it needs an additional HTTP link after extracting it separately. It doesn’t feel necessary. But as the project gets bigger, that may not be the case. Therefore, each project should be subcontracted according to its own situation.

conclusion

Subcontracting is a process of game. Should I make A bundle bigger or B?

Should the first load be faster or should the cache be more utilized?

However, it is important to remember that when unpacking, do not go too far in the quest of granulation, everything into a separate bundle, or you may need to load more than a dozen JS files per page, if you are not HTTP/2, the request blocking is still very obvious (limited by the number of concurrent browser requests).

So again, there is no complete solution for resource loading strategy, and all of them need to be subcontracted according to the project itself.

What we’re going to do next

The next step after subcontracting is to make full use of the browser cache. The first step is to put the static resources on the CDN, and then set up a reasonable caching policy. As long as the chunk hash does not change, all the resources will be read from the browser cache.

Reference data: https://panjiachen.github.io/…

Article/small Calvin

Pay attention to the technology of things, hand in hand to the cloud technology