This is the 20th day of my participation in the August Text Challenge.More challenges in August

Loaders and plugins commonly used by Webpack

  • Loader
  • Css-loader: loads the CSS and supports features such as modularization, compression, and file import
  • Style-loader: Inserts CSS code into JavaScript and loads CSS via DOM manipulation
  • Postcss-loader: extends the CSS syntax and uses the next generation CSS. It can work with the autoprefixer plug-in to automatically complete the CSS3 prefix

-** babel-loader** : convert ES6 to ES5

  • 14. file-loader: To export files to a folder and reference the output file in code by a relative URL (processing images and fonts)
  • Url-loader: similar to file-loader except that you can set a threshold. If the threshold is greater than the threshold, the file will be processed by file-loader. If the threshold is smaller than the threshold, the file base64 encoding (processing images and fonts) will be returned.
  • Vue-loader: loads vue. js single file components
  • Loader provided by mini-CSS-extract-plugin: uses the link tag to import an external CSS file
  • Plugin
  • Html-webpack-plugin: Sets the template for rendering the page
  • Terser-webpack-plugin: Supports compression of ES6 (Webpack4)
  • Mini-css-extract-plugin: Separate style files, extract CSS into separate files, support on-demand loading
  • Clean-webpack-plugin: directory cleaning
  • Define-plugin: Defines environment variables
  • DllPlugin: This plug-in is used to create a DLL-only -bundle in a separate Webpack configuration. The plugin generates a file called manifest.json that is used to map the DllReferencePlugin to the dependencies

What is the difference between Loader and Plugin?

  • Loader is essentially a function that converts the received content and returns the converted result. Since Webpack only knows JavaScript, the Loader acts as a translator, preprocessing the translation of other types of resources. Loader is configured in module.rules as the parsing rule for modules. The type of Loader is array. Each item is an Object and contains properties such as test(type file), Loader, and Options.
  • Plugin is plug-in, based on the event flow framework Tapable, plug-in can extend the function of Webpack, in the life cycle of Webpack running will broadcast many events, Plugin can listen to these events. Change the output through the API provided by Webpack when appropriate. Plugins are configured separately in plugins, and are of type array. Each item is an instance of the Plugin, and the parameters are passed in through the constructor

The Webpack build process.

The process can be roughly divided into the following seven phases

  • Initialization parameters: Read and merge parameters from configuration files and Shell statements to arrive at the final parameters
  • Start compiling: Initialize the Compiler object with the parameters obtained in the previous step, load all configured plug-ins, and execute the object’s run method to start compiling
  • Identify entry: Locate all entry files according to the entry in the configuration
  • Compiling modules: 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 passed this step
  • Complete module compilation: After using Loader to translate all modules in Step 4, the final content of each module after translation and the dependencies between them are obtained
  • Output resources: assemble chunks containing multiple modules one by one according to the dependencies between entries and modules, and convert each Chunk into a separate file > add it to the output list. This step is the last chance to modify the output content
  • Output complete: After determining the output content, determine the output path and file name based on the configuration, and write the file content to the file system

Hot update principle for Webpack

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. The core of HMR is that the client pulls updated files from the server, namely chunk diff (the part of chunk that needs to be updated). In fact, WDS maintains a Websocket between the browser and WDS. When the local resources change, WDS pushes updates to the browser. With the build-time hash, let the client compare to the last resource. The client compares the difference and makes an Ajax request to WDS to get the change (file list, hash), which can then be used to make jSONP requests to WDS to get incremental updates of the chunk. What happens after you get the incremental update? Which states should be preserved? What needs updating?) This is accomplished by the HotModulePlugin, which provides apis for developers to handle their own scenarios, such as react-hot-loader and Vue-Loader, using these apis to implement HMR.

Optimization of Webpack builds

  • Use the latest version of Webpack. We do performance tuning on a regular basis. Keeping Node.js up to date also ensures performance. In addition, keeping your package management tools (such as NPM or YARN) up to date also ensures performance. Newer versions allow for more efficient tree of modules and faster parsing.
  • Apply loaders to the minimum number of necessary modules.
  • Code that changes infrequently is compiled separately using the DllPlugin. This will improve the compilation speed of reference programs, even if it adds complexity to the build process.
  • Reduce the overall size of compilations to improve build performance. Try to keep chunks small. – Use fewer/smaller libraries. – Use CommonsChunksPlugin in multi-page applications. – Use CommonsChunksPlugin in Async mode in multi-page applications. – Remove unused code. – Only compile the part of the code you are currently developing.
  • Use cache-loader to enable persistent caching. Use “postinstall” in package.json to clear the cache directory.
  • Basic package separation: Use htML-webpack-externals-plugin to import the base package through CDN without entering the bundle. SplitChunksPlugin is used to separate (common script, base package, page public file) (built-in Webpack4). Replaces the CommonsChunkPlugin
  • Multi-process/multi-instance builds: HappyPack(no longer maintained), Thread-loader

Webpack optimization of 2

  • Compress JS and CSS. Webpack compresses JS automatically by default. However, after CSS compression is configured, js compression is no longer automatic. You need to configure it manually. Plugins: CSS-minimizer-webpack-plugin and terser-webpack-plugin
    optimization:{
    	minimizer: [new CssMinimizerPlugin(),
    		new TerserPlugin()
     	]
    }
    Copy the code
  • Exclude: Use exclude to exclude files that do not need to be parsed to improve compilation speed. It is usually the node_modules directory
  • NoParse: Does not check whether the package contains other dependencies. This is used when a package has been explicitly introduced that does not contain other dependencies, such as jquery or Lodash.
  • Resolve. Alias: Define an alias, using an absolute path to speed up file lookup, which in turn speeds up WebPack compilation
  • Resolve. Extensions: omit file suffix [‘.vue’,’.js’] when importing files
  • Resolve. modules: Search in the specified directory to narrow the search scope and improve compilation speed
  • Webpack. ProvidePlugin: You can import libraries in modules without import or directly use them after configuration. For example, jquery can omit the import step after the following configuration
let webpack = require('webpack');
plugins:[
	new webpack.ProvidePlugin({
		$:'jquery'})]Copy the code
  • Some of the unnecessary files in the package, such as the moment library, are used to manipulate time and support multiple languages, but sometimes we may only use Chinese and English, so we can ignore files in other languages
  • Externals :{vue:” vue “// vue is a global variable that we import through the CDN, and vue is the ww} : external extension that we import from wW by importing xx from WW
  • SplitChunks: the subcontract
optimization:{
	splitChunks: {cacheGroups: {jq: {filename:'jq.js'.test:/jquery/
	}}}}
Copy the code
  • DllPlugin+DllReferencePlugin: The combination of the two can package files that are not modified or not modified often. The DllPlugin is used to package files in a separate configuration file and the DLLReferencePlugin is used to configure packaged package files in the main configuration file
// Separate configuration file
output: {
 	path: path.join(__dirname, "dist"),
 	filename: "MyDll.[name].js".library: "[name]_[fullhash]"
 },
 plugins: [
 	new webpack.DllPlugin({
 		path: path.join(__dirname, "dist"."[name]-manifest.json"),
 		name: "[name]_[fullhash]"})]// Master configuration file
plugins: [
 	new webpack.DllReferencePlugin({
 		context: path.join(__dirname, ".."."dll"),
 		manifest: require(".. /dll/dist/alpha-manifest.json") // eslint-disable-line
 	}),
 	new webpack.DllReferencePlugin({
 		scope: "beta".manifest: require(".. /dll/dist/beta-manifest.json"), // eslint-disable-line
 		extensions: [".js".".jsx""})"Copy the code

Handwritten loader

const parser =  require('@babel/parser');// You can convert js source code into an AST syntax tree
		const traverse = require('@babel/traverse').default // The AST node can be recursively traversed
		const generator = require('@babel/generator').default; // Convert the modified AST syntax tree into a source string
		const types = require('@babel/types') // Add, delete, and modify nodes
		module.exports = function(source){
		  const ast = parser.parse(source,{sourceType:'module'})
		  // console.log(ast.program.body);
		  traverse(ast,{
		    CallExpression(path){
		      // console.log(path)
		      if(types.isMemberExpression(path.node.callee) && types.isIdentifier(path.node.callee.object,{name:'console'})){
		        path.remove()
		      }  
		    }
		  })
		  const output = generator(ast,{},source);
		  return output.code
		}
Copy the code

Write a plugin

class Myplugin{
		 // a new file can be generated when repackaged
		  constructor(options){
		    // The new plugin is the parameter passed in
		    this.options = options
		  }
		  apply(compiler){
	      const hooks = compiler.hooks;
		  if(hooks){
		      hooks.emit.tap('myplugin'.function(complication,callback){
		        var str = 'The list of files is :\n';
		        for(let k in complication.assets){
		          str += 'File name:${k},,, size is${ complication.assets[k].size()} \n\n`
		        }
		        complication.assets['myfile.md'] = {
		          source(){
		            return str
		          },
		          size(){
		            return str.length
		          }
		        }
		        callback&&callback()
		      })
		    }else{
			      compiler.plugin('emit'.function(complication,callback){
			        var str = 'The list of files is :\n';
			        for(let k in complication.assets){
			          str += 'File name:${k},,, size is${ complication.assets[k].size()} \n\n`
			        }
			        complication.assets['myfile.md'] = {
			          source(){
			            return str
			          },
			          size(){
			            return str.length
			          }
			        }
			        callback&&callback()
			      })
			    }
		  }
	}
	module.exports = Myplugin
Copy the code