The first time I wrote nuggets, I had read other people’s articles before, but this time I wanted to record the problems I encountered in the recent project and some of my own growth.

First, let’s briefly describe the technology selection of the recent project. The company upgraded the front-end technology two months ago, and all the subsequent projects will be developed using the mainstream framework. After doing three medium projects of VUE, there are some pit and climb the pit process. It is also a systematic summary of these three projects. If there are any shortcomings in the article, please communicate more in the comment area and learn from each other. I hope you can have some feelings and harvest after watching.

1. Project overview: VUE family bucket was used for development, but VUE - CLI was not used. As for the reasons, the following will be explained in detail. Ii. Project pits: After doing three medium-sized projects, the business logic layer did not step on any pits, the pits are mainly in the following aspectsCopy the code
  • Webpack4 + VUE Build configuration step pit
  • Webpack packaging performance detection and optimization
  • Involve permission system, front end to do a set of permission verification, generate dynamic routing table

1. Why not use vue-CLI scaffolding?

The main project of the company is still the most traditional jQ + PHP architecture. The coordinates of the Internet company in Imperial City are actually far from most Internet companies in terms of technology. Therefore, in the selection of new projects, as the only front end of the company, WE immediately decided to use VUE to do it, so as to truly achieve the separation of front and rear ends. If the main framework is determined, should WE use vue-CLI or vue+ WebPack? (The project schedule for the product is 5 days for development and testing, and 5 days for launch), and the time limit should be taken into account.

After careful consideration, I still choose to build by myself for the following reasons:

  1. You know what’s wrong with your custom scaffolding, so you can develop some front-end architecture
  2. More proficient in webPack configuration and webpack3.0 upgrade to 4.0
  3. If the project is later converted to server rendering (SSR), the configuration can be changed more quickly, which vue-CLI does not have

In addition to the above points, I personally think that whether we have the ability of webpack configuration is the standard to measure the level of a front-end, and THE author has interviewed many front-end devices, with three years of experience, almost few front-end devices that can webpage from 0 webpage, let alone performance optimization or write loader and plugin by ourselves.

2. Configure the WebPack section

Entry, Output, Loader, and plugins. This article is not about how to configure WebPack, so I won’t go over all of them. This is mainly to record the pits I stepped in the configuration process and the points worth summarizing.

Let’s take a look at some of the major differences between webpack3.0 and 4.0

1. Webpack4 must install webpack - 2 cli webpack4 Settings with a configuration mode, only two values development | production, to the different environment will provide 3 different some default configuration. Split individual modules using optimizations. SplitChunks instead of CommonsChunkPlugin 4. Extract a single CSS file using MiniCssExtractPlugin instead of extract-text-webpack-plugin 5. If you are developing a VUE project, the base configuration file must be imported into vue-loader/lib/plugin 6. Instead of compressing js files with UglifyJsPlugin, compress the code with optimization. Minimize set to true, which defaults to true 7 when mode is production. Introduced Tree Shaking, not packaging useless codeCopy the code

Those are the major updates for version 4.0, and there are many more. I’ve attached the official change log here

Note: The MiniCssExtractPlugin will just extract the CSS from JS into a separate CSS file, but it won't compress it. The CSS needs to be optimistic-csS-assets -webpack-plugin alone. And configure it in the Optimization optionCopy the code
optimization: {
    minimizer: [
      <! - compressing CSS - >
      new OptimizeCSSAssetsPlugin({
        assetNameRegExp: /\.css$/
      })
    ]
}
Copy the code

The general idea of project configuration is to configure different config.js according to different environments, and use webpack-merge to merge the basic configuration, package.json, and perform corresponding operations according to different commands. Look at the picture and say:

"dev": "webpack-dev-server --config build/webpack.dev.config.js"."build": "webpack --config build/webpack.prod.config.js"."build:dll": "webpack -p --progress --config build/webpack.dll.config.js"
Copy the code

3. Webpack Optimization

1. Webpack4 production mode comes with optimization

1. Tree Shaking

Tree Shaking is a term often used to move code that is referenced in Javascript at packaging time, and it depends on the static structure of imports and exports in the ES6 module system.

After a module is introduced during development, if only one of its functions is used, only the functions used will be packaged into the corresponding bundle during online packaging, and other useless functions will not be packaged, thus achieving the most basic optimization.

This is provided that the import and export syntax is used. What does that mean? This means that if a module uses ES6 imports and exports, it will be shaking up the code when it is packaged online; But! Note that if you are using require, an import and export of the commonJS specification, it will not be shaking.

Why won’t require modules be taken as shaking? The reason is that require is a dynamic import. When webPack is packaged, if the module is imported dynamically, it does not know if there is useless code in the imported module, so it will not be shaken up.

2. Scope power in the following hoisting cases

The use of scope collieries is to predict the results (precompile) of the relationships between modules, making webPack code files smaller and faster.

The principle of implementing scope colliers is quite simple: figure out the dependencies between the modules and try to merge as many as possible into a function without code redundancy, so only modules that have been referenced once can be combined.

As the scope colliers need to analyze the dependencies between modules, the source code must use ES6 module sentences, just like Tree Shaking.

3. Code compression

In production mode, the js code is compressed and extracted by default (SplitChunksPlugin).

2. Custom optimization

1. Use Loader as little as possible

Webpack packaging takes most of the time because of the loader precompilation phase, so use Loader as little as possible, as shown below

  • For example, if a less-loader is used in a project, skip the sass-Loader, stylus-loader, and use only one CSS preprocessor if possible
  • For example, the image loader, usually usedfile-loader.url-loader.img-loader. Buturl-loaderOfficial statement:url-loader works like file-loader, which meansurl-loaderSimilar to thefile-loader“Then stop using itfile-loader(unless the image is too large and exceeds the limit value configured in url-Loader)

2. Dynamic import (lazy loading)

By default, Webpack allows dynamic import of import syntax, but requires the plugin support of Babel, which is to add @babel/plugin-syntax-dynamic-import to the.babelrc configuration file

One of the biggest benefits of dynamic imports is lazy loading, which can increase the first-screen loading of SPA applications by loading whichever module is used

3. noParse

When we introduce some third-party modules, such as jQuery and Element-UI, we know that they will not rely on other modules internally, because we finally use only a single JS file, so it will be time-consuming for Webpack to parse the internal dependencies of jQuery.

I can add noParse under the Module node in the WebPack configuration file and configure the re to tell WebPack that I don’t need to parse the modules anymore

module: {
    noParse: /jquery|element-ui/
}
Copy the code

Here’s the catch: Element-UI is introduced on demand. Note that you can’t use noParse to optimize element-UI because an element introduced on demand has a set of internal dependencies that WebPack doesn’t parse with noParse

Now, let’s look at the optimization. The packing speed is almost four times faster

4. IgnorePlugin

The project uses element-ui and moment.js, both of which have a number of language packs built into them, especially moment.js. The language pack takes up a lot of space, and our project only needs the Chinese language pack, so we should ignore all the language packs and introduce them as needed to make the build more efficient and the package generated smaller files

  • First find out what language packs the third-party library depends on (in the package.json file of the third-party library, find the main entry file, and find the referenced language packs in the entry file).
  • Ignore its dependencies using the Webpack.ignoReplugin plug-in
  • Import dependent language packs as needed

Let’s take a look at the packaging time and the size of the DLL package, and the results are good

5. Improve performance by reducing file search scope

What do you mean by reducing the file search scope? This requires an understanding of the basics of WebPack. Webpack extracts third-party and public modules introduced into the project through configuration files, and each extracted module has an ID, which is mapped and searched in the main file referenced to the module. So if you can improve the speed of file search, there will be a certain improvement in webPack packaging performance.

  • A:resolve.modulesThe configuration tells WebPack which directories to search for when parsing a module.
import vue from 'vue'
import myCommonJs from '.. /src/myCommonJs'
Copy the code

The above code, which references third-party libraries and common JS, respectively, has a default WebPack configuration that packages references to search files recursively up the current path. Modules can be used to tell webPack that I’m going to look for both node_modules and SRC files.

  • Method 2: include & exclude

When you configure the Loader, you can specify the directory to be processed more precisely by configuring include and exclude, which reduces unnecessary traversal and thus performance penalty. This is the simpler way, and I won’t go into it here

6. The Happypack multiprocess is packaged and built

By default, webPack builds are single-process packages. When a Babel-Loader needs to process multiple resource files of different types, node’s single-process file reading feature can become performance consuming. This is where Happypack is used. However, it may be because the project size and file resources are relatively simple. By configuring Happypack, the author did not improve the actual packaging speed, but increased the speed by 2-3s. After that, 0 needs to be carefully studied.

7. Set the babel-Loader configuration item cacheDirectory to true

Once set, the given directory will be used to cache the results of the loader. The WebPack build will then attempt to read from the cache to avoid the potentially expensive Babel recompile process running every time it is run

8. DllPlugin and DllReferencePlugin

DllPlugin provides a dynamic link library package for WebPack. It is usually used to package third-party libraries whose versions do not need to be updated frequently. Provide a separate configuration file to package the dynamic link library (webpack.dll.config.js). Package the dynamic link library before generating environment packaging. After packaging, vendor_dll.js and vendor-manifest.json are generated. It contains a mapping from the import request to the module ID

DllReferencePlugin is used in the production environment configuration file (webpack.prod.config.js), where the manifest option requires DllPlugin to package the generated manifest.json file, Map the dependency names to the module IDS, and then use them as needed using the internal __webpack_require__ function

The main idea is to pre-package some of the unmodified dependencies so that we don’t need to package the code when we release it, thus saving packaging time

If this item is configured in actual projects, the packaging speed can be improved by 6-8s

The generated vendor_dll.js file must be manually added to the index.html or dynamically added to the HTML file using add-asset-html-webpack-plugin. 2. When add-asset-html-webpack-plugin is used to dynamically introduce the dynamic link library to generate js after mapping, because speed-measure-webpack-plugin is used to analyze the time when the environment is packaged and generated, resulting in a packaging error. The following error is reported: Guess should be two plug-in incompatible, there are big guy also encountered this kind of problem and solution, beg to shareCopy the code

9. Import third-party libraries by referring to CDN links

After the conclusion, there are many such summaries on the Internet. However, through self-configuration and through Webpack-bundle-Analyzer and speed-measured-webpack-plugin, we can observe the packaging performance and optimize the summary, which deepens our understanding of WebPack configuration and principle once again.