plugin

The principle of

The Webpack plug-in is a JS object with the Apply method, which is called by the Webpack Compiler and is accessible throughout the compiler life cycle.

How it works: Extends functionality by mounting functions in lifecycle hooks.

The life cycle is the key point in the whole life process.

A custom plugin

A hook is a function, a lifecycle function, buried in advance where functionality can be added.

There are 40-50 hooks on the official website. Here are a few key hooks

hook describe type
environment Environment ready SyncHook
compile Compile the start SyncHook
compilation Compile the end SyncHook
emit Package resources before output SyncSeriesHook
afterEmit After the resource is packaged to output SyncSeriesHook
done Packaging complete SyncHook
const pluginName = 'MyWebpackPlugin'; Class MyWebpackPlugin {// Compiler object is the Webpack compiler object apply(Compiler){// The first argument to the tap function in hook is the plug-in name PluginName, compilation => {console.log(" The webpack build process begins!" )}}}Copy the code

The characteristics of the plugin

  • Is a separate module
  • The module exposes a JS function
  • The prototype of the function defines an Apply method that is injected into the Compiler object
  • The Apply function requires a Webpack event hook that is mounted via the Compiler object. The hook callback can be used to retrieve the compilation object currently compiled, or the callback if the plug-in is compiled asynchronously
  • Complete the custom subcompilation process and process the internal data for the Complition object
  • If the plug-in is compiled asynchronously, the callback is executed after the data processing is complete

loader

The characteristics of the loader

  • Loader is essentially an ESM module that exports a function in which packaged resources are converted

  • The loader must return a javascript code so that eval can be executed. Otherwise, an error will be reported.

Loader execution sequence

When multiple Loaders are configured, the execution sequence of loaders is from right to left. The execution result on the right is sent to the left as a parameter.

Less-loader converts less to CSS and sends it to CSS-loader. Css-loader sends the result to style-loader. Style-loader returns a javascript code string. {test:/\.less$/,
    use:[
        'style-loader'.'css-loader'.'less-loader']}Copy the code

Array object, or by default, bottom to top

module: {
    rules: [{test: /\.less$/,
        use: 'style-loader'
      },
     {
        test: /\.less$/,
        use: 'css-loader'
      },
     {
        test: /\.less$/,
        use: 'less-loader'}}]Copy the code

How to ensure that each loader works as expected?

You can use Enforce to execute the sequence of loaders. Pre indicates that this command is executed before all normal loaders, and POST indicates that this command is executed after all Loaders. (Not recommended for inline officially)

You can use a Enforce attribute, which defaults to the following values

  1. Pre priority processing
  2. Normal Normal processing (default)
  3. Inline secondary processing
  4. Post final processing

Use of Enforce:

module: {
    rules: [{test: /\.less$/,
        use: 'less-loader'.enforce: 'pre'
      },
     {
        test: /\.less$/,
        use: 'css-loader'
      },
     {
        test: /\.less$/,
        use: 'style-loader'.enforce: 'post'}},Copy the code

Custom loader

Loader-utils Obtains the option of the Loader configuration item

For example, declare a loader that reads the contents of a Markdown file. cosnt {getOptions} =require('loader-utils')
const marked = require('marked')
module.exports = function(source){
    
    // Get loader configuration options
    const options =  getOptions(this)
    
    // Process the input
    const html = marked(source)
    // Return to the next loader for processing. If not, make sure to return js code
    return html
    
}
Copy the code
Module. exports= function(source) {return 'module.exports=${source}'; }Copy the code
  • When you define a loader, the loader function takes only one argument, which is a string containing the contents of the file.
  • The synchronous loader can return a simple value representing the converted module
  • The return value of the loader is either a javascript code string or Buffer

summary

configuration

  • Conditional matching: Uses test, include, and exclude to match the rule file to be applied by the Loader.
  • Application rule: Use the use configuration item to apply the Loader to the selected file. You can apply one Loader or a group of Loaders in backward order. You can also pass parameters to the Loader separately.
  • Reset order: The default execution order of a group of Loaders is from right to left. The Exforce option allows the execution order of one loader to be placed first or last.

Writing principles

  • Single responsibility. Each loader is only responsible for one thing.
  • Use chain calls to make sure loader’s dependencies are correct.
  • Stateless to ensure that Loader does not save state between module transitions. Each run should be independent of other compiled modules and previous compilations of the same module.

The difference between loader and plugin

  1. Functions and Features
  • Loader: Converts files to files recognized by WebPack, executed from right to left

  • Plugin: Plugins that listen to files and process them while Webpack is packed, in order to solve other things that loader can’t do

  • 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 describes how WebPack handles non-javascript modules and introduces these dependencies in builds. Loader can convert files from different languages (such as TypeScript) to JavaScript, or convert inline images to data urls. For example, CSS-loader, style-loader and so on.

  • Plugin is a plug-in, based on the event flow framework Tapable, plug-ins can extend the functions of Webpack,A number of events are broadcast during the life cycle of a Webpack run, and plugin can listen for these eventsChange the output when appropriate through the API provided by Webpack.
  1. configuration
  • 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.
  • 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.

Commonly used Loader and Plugin

Packaging CSS

  • Style-loader: Inserts js style code into the index.html file
  • Css-loader: Simply writes style code to JS
  • Postcss-loader prefix postcss.config.js require(‘autoprefixer’)
  • less-loader
  • Stylelint-webpack-plugin: CSS code format check also need to install stylelint stylelint-config-standard
  • Optimize – CSS -assets-webpack-plugin/CSS -minimizer-webpack-plugin CSS compression, different components of the repeated CSS can be quickly removed
  • Sass-loader: loads sASS/SCSS files and compiles them to CSS
  • Mini-css-extract-plugin: Package CSS files. This plugin can be used to separate styles into a SINGLE CSS file. The plugin needs to use both its Loader and plugin
Plugins :[new MiniCssExtractPlugin({filename: 'css/main.css' }), ], module: { rules: [ { test: /\.css$/, loader: [MiniCssExtractPlugin. Loader, 'CSS - loader]}}] on pit lies in the fact that the style - loader and miniCss. Loader used together, the cause has been packaged is not successful, Document is not foundCopy the code

Packaging JS

  • babel-loader babel-core @babel/preset-env

@babel/preset-env can only be preset to basic syntax (promise cannot be preset)

@babel/polyfill converts all js new syntax to introduce files that are too big, add junk code core-JS to translate JS new syntax on demand, this is best

  • Eslint eslint-config-Airbnb-base eslint-webpack-import eslint eslint-config-airbnb-base eslint-webpack-import eslint eslint-webpack-import eslint eslint-config-airbnb-base eslint-webpack-import

Packaging pictures

  • File-loader: copies files to be loaded to a specified directory. Generate the request file resource URL,Import on demand, files not imported will not be processed. It is used to copy the image to the output directory, filter out the unused image.
{ test: /\.(png|jpe? g|gif|svg)(\? . *)? $/, loader: 'file-loader', query: { name: '[name].[ext]', outputPath: 'static/img/', publicPath: '/dist/static/img/'}} name Specifies the file name. OutputPath Specifies the output directory of the file, which is the relative path to the webpack output directory. PublicPath specifies the URL to request the file. The generated URL is /dist/static/img/${name}Copy the code

Note: the mini – CSS – extract – the plugin requires additional processing of the image path of CSS (for example: the background image loading failure), or it will failure load, specific see MiniCssExtractPlugin. Loader

  • url-loader: The upgraded version of file-loader, if the image is smaller than the configured size, will be converted to base64 string, reducing the number of image requests, such as setting the limit of 8192, that is, 8M. Url-loader is an enhanced feature.

  • Html-loader: exports HTML as a string. In the process of exporting, it can handle all the content related to the resource in THE HTML, so it can solve the problem of image introduction. It will convert the image to require or import. Audio, video and other resources can be processed.

Handle the problem of loading images in HTML. If you import images in HTML directly, you can use htML-loader to process the image path without using htML-loader.

Although html-loader is configured, the path image in HTML is processed, but the image cannot be read normally, because urL-loader uses ES Modules specification by default, but htML-loader uses CommonJS specification to import images. Solution: Disable the ES Modules specification of urL-loader and force urL-loader to use CommonJS specification for packaging

esModule:false
Copy the code

In Webpack4, only the URl-loader configuration esModule:false is required

Webpack5 requires esModule:false for both html-loader and url-loader

Conflicts between html-loader and html-webpack-plugin:

HtmlWebpackPlugin detects whether the target file has been processed by loader, and if so

Other loaders handle it. HtmlWebpackPlugin no longer uses LoDash.template to handle EJS syntax.

Html-loader If the HTML is common, the HTML is processed according to htML-loader. Otherwise, the HTML syntax is changed to EJS.

Html-loader can handle static templates, and the template does not use EJS syntax syntax, can handle image loading problems. If ejS syntax is used, html-webpack- can be used

  • Image-webpack-loader: Using image compression can greatly reduce package size

Packaged font

  • File-loader packs fonts

If the url-loader condition is not met, file-loader is used

other

  • DefinePlugin(built-in webpack plug-in) : Define environment variables, which is useful for building development and release patterns to allow different behaviors.
  • Copy-webpack-plugin: Other files that do not need to be processed, can be directly copied to the output directory, copy resource plug-ins
  • Clean-webpack-plugin: clean the specified files in the specified directory. Delete the historical files before each packing
  • Html-webpack-plugin: automatically generate HTML (filename,title,template)
  • Compression -webpack-plugin: Compression files, production environment can use Gzip compression JS and CSS
New CompressionPlugin({// Package file in GIz format filename: '[path].gz[query]', // Target resource name. [file] will be replaced with the original resource. (path) will be replaced with the original resource path, [query] to replace the original query string algorithm: 'gzip, / / algorithm test: new RegExp (' \ \. (js) | CSS $'), the threshold: 10240,// Only resources larger than this value are processed. MinRatio in bytes: 0.8// Only resources with a compression ratio less than this value are processed})Copy the code
  • Vconsole webpack – plugin: debugging

  • Extract -text-webpack-plugin: Separate styles referenced in js files into CSS files to prevent packing styles in JS and causing page style loading errors

  • ProvidePlugin: Automatically loads modules without having to import or require them everywhere

To automatically load jquery, we can point both variables to the corresponding Node module new webpack.ProvidePlugin({$: 'jquery', jquery: 'jquery'}).Copy the code
  • SplitChunksPlugin: unpacking
splitChunks: {
  chunks: 'async',
  minSize: 20000,
  minRemainingSize: 0,
  maxSize: 0,
  minChunks: 1,
  maxAsyncRequests: 30,
  maxInitialRequests: 30,
  automaticNameDelimiter: '~',
  enforceSizeThreshold: 50000,
  cacheGroups: {
    defaultVendors: {
      test: /[\\/]node_modules[\\/]/,
      priority: -10
    },
    default: {
      minChunks: 2,
      priority: -20,
      reuseExistingChunk: true
    }
  }
}
Copy the code
  • Uglifyjs-webpack-plugin: Compress code based on UglifyJS
new UglifyJsPlugin()
Copy the code
var webpackConfig = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js'
  },
  plugins: [new HtmlWebpackPlugin()]
};
Copy the code
  • CommonsChunkPlugin(built-in WebPack plug-in) : Improves packaging efficiency by packaging third-party libraries separately from business code.

  • Babel-plugin-transform-runtime: reduces redundant code

Note:

Why not use scaffolding: The extract-text-webpack-plugin does not yet have the webpack4 version, and the extract-text-webpack-plugin does not have the webpack4 version. Use NPM install extract-text-webpack-plugin@next to resolve the problem

It is inevitable to update ecology-related plug-ins to the new version, and this process may encounter many potholes: for example, CommonsChunkPlugin has been removed from Webpack4

The difference between url-loader and file-loader

The url-loader function is similar to file-loader, but returns a DataURL if the file size (in bytes) is below the specified limit.

File-loader By default, the generated file name is the MD5 hash value of the file content and retains the original extension of the referenced resource.

Import img from ‘./file. PNG ‘to generate file file. PNG, output to the output directory and return the public URL. “/public/path/0dcbbaa7013869e351f.png”

test: /\.(jpe? g|png|gif)$/, use: [ { loader: 'url-loader', options: { esModule: Img attribute SRC ="[object Module]" limit: 1024 * 100, // When larger than 100KB, package the file to publicPath outputPath: 'images', // Where to pack the file publicPath: 'images/', name: [hash:8].[ext]'}}] options publicPath+name= full write of HTML and CSS reference paths /images/ will cause the reference path on the page to be incorrect, and if publicPath is changed to images/, the CSS reference path will be incorrect. Set outputPath: 'img', publicPath: '/img',Copy the code

This packaging method has certain drawbacks: after packaging, each image will be loaded, will send an HTTP request, when the page image is too many, will seriously slow down the page load speed. In this case, we can choose to use urL-loader for packaging. By configuring rules, small images can be packaged as Base64 and stored in the packaged JS, and there is no need to send separate HTTP requests to load images.

www.jianshu.com/p/dc7226ac6… www.yuque.com/yijiangxili…

Segmentfault.com/a/119000001…