Perception: 🌟🌟🌟🌟🌟

Taste: Steamed sea bass

Cooking time: 15 minutes


This article is available on Github github.com/Geekhyt.

From the depth of her hair and her brisk walk, I could tell that the interviewer in front of me was a good one, too. As usual, I’m going to take three minutes to introduce myself. During this time, my eyes were attracted by the 16-inch MacBook Pro. I was fully prepared for this self-introduction and was confident to conquer the interviewer. As I expected, the interviewer was drawn to my area of expertise.

You’re familiar with Webpack, so I’ll give you a quiz

0. What are the common loaders? Which loaders have you used?

(I began to name the dishes familiar)

  • Raw-loader: Loads the original content of the file (UTF-8)

  • File-loader: Outputs a file to a folder and references the output file (images and fonts) in code using a relative URL.

  • Url-loader: Similar to file-loader, the difference is that the user can set a threshold. If the threshold is greater than the threshold, the file is processed by file-Loader. If the threshold is smaller than the threshold, the base64 encoding of the file is returned (processing images and fonts).

  • Source-map-loader: Loads additional source map files to facilitate breakpoint debugging

  • Svg-inline-loader: Injects compressed SVG content into the code

  • Image-loader: loads and compresses image files

  • Json-loader loads json files (included by default)

  • Handlebars – Loader: Compiles the Handlebars template into a function and returns it

  • Babel-loader: converts ES6 to ES5

  • Ts-loader: converts TypeScript to JavaScript

  • Awesome -typescript-loader: Converts typescript to JavaScript for better performance than TS-loader

  • Sass-loader: converts SCSS/SASS code to CSS

  • Css-loader: loads the CSS and supports features such as modularization, compression, and file import

  • Style-loader: Injects CSS code into JavaScript and loads the CSS using DOM operations

  • Postcss-loader: Extends the CSS syntax and uses the next generation CSS. It can work with the autopreFixer plug-in to automatically complete CSS3 prefixes

  • Eslint-loader: Checks JavaScript code with ESLint

  • Tslint-loader: Checks TypeScript code with tsLint

  • Mocha-loader: Loads the code for the Mocha test case

  • Coverjs-loader: calculates the test coverage

  • Vue-loader: loads the vue. js component in a single file

  • I18n – loader: internationalization

  • Cache-loader: Can be added before some performance expensive loaders to cache results to disk

For more Loader information, see the official website

(Interviewer: Good, I know quite a lot.)

1. What are the common plugins? What plugins have you used?

(This big brother seems to listen to addiction, continue to open the regular operation)

  • Define -plugin: define environment variable (mode will be automatically configured after Webpack4)

  • Ignore-plugin: ignores some files

  • Html-webpack-plugin: Simplifies HTML file creation (relies on HTmL-loader)

  • Web-webpack-plugin: Easy to output HTML for single-page applications, better than HTmL-webpack-plugin

  • Uglifyjs-webpack-plugin: ES6 compression is not supported (before Webpack4)

  • Terser-webpack-plugin: Supports compression for ES6 (Webpack4)

  • Webpack-parallel-uglify-plugin: Multiprocess code compression for faster builds

  • Mini-css-extract-plugin: Separate style files and CSS extracts into separate files, supporting on-demand loading (instead of extract-text-webpack-plugin)

  • Serviceworker-webpack-plugin: adds offline caching to web applications

  • Clean-webpack-plugin: cleans directories

  • ModuleConcatenationPlugin: open the Scope Hoisting

  • Speed-measure-webpack-plugin: You can see the execution time of each Loader and plugin (overall packaging time, each plugin and Loader time)

  • Webpack-bundle-analyzer: Visualizes the volume of webPack output files (business components, dependent third-party modules)

Please refer to the website for more plugins

(Double Kill)

2. What is the difference between Loader and Plugin?

(I knew you’d ask, but I covered my smile with my hands)

Loader is essentially a function that converts the received content and returns the converted result. Because Webpack only knows JavaScript, the Loader acts as a translator, preprocessing other types of resources for translation.

Plugins are plugins that extend Webpack functionality based on the event flow framework Tapable. Plugins can listen for events that are broadcast during the life of Webpack. Change the output using the APIS provided by Webpack when appropriate.

Loader is configured in module.rules as the module resolution rule. The type is array. Each entry is an Object containing properties such as test(type file), Loader, and options (parameter).

Plugins are individually configured in an array of types, each of which is an instance of the Plugin, and arguments are passed in through the constructor.

3.Webpack build process

The running process of Webpack is a serial process. From start to finish, the following processes are executed in sequence:

  • Initialization parameters: Read and merge parameters from configuration files and Shell statements to produce the final parameters

  • Start compiling: The Compiler object is initialized with the parameters obtained in the previous step, all configured plug-ins are loaded, and the run method of the execution object starts compiling

  • Determine entry: Find all entry files based on the entry in the configuration

  • Module compilation: Start from the entry file, call all configured loaders to translate the module, then find out the module that the module depends on, and then recurse this step until all the entry dependent files have been processed by this step

  • Completion of module compilation: After all modules are translated by Loader in step 4, the final content of each module after translation and the dependencies between them are obtained

  • Output resources: Assemble chunks of modules based on the dependencies between the entries and modules, and convert each Chunk into a separate file to add to the output list. This is the last chance to modify the output

  • Output completion: After the output content is determined, the output path and file name are determined according to the configuration, and the file content is written to the file system

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

In a nutshell

  • Initialization: Start the build, read and merge configuration parameters, load Plugin, and instantiate Compiler

  • Compile: Start from Entry, call the corresponding Loader serial for each Module to translate the contents of the file, and then find the Module that this Module depends on, and compile recursively

  • Output: The compiled modules are combined into chunks, the chunks are converted into files, and the files are output to the file system

For those interested in the source code, check out another of my columns about how WebPack4.x works from the source code

4. What plugins have you used to improve productivity while developing with WebPack?

(This question is also quite pay attention to the practical, the user’s experience or to start from childhood)

  • Webpack-dashboard: more user-friendly presentation of packaging information.

  • Webpack-merge: Extract common configuration to reduce duplication of configuration code

  • Speed-measur-webpack-plugin: SMP analyzes the time spent by the Loader and plugin during the WebPack packaging process, helping to identify performance bottlenecks during the build process.

  • Size-plugin: Monitors resource volume changes to detect problems early

  • Hot replacement HotModuleReplacementPlugin: module

5. What is the source map? How to use it in production environment?

Source Map is the process of mapping compiled, packaged, and compressed code back to source code. The packaged compressed code is not readable, and soucre Map is needed to debug the source code.

The map file is not loaded by the browser unless the developer tools are open.

There are generally three solutions for online environments:

  • Hidden-source-map: Used with the third-party error monitoring platform Sentry

  • Nosource-source-map: Displays only the exact number of lines and the error stack for viewing source code. Higher security than sourcemap

  • Sourcemap: Nginx sets the.map file to be open only to white lists (Intranet)

Note: Avoid using inline- and eval- in production, as they increase the bundle size and degrade overall performance.

6. Do you know the module packing principle?

Webpack actually creates an environment for each module that can be exported and imported, essentially without modifying the execution logic of the code, which is executed in exactly the same order as the module was loaded.

7. How does file listening work?

When a change is detected in the source code, the new output file is automatically rebuilt.

There are two ways to enable listening mode in Webpack:

  • Start the webpack command with the –watch parameter
  • Set watch:true in configuring webpack.config.js

Cons: You need to manually refresh the browser each time

Principle: Polling to determine whether the last editing time of a file has changed. If a file has changed, the system does not immediately notify listeners. Instead, the system caches the file and executes the file after aggregateTimeout.

module.export = {

// The default value is false

watch: true.

// watchOptions is only meaningful if the listening mode is enabled

watchOptions: {

// Default is empty, do not listen to files or folders, support regular match

ignored: /node_modules/.

// Wait 300ms before executing. Default: 300ms

aggregateTimeout:300.

// The default value is 1000 times per second. // The default value is 1000 times per second

poll:1000

}

}

Copy the code

8. How Webpack’s hot update works

(Knock on the blackboard, this question must be taken)

Hot update of Webpack is also called Hot Module Replacement, abbreviated as HMR. This mechanism makes it possible to replace old modules with new ones without refreshing the browser.

The core of HMR is that the client pulls the chunk diff from the server. In fact, WDS maintains a Websocket between the browser and WDS. When the local resource changes, WDS pushes the update to the browser. With the build time hash, the client is compared to the last resource. The client then makes an Ajax request to WDS to retrieve the changes (file list, hash). The client then uses this information to make a JSONP request to WDS to obtain the incremental update of the chunk.

What happens when you get the incremental update? Which states should be retained? Which ones need updating?) This is done by the HotModulePlugin, which provides apis for developers to handle their own scenarios. React-hot-loader and Vue-Loader implement HMR using these apis.

For details, see Webpack HMR Principle analysis

(Interviewer: Not bad, the young man has good expression ability)

(Do not 6)

9. How do I monitor and analyze the bundle volume?

There is a plug-in Import Cost in VSCode that can help you monitor the size of imported modules in real time. You can also use Webpack-Bundle-Analyzer to generate a module composition diagram of a bundle to show the size of the bundle.

The Bundlesize toolkit enables automated resource volume monitoring.

10. What is a file fingerprint? How does it work?

The file fingerprint is the suffix of the output file name after the package.

  • Hash: Related to the entire project build, the Hash value of the entire project build changes whenever the project file is modified

  • Chunkhash: Related to the chunk that is packaged by Webpack, different entries produce different Chunkhash

  • Contenthash: Hash is defined according to the file content. If the file content does not change, the Contenthash does not change

JS file fingerprint Settings

Set the output filename to chunkhash.

module.exports = {

entry: {

app: './scr/app.js'.

search: './src/search.js'

},

output: {

filename: '[name][chunkhash:8].js'.

path:__dirname + '/dist'

}

}

Copy the code

The file fingerprint Settings of the CSS

Set the filename of MiniCssExtractPlugin to contenthash.

module.exports = {

entry: {

app: './scr/app.js'.

search: './src/search.js'

},

output: {

filename: '[name][chunkhash:8].js'.

path:__dirname + '/dist'

},

plugins: [

new MiniCssExtractPlugin({

filename: `[name][contenthash:8].css`

})

]

}

Copy the code

File fingerprint Settings for pictures

Example Set the name of file-loader to hash.

Placeholder name and meaning

  • Extension name of ext resource
  • Name File name
  • Path Relative path of the file
  • Folder Specifies the folder where the file resides
  • Contenthash Hash the contents of the file, which is generated by MD5 by default
  • Hash Hash of the contents of a file. The default value is MD5
  • Emoji A random emoj that refers to the content of a file
const path = require('path');



module.exports = {

entry: './src/index.js'.

output: {

filename:'bundle.js'.

path:path.resolve(__dirname, 'dist')

},

module: {

rules: [{

test:/\.(png|svg|jpg|gif)$/.

use: [{

loader:'file-loader'.

options: {

name:'img/[name][hash:8].[ext]'

}

}]

}]

}

}

Copy the code

11. In practical projects, it is common to have hundreds of lines of configuration files. How do you ensure that each loader works as expected?

You can use Enforce to enforce the order of action of loaders. Pre means before all normal loaders, and POST means after all loaders. (Inline is not recommended officially)

12. How to optimize Webpack build speed?

(This is like saying “What happened from the URL input to the page display”)

(I just want to say: How long do you want me to talk?)

(Interviewer:…)

  • Use higher versions of Webpack and Node.js

  • Multi-process/multi-instance build: HappyPack(not maintained), thread-loader

  • The compression code

    • Multi-process parallel compression
      • webpack-paralle-uglify-plugin
      • Uglifyjs-webpack-plugin enables parallel argument (ES6 not supported)
      • Terser-webpack-plugin enables the parallel argument
    • Use the mini-css-extract-plugin to extract the CSS code from the Chunk into a separate file, and use the minimize option of csS-loader to enable CSsnano to compress the CSS.
  • Image compression

    • Use Imagemin based on the Node library (many customization options, can handle a variety of image formats)
    • Configuration image – webpack – loader
  • Reduce the packaging scope:

    • Exclude /include (determine the scope of the Loader rule)
    • Resolve.modules specifies the absolute path to third-party modules (reducing unnecessary looups)
    • Resolve. MainFields only uses the main field as the entry file description field (reduces the search step, needs to consider the entry file description field of all third-party modules that the runtime depends on).
    • Resolve. Extensions minimize the possibility of suffix attempts
    • NoParse ignores libraries that do not need to be parsed at all (not parsed but still packaged into bundles, note that omitted files should not contain modular statements such as import, require, define, etc.)
    • IgnorePlugin (completely exclude modules)
    • Use Alias properly
  • Extract page public resources:

    • Base package separation:
      • Html-webpack-externals-plugin is used to introduce the base package through CDN, not into the bundle
      • Use SplitChunksPlugin (built-in to Webpack4) to separate (common scripts, base packages, and page common files) instead of CommonsChunkPlugin
  • DLL:

    • Using the DllPlugin for subcontracting and using the DllReferencePlugin(index link) for referencing manifest.json, the code that is basically unchanged is packaged as a static resource first, avoiding the time of repeated compilation.
    • HashedModuleIdsPlugin can solve the module digital ID problem
  • Make full use of cache to speed up the secondary build:

    • Babel-loader Enables cache
    • The terser-webpack-plugin enables caching
    • Use the cache-loader or hard-source-webpack-plugin
  • Tree shaking

    • During the packaging process, modules that are not referenced in the project are detected and marked, and they are removed from the final bundle when resources are compressed (only valid for ES6 Modlue). ES6 Module modules are used as much as possible in development to improve the efficiency of tree shaking
    • Disable module dependency resolution for Babel-Loader, otherwise Webpack will receive converted CommonJS modules without tree-shaking
    • Use PurifyCSS(not maintained) or uncss to remove unwanted CSS code
      • Use purgecss-webpack-plugin with Mini-css-extract-plugin (recommended)
  • Scope hoisting

    • The code that is built will have a large number of closures, resulting in an increase in size, more scope for functions to be created while the code is running, and a high memory overhead. Scope reactically put all module code in a function Scope in reference order, then rename some variables appropriately to prevent variable name conflicts
    • In order to fully use Scope collieries, you need to configure mainFields to use ES6 modularized syntax as directed in JsNext: Main for third-party modules
  • Dynamic Polyfill

    • You are advised to use the polyfill-service to return only the required polyfill to the user and maintain the community. (Part of the domestic browser UA may not be recognized, but can be degraded to return all the required polyfill)

See the website – Build Performance for more optimizations

13. You mentioned code segmentation, what is the nature of code segmentation? What’s the point?

The essence of code splitting is the middle ground between the extremes of going live directly and packaging the source code into a unique script, main.bundle.js.

Akari: Glory sword down, balance in chaos

An acceptable increase in server performance in exchange for a better user experience.

Source code directly online: although the process is controllable, but HTTP requests, performance overhead.

Package as a unique script: one shuttle is cool, the server pressure is low, but the page blank period is long, the user experience is bad.

(Easy peezy right)

14. Has the Loader been written? How to write a loader?

Loaders support chained calls, so the development needs to follow a strict “single responsibility”, with each Loader only responsible for what it needs to do.

You can check the Loader API on the official website

  • Loader runs in Node.js, and we can invoke any of the node.js apis or install third-party modules
  • The content that Webpack passes to Loader is a string encoded in UTF-8 format. In some scenarios, when Loader processes binary files, it needs to tell Webpack whether the Loader needs binary data by exports.raw = true
  • Make loaders as asynchronous as possible, or synchronize if the computation is small
  • Loaders are stateless and we should not keep state in loaders
  • Use the utilities provided for us by Loader-utils and Schema-utils
  • Load the local Loader method
    • Npm link
    • ResolveLoader

15. Have you written a Plugin? A brief description of how to write a Plugin?

Webpack broadcasts a number of events throughout its life cycle, and the Plugin can listen for these events to hook in any custom functionality it wants to add at certain stages. Webpack’s Tapable event flow mechanism ensures the order of plug-ins and makes the whole system extensible.

The Plugin API can be found on the official website

  • Compiler exposes hooks that are relevant throughout the Webpack lifecycle
  • Compilation exposes less granular event hooks related to modules and dependencies
  • The plug-in needs to bind the Apply method to its prototype in order to access the Compiler instance
  • The Compiler and Compilation objects passed to each plug-in are the same reference, and changing their properties in one plug-in can affect subsequent plug-ins
  • Find the appropriate event points to accomplish the desired function
    • When the Emit event occurs, the final output resource, code block, module and its dependencies can be read and modified (the Emit event is the last time to modify the Webpack output resource)
    • Watch-run is triggered when the dependent file changes
  • Asynchronous events need to call the callback function to notify Webpack to proceed to the next process when the plug-in has finished processing the task, otherwise they will get stuck

16. Tell us how Babel works

While most JavaScript Parsers follow the Estree specification, Babel was originally based on the Acorn project (a lightweight modern JavaScript Parser).

  • Parse: Convert the code to an AST
    • Lexical analysis: Split code (strings) into token streams, which are arrays of syntactic units
    • Parsing: Analyzing the token stream (the array generated above) and generating the AST
  • Transformation: Nodes accessing the AST perform transformation operations to produce a new AST
    • Taro is a small program syntax transformation using Babel
  • Generate: Generate code based on the new AST

If you want to learn how to implement a compiler step by step, you can use the open source project the super-tiny-Compiler, which is featured on Babel’s website

Interviewer :(I’m thirsty. Let’s take a break for the second half.)

The interviewer picked up the cool longjing nearby and took a drink.

(This guy’s got something)

Keep updating…

reference

  • Webpack is easy to understand

  • Webpack of actual combat

  • How to play the Webpack

❤️ love triple strike

1. If you see here, please click under the support of “watching”. Your “watching” is the motivation of my creation.

2. Pay attention to the public number front canteen, “your front canteen, remember to eat on time”!

3. github.com/Geekhyt, thanks Star.