One, foreword

The react JSX code must be compiled before it can be used in the browser. Sass and less code are not supported by the browser. If you get rid of these frameworks, development efficiency drops dramatically.

Among many front-end engineering tools, WebPack stands out as the most popular front-end construction tool today.

The principle of Webpack

Know what you are and why you are.

1. Core Concepts (5)

  1. The **Entry** Entry indicates which file Webpack starts packing as the Entry point to analyze and build internal dependency diagrams.

  2. **Output** Indicates where resource bundles are exported after Webpack has been packaged.

  3. **Loader**Loader allows Webpack to handle non-JS files.

  4. Plugins can be used for packaging optimization and compression, redefining environment variables, and more.

  5. **Mode** instructs Webpack to use the configuration of the corresponding Mode. By selecting one of development, Production, or None to set the Mode parameter, you can enable the optimization built into Webpack for the corresponding environment.

2. Webpack Construction process (principle)

A sequence of steps from starting the build to producing the results:

(1) Initialization parameters: parse webpack configuration parameters, merge the parameters passed in by shell and configured by webpack.config.js file, and form the final configuration result.

(2) Start compiling: The parameter obtained in the previous step initializes the Compiler object and registers all configured plug-ins. The plug-in listens to the event node of the WebPack construction life cycle and makes corresponding responses. The run method of the object is executed to start compiling.

(3) Determine the entry: from the entry of the configuration, start parsing the file to build the AST syntax tree, find out the dependencies, and recurse down.

(4) Compiling modules: In recursion, according to the file type and Loader configuration, all configured Loaders are called to convert files, and then the module dependent on the module is found, and this step is recursed again until all the files dependent on the entry have been processed in this step.

(5) Complete module compilation and output: after the completion of recursion, get the result of each file, including each module and the dependencies between them, and generate code chunk according to entry configuration.

(6) Output complete: Output all chunks to the file system.

Note: there are a number of plug-ins in the build life cycle that do the right thing at the right time, such as UglifyPlugin that overwrites the results with UglifyJs compression after the Loader transforms recursively.

3. Service scenarios and corresponding solutions

1. Single page apps

A single page application needs to be configured with an entry indicating the execution entry. The WebPlugin in web-webpack-plugin can automatically complete these tasks: Webpack generates a chunk for entry that contains all the dependent files for the entry, but it also needs an HTML to load the CHUNK generated JS, and if the CSS is also extracted, it needs to import the extracted CSS into the HTML file.

A simple WebPack configuration file chestnut

const { WebPlugin } = require('web-webpack-plugin'); module.exports = { entry: { app: './src/doc/index.js', home: './src/doc/home.js' }, plugins: New WebPlugin({// The output HTML file filename: 'index.html', // This HTML dependency 'entry' requires: ['app','home'], }), ], };Copy the code

Require: [‘app’, ‘home’] specifies which entries this HTML depends on. The JS and CSS generated by the entry are automatically injected into the HTML.

You can also configure these resource injection modes. The following attributes are supported:

(1) _dist Resources introduced only in the production environment;

(2) _dev is a resource introduced only in the development environment;

(3) _inline inserts the content of the resource into the HTML;

(4) _ie Indicates the resource imported only by Internet Explorer.

These properties can be configured in js. Here is a simple example:

new WebPlugin({
    filename: 'index.html',
    requires: {
         app:{
              _dist:true,
              _inline:false,
         }
    },
}),
Copy the code

These properties can also be set in templates, which give you flexibility to control the injection point of resources.

New WebPlugin({filename: 'index.html', template: './template.html',}), //template <! DOCTYPE html> <html lang="zh-cn"> <head> <link rel="stylesheet" href="app? _inline"> <script src="ie-polyfill? _ie"></script> </head> <body> <div id="react-body"></div> <script src="app"></script> </body> </html>Copy the code

The WebPlugin plugin borrows ideas from FIS3 and complements the htML-centric functionality missing from WebPack. To learn more about WebPlugin, see the documentation.

2. Manage multiple single pages for a project

A project may contain multiple single-page applications. Although multiple single-page applications can be combined into one, this will cause parts of the project not accessed by the user to be loaded, if there are many single-page applications in the project. Configure an entry and WebPlugin for each one-page application? The AutoWebPlugin method in web-webpack-plugin can solve these problems. The AutoWebPlugin method in web-webpack-plugin can solve these problems.

Module.exports = {plugins: new AutoWebPlugin('./ SRC /'),]}; module.exports = {plugins: new AutoWebPlugin('./ SRC /'),]};Copy the code

1. AutoWebPlugin automatically configures a WebPlugin to output the corresponding HTML for all page entries by using each folder in the./ SRC/directory as a single page entry.

2. To add a new page, create a folder under./ SRC/containing the code that the single-page application depends on. AutoWebPlugin automatically generates an HTML file named the folder name.

3. Code separation optimization

A good code split makes a big difference to the browser’s first screen.

The most common React system:

React-dom redux redux redux react-dom redux redux react-dom redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux redux If you package the base library and the business code in a file every time you change the business code it changes the hash value of the file so that the cache is invalid and the browser repeatedly downloads the code that contains the base library. So package the base library into a file.

// the vender.js file is removed from the base library to a separate file to prevent the business code from being updated // the third party library that all pages depend on // react base import 'react'; import 'react-dom'; import 'react-redux'; // redux base import 'redux'; import 'redux-thunk'; // Webpack configuration {entry: {vendor: './path/to/vendor.js',},}Copy the code

(2) Through CommonsChunkPlugin, multiple code blocks can be extracted to form a single chunk. Extract common code for all pages in scenarios with multiple pages, reduce the code for a single page, and switch between pages when all common code has been loaded before without having to reload. So the CommonsChunkPlugin can extract the code that multiple code blocks depend on into a single chunk.

4. Build server render

Server-side rendering code should run on nodeJS. Unlike browsers, server-side rendering code should follow the CommonJS specification and should not include files other than JS such as CSS.

The Webpack configuration is as follows:

module.exports = {
  target: 'node',
  entry: {
    'server_render': './src/server_render',
  },
  output: {
    filename: './dist/server/[name].js',
    libraryTarget: 'commonjs2',
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
      },
      {
        test: /\.(scss|css|pdf)$/,
        loader: 'ignore-loader',
      },
    ]
  },
};
Copy the code

Analyze:

(1) Target: ‘node’ specifies that the built code should run in the Node environment.

(2) libraryTarget: ‘commonjs2’ indicates that output code is the CommonJS specification.

(3) {test: / \. (SCSS | | CSS PDF) $/, loader: ‘ignore – loader’} is to prevent cannot be executed in the node of files on the server side rendering is also used not be packaged in.

Fis3 migrated to WebPack

Fis3 has a lot in common with WebPack, but also a lot in common with WebPack: CommonJS specification, and a lot in different ways: how to import CSS non-JS resources.

Fis3 passes @require ‘./index.scss’, while webpack passes require(‘./index.scss’).

If you want to smoothly migrate FIS3 to Webpack, you can use comment-require-loader.

For example, you want to build in WebPack using the IMUI module with the FIS3 approach

loaders:[{
     test: /\.js$/,
     loaders: ['comment-require-loader'],
     include: [path.resolve(__dirname, 'node_modules/imui'),]
}]
Copy the code

4. Custom WebPack extensions

If you can’t find a solution for your application scenario in the community, you need to write your own loader or plugin. Before you write a custom Webpack extension you need to decide whether to be a Loader or a plugin. It can be judged as follows:

If your extension wants to convert individual files then write a loader and the rest is a plugin.Copy the code

Where the file conversion can be as follows:

1. Babel-loader converts ES6 to ES5.

2. File-loader replaces the file with the corresponding URL.

3. Raw-loader injects the text file content into the code.

1. Write webPack Loader

Loader is very simple to write, take comment-require-loader as an example:

module.exports = function (content) {
    return replace(content);
};
Copy the code

The loader entry needs to export a function that converts the contents of a file. The function receives the parameter Content as the string content of a file before conversion, and needs to return a new string content as the result of conversion. All files that are dumped through modularization will pass through the Loader. You can see from this that loader can only handle individual files and not code blocks. You can refer to the official documentation

2. Write the WebPack Plugin

Plugin is a bit more complicated because it is used in a wide range of scenarios. Take end-webpack-plugin as an example:

class EndWebpackPlugin { constructor(doneCallback, failCallback) { this.doneCallback = doneCallback; this.failCallback = failCallback; Plugin. plugin('done', (stats) => {this.donecallback (stats);}} apply(compiler) {// Monitor events in the webpack lifecycle and do the corresponding processing. }); compiler.plugin('failed', (err) => { this.failCallback(err); }); } } module.exports = EndWebpackPlugin;Copy the code

When the new EndWebpackPlugin() constructor is passed in, the plugin will be instantiated first, and then the plugin will be called by the apply method. The plugin listens for events in the WebPack life cycle in the Apply function and handles them accordingly.

The webPack Plugin has two core concepts:

(1) Compiler: There is only one compiler from webpack startup to exit, and compiler stores the configuration of Webpack.

(2) Compilation: Due to webpack’s automatic compilation mechanism that listens for file changes, compilation means one compilation.

Both Compiler and Compilation broadcast a series of events. There are a lot of events in the WebPack life cycle

This is just a simple demo. For more complex examples, see How to Write a Plugin or see the Web-webpack-plugin.

Five, the summary

Webpack is actually quite simple, summed up in one sentence essence:

Webpack is a tool to package modular JS, convert files by loader, and extend functionality by plugin.Copy the code

If WebPack is confusing to you, it’s because of the various Loaders and plugins.

Six, some questions

1. How is Webpack different from Grunt and gulp?

Grunt and Gulp were popular in the early days. Webpack is relatively mainstream now, but gulp is still used for some lightweight tasks, such as packaging CSS files separately.

Grunt and gulp are based on tasks and streams (tasks, streams). Similar to jQuery, find a file (or a class of files) and do a series of chain operations on it to update the data on the stream. The chain operations constitute a single task, and multiple tasks constitute the entire Web build process.

Webpack is portal based. Webpack will automatically recursively parse all the resource files that need to be loaded by the entry, then use different loaders to process different files, and use Plugin to extend WebPack functionality.

Summary: (1) From the construction idea: Gulp and Grunt require developers to divide the whole front-end construction process into multiple ‘tasks’ and reasonably control the call relationship of all’ tasks’. Webpack requires developers to find the entry point and know which Loader to use for different resources to parse and process.

(2) Knowledge background: Gulp is more like the thinking of back-end developers, so we need to be familiar with the whole process. Webpack is more inclined to the thinking of front-end developers.

2. What other tools are similar to WebPack? Talk about why you ultimately chose (or abandoned) Webpack.

There are also several major portal based packaging tools: WebPack, rollup, and Parcel.

From the perspective of application scenarios :(1) webpack is suitable for the construction of large and complex front-end sites; (2) Rollup is suitable for basic library packaging, such as vue, React; (3) Parcel is good for simple lab projects, but packing errors can be difficult to debug.

3. What are the common loaders? What problems do they solve?

(1) Babel-loader: convert ES6 to ES5;

(2) CSS-loader: load CSS, support modularization, compression, file import and other features;

(3) style-loader: the CSS code into JS, through DOM operation to load CSS;

(4) eslint-loader: checks js code with ESLint;

(5) image-loader: load and compress images at night;

(6) file-loader: output files to a folder, and reference the output files through the relative URL in the code;

(7) URl-loader: similar to file-loader, the content of files can be base64 injected into the code when the file is small.

(8) source-map-loader: load additional source map files for easy debugging.

4. What are the common plugins? What problems do they solve?

(1) UglifyJs-webpack-plugin: Compress JS code by uglifyJS;

(2) Commons-chunk-plugin: extract common code;

(3) define-plugin: Define environment variables.

5. Differences between Loader and plugin

(1) Loader makes Webpack have the ability to load and parse non-JS; (2) Plugin can extend the function of Webpack, in the running cycle of Webpack will broadcast a lot of events, Plugin can listen to some events, through the WEBpack API change the result.

Different usage :(1) loader is configured in module.rule. The type is array, and each item is Object; (2) Plugin is configured separately and is of type array. Each item is an instance of plugin, and the parameters are passed in through the constructor.

6. What is the webPack build process? The process from reading configuration to output file is as complete as possible

The running flow of Webpack is a sequential process, from start to finish:

(1) Initialization parameters: read and merge parameters from configuration files and Shell statements to get the final parameters;

(2) Start compiling: initialize the Compiler object using the parameters obtained in the previous step, load all the configured plug-ins, and execute the run method of the object to start compiling;

(3) Determine the entry: find out all the entry files according to the entry in the configuration;

(4) Module compilation: Starting from the entry file, call all configured Loader to translate the module, find out the module that the module depends on, and then recurse this step until all the entry dependent files have gone through this step;

(5) Complete module compilation: After using Loader to translate all modules in step 4, obtain the final content of each module after translation and the dependency between them;

(6) Output resources: according to the dependency between the entry and modules, assemble chunks containing multiple modules one by one, and then convert each Chunk into a separate file and add it to the output list. This step is the last chance to modify the output content.

(7) Output completion: After determining the output content, determine the output path and file name according to the configuration, and write the file content to the file system.

In the above process, Webpack will broadcast a specific event at a specific point in time, the plug-in will execute a specific logic after listening for the event of interest, and the plug-in can call the API provided by Webpack to change the running result of Webpack.

7. Have you written Loader and Plugin? Describe the idea of writing a Loader or plugin?

When writing a Loader, follow a single principle. Each Loader does only one “escape” job. Each Loader retrieves the content of the source file, which can be output by returning a value, or it can call this.callback() to return the content to Webpack. You can also use this.async() to generate a callback function and use this callback to output the processed content.

Plugin writing is much more flexible. Webpack broadcasts a number of events during its run life, and the Plugin can listen for these events and change the output when appropriate through the API provided by WebPack.

8. How does webpack’s hot update work? How does that work?

Hot updates to Webpack are also known as Hot Module Replacement, or HMR. This mechanism allows you to replace the old module with the new one without refreshing the browser.

Principle:

Analysis:

(1) In the first step, in Webpack’s Watch mode, when a file in the file system is modified, Webpack detects the file changes, recompiles and packages the module according to the configuration file, and saves the packaged code in memory through simple JavaScript objects.

(2) The second step is the interface interaction between Webpack-dev-server and Webpack. In this step, it is mainly the interaction between Webpack-Dev-middleware of Dev-server and Webpack. Webpack-dev-middleware calls the API exposed by Webpack to monitor code changes and tells Webpack to pack the code into memory.

(3) The third step is a monitoring of file changes by Webpack-dev-server, which is different from the first step and does not monitor code changes and repackaging. . When we are in the configuration file is configured with devServer watchContentBase to true, the Server will listen to these configuration static files in the folder change, change will notify the browser after the live for the application to reload. Notice that this is browser refresh, and HMR are two different things.

(4) The fourth step is also the work of webpack-dev-server code, this step is mainly through sockJS (webpack-dev-server dependency) between the browser and server to establish a websocket long connection, This tells the browser about the status of the various stages of the Webpack compilation and packaging, as well as the information that the Server listens for static file changes in step 3. The browser performs different operations based on these socket messages. Of course, the most important information passed by the server is the hash value of the new module, and the subsequent steps use this hash value to perform module hot replacement.

(5) The webpack-dev-server/client does not request updated code, and does not perform hot module operations, which are handed back to Webpack. The job of webpack/hot/dev-server is to decide whether to refresh the browser or hot update the module based on the information passed to it by webpack-dev-server/client and the configuration of dev-server. Of course, if you just refresh the browser, there are no further steps.

(6) HotModuleReplacement. The runtime is the centre of the client HMR, step on it receives hash value passed to his new module, it through JsonpMainTemplate. Runtime sends an Ajax request to the server end, The server returns a JSON that contains the hash values of all the modules to be updated. Once the updated list is retrieved, the module requests the latest module code again via JSONP. These are steps 7, 8 and 9 in the figure above.

(7) Step 10 is the key step to determine the success of HMR. In this step, HotModulePlugin will compare the old and new modules and decide whether to update the module. After the decision of updating the module, check the dependency relationship between the modules and update the dependency references between the modules.

(8) In the last step, when HMR fails, fall back to live Reload, that is, do a browser refresh to get the latest packaging code.

9. How to use Webpack to optimize front-end performance? (Improved performance and experience)

Optimizing front-end performance with WebPack means optimizing the output of WebPack so that the packaged end result runs quickly and efficiently in the browser.

(1) Compress the code. Remove unnecessary code, comments, simplify code writing, and so on. Webpack UglifyJsPlugin and ParallelUglifyPlugin can be used to compress JS files, using CSSNano (CSS-loader? Minimize to compress CSS. With Webpack4, packaging projects in Production mode will automatically turn on code compression.

(2) CDN acceleration. During the build process, the referenced static resource path is changed to the corresponding path on the CDN. The resource path can be modified using the Webpack for the output parameter and the publicPath parameter of each loader

(3) Tree Shaking Remove pieces of code that never go anywhere. This can be done by appending the parameter optimize-minimize when starting webpack or by using the ES6 module to enable the removal of dead code.

(4) Optimize the picture, for the small picture can use base64 way to write into the file

(5) Split the code according to the route to achieve on-demand loading and extract the common code.

(6) add hash to the packaged file name to realize the browser cache file

10. How to speed up webPack construction?

(1) In the case of multiple entries, use commonsChunkPlugin to extract common code;

(2) Extract common libraries through externals configuration;

(3) Use happypack to achieve multi-threaded accelerated compilation;

(4) Use Webpack-Uglify-Parallel to improve the compression speed of uglifyPlugin. In principle, Webpack-Ugli-fi parallel uses multi-core parallel compression to improve compression speed.

(5) Use tree-shaking and scope compensation to remove redundant code.

11. How to configure a single page application? How to configure a multi-page application?

Single-page applications can be understood as the standard mode of WebPack, directly in entry to the order page application entry.

For multi-page applications, webPack’s AutoWebPlugin can be used for simple, automated builds, but only if the project’s directory structure complies with its preset specifications.

12. What should BE paid attention to when packaging NPM? How can WebPack be used for better builds?

Note the following issues for the NPM module:

(1) To support the CommonJS modularity specification, require that the packaged final result also comply with this rule

(2) The environment of the Npm module user is uncertain and probably does not support ES6, so the final result of the package should be written in ES5. And if ES5 is converted, you’d better upload it with SourceMap.

(3) Npm package size should be as small as possible (some warehouses will limit package size)

(4) Published modules can not be packaged with dependent modules, users should selectively install them. This prevents the underlying module from being repackaged by the module user.

(5) UI component modules should rely on other resource files, such as.css files should also be included in the published module.

Based on the above considerations, we can make the following extensions and optimizations to the WebPack configuration:

** Set output.libraryTarget=’commonjs2’** set output.libraryTarget=’commonjs2’** Set output.libraryTarget=’commonjs2′

(2) Output ES5 code solution: use Babel-Loader to convert ES6 code into ES5 code. Publish debugging by turning on devtool: ‘source-map’ to print SourceMap.

(3) Solution of Npm package size as small as possible: Babel will inject some auxiliary functions when converting ES6 code into ES5 code, which will eventually result in each output file containing the code of this auxiliary function, resulting in code redundancy. The solution is to modify the. Babelrc file and add transform-Runtime to it

(4) The solution to not packing dependent modules into NPM modules: Use the externals configuration item to tell WebPack which modules do not need to be packed.

(5) For the solution of dependent resource file packaging: through CSS-loader and extract-text-webpack-plugin, configuration is as follows:

How to implement load on demand in VUE project?

Libraries of off-the-shelf UI components such as ElementUI, iView, and so on are often introduced, but their size, as well as the functionality they provide, are enormous.

However, many component libraries already provide ready-made solutions, such as Element’s babel-plugin-Component and AntDesign’s babel-plugin-import. Set this parameter in the. Babelrc configuration or in the babel-loader parameter to load components on demand.

At present, many front-end projects are developed by single-page application, but with the continuous expansion of business, it will face a serious problem — the amount of code loaded for the first time will become more and more, affecting the user experience.

Seven, reference

1, github.com/webpack/doc…

2, webpack.js.org/api/compile…

3, webpack.js.org/concepts/lo…

4, webpack.js.org/concepts/pl…

5, hand in hand teach you a simple webpack