After entering the company, he took over a big project left by predecessors. Fortunately, the whole project has a complete documentation of product functions, but the project is too large and old. This includes problems such as slow packaging and redundant files. It would be too expensive to solve these problems quickly and completely refactor the functionality. A file to pass, the time cost is relatively large. So in this article, let’s take a look at how I worked with WebPack step by step to analyze and optimize the project.


I also encapsulated one for the idea
webpack-unused-files, used to find redundant files in the project, welcome to try and star



The original link

The problem

First of all, let’s take a look at what problems we have and work on them step by step

  • The project is frequently modified and has too many redundant files
  • Some third party dependencies abuse, want to remove but do not know in which file. Or useless, but left behind in package.json,
  • Projects are huge, packaging results are too big and take too long

Delete redundant files

Due to frequent changes to the project, many files are no longer in use and have not been deleted. As the project grows, it can only affect how quickly we can locate features and problems, so it is important to clean up redundant files. But it’s hard to tell by eye which files are dependent or not, so we need to use Webpack.

1. Obtain all files that the project depends on

Let’s take a look at the webpack output file format:

{... Chunks: [{name: 'chunk-name', modules: [// all dependent files in each chunk]}]... }Copy the code

So, according to stats.json, we can get all the project files we get in the entire project:

/ function findSrcModules () {return new Promise(resolve, reject) => {fs.readFile(statPath, (err, Parse (data) const assetsList = json.chunks ret = [] // Get all dependent files of all chunks  assetsList.forEach(chunk => { const modules = chunk.modules.map(item => item.name) ret = ret.concat(modules) }) // Ret = ret.filter(item => item.indexof ('node_modules') < 0) resolve(ret)})}Copy the code

With this step, we can get all the files for the package dependencies in the project.

2. Get all the files in the project

With glob, we can get all the files:

function getAllFilesInSrc () {
  const pattern = './src/**'

  return new Promise((resolve, reject) => {
    glob(pattern, {
      nodir: true
    }, (err, files) => {
      const ret = files.map(item => {
        return item.replace('./src', '.')
      })
      resolve(ret)
    })
  })
}Copy the code

3. Compare two file arrays and delete them:

Comparing the two arrays, files that do not appear in the dependency are redundant. We can delete it with one click

findSrcModules().then(ret => {
  getAllFilesInSrc().then(allFiles => {
    const unUsed = allFiles.filter(item => {
      return ret.indexOf(item) < 0
    })
    const join = p => path.join('./src', p)

    unUsed.forEach(file => {
      shelljs.rm(join(file))
    })
  })
})Copy the code

Analyzing third-party dependencies

According to the idea of redundant files above, we can also handle third-party dependencies, the general idea is as follows

  1. Get all dependencies that contain node_modules
  2. The file name for interception, deduplication. Get all the dependencies
  3. Compare this to package.json to get unused dependencies
  4. The comparison results are analyzed, and unwanted dependencies are saved
  5. Look at stat.json again, look for the dependency’s reson field, ask where the dependency is referenced, and output it
  6. Manually replace or delete dependencies

So to speak, with all the dependencies and dependencies, we can be very flexible to deal with them and get the results we want.

This feature will also be updated to webpack-unused-files.

Optimize package size

Surprisingly, the size of the whole project was nearly 20M after packaging for various reasons! It’s not a TO C project, and it’s split code and lazy loading for pages, but as a “decent front end” it’s something that needs TO be fixed (yes!). . How do you start? Go through the code one by one to see what big dependencies we reference and which projects are too big and complex. Let’s see what Webpack offers me:

1. Show packing results

As we know, the webPack results are automatically displayed on the console after the webpack is finished. It also provides the ability to output dependencies and sizes, so we can display all dependencies and see their sizes by executing the following parameters.

webpack --display-modules --sort-modules-by sizeCopy the code

The result is something like this:

We can quickly locate the top JS files or third-party dependencies and decide what to do with them.

2. Visualize dependencies

Webpack provides the ability to package all dependencies and relationships in JSON format:

webpack --profile --json > stats.jsonCopy the code

This is the basis of our whole article. Many people have encapsulated a lot of visual analysis tools based on this, which can intuitively see the dependence and size of each file and chunk, and quickly locate large files and modules

webpack analyse

webpack chart

3. Optimize the plan

Through the above two methods, we can locate and analyze content files and dependencies very well. There are many optimization schemes for package size on the Internet, which will not be repeated here, but provide several ideas and references:

  • CommonsChunkPlugin extracts common code
  • DLL – Plugin for large files individually packaged, cached
  • Remove useless dependencies (described below)
  • Optionally deprecate some dependencies
  • Code compression
  • babel-polyfill
  • Scope Hoisting

Optimize packaging time

There are a lot of articles on how to optimize the packaging time, so here are just some ideas. Our main point is that the project references a lot of SVG ICONS and flag ICONS in the build, and the packaging time becomes extremely slow each time a static resource is processed.

The SVG-Sprite-loader we used in the project automatically does SVG-spirte for each SVG icon. But we know that once these ICONS are referenced, we rarely modify them. Especially something like the flag icon, but we had to repackage it every time we built it. Therefore, we can advance these ICONS to svG-Sprite. Recommend a site that has various SVG ICONS pre-sprite and automatically references them:

iconmoon

Daily packaging time optimization point

  • Externals avoids packaging large third-party dependencies
  • Dll-plugin prepackages third-party dependencies
  • Happypack multi-process processing, caching
  • Caching versus incremental builds

    • babel-loader? cacheDirectory
    • webpack cache:true
  • Reduce build search or build path alias resolve
  • Scope include exclude for concrete packaging

conclusion

Through json analysis of webpack output dependencies, we can intuitively get the following data:

  • All dependent files and their size
  • Which files each dependency file is referenced by
  • Third party dependencies of project dependencies

With this data, we can easily optimize existing projects.

Where there is life, there is life. Let’s say goodbye to all that disgusting code!