current position:Home>An article takes you to master the functions of loaders and plugins commonly used in webpack

An article takes you to master the functions of loaders and plugins commonly used in webpack

2021-08-27 05:44:47 fstar

This is my participation 8 The fourth of the yuegengwen challenge 6 God , Check out the activity details :8 Yuegengwen challenge

Usually, we seldom fiddle with webpack To configure , It's all made for us by the big guys , Let's just write business code , For many commonly used loader and plugin Probably know what it is , But in fact, what has been done underneath is like a layer of fog .

So I wrote this article , I hope you can get rid of this fog after reading this article , For the common loader and plugin The role of .

Commonly used loader

webpack Of loader It is used to process a single file . Or it can be called converter , It applies the corresponding multiple... To the matching file loader Deal with in order , Finally return to a JS String of content , Give Way webpack It can be modularized . The core points are :

  • loader Finally, they all return a JS String of content .

  • loader It's actually a converter , Process the source file .

  • Multiple in series in the configuration loader The order of execution is from back to front .

babel-loader

babel-loader Can be said to be Webpack The standard configuration of the construction project , Because it implements a core compatibility function : The new version of ES The syntax is converted to... That can run on most browsers ES5 grammar .

{
  module: {
    rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
        },
      },
      // ...
    ]
  }
}
 Copy code 

because babel The configuration of is more complicated , So we don't usually webpack Configure on , But use babel Dedicated configuration file . Reference resources

  • babel.config.js. Global configuration ( Project level , Execute Directory )
  • .babelrc. Local configuration ( Directory level ), Will work with project level babel.config.js A merger . If the current directory does not have .babelrc, Look up for the nearest . If this file is outside the project root directory , Will not apply to the file under the same level directory .babelrc.

Besides babel.config.js yes JS file , Modules can be introduced ; and .babelrc It is JSON file .

We usually need to be in babel Add some preset sets to your configuration file (preset), The so-called preset set is to put some babel Common transformations are packaged . There is no talk here

css-loader

css-loader take CSS Compile the file into an object , Recorded some necessary information . This object cannot be used directly , Need to cooperate with style-loader, Realize the mounting of style .

// index.css
.red {
  background-color: #f04;
}
 Copy code 

The above style will be converted to the following object .

image.png

css-loader An important function of is to support **CSS modularization (CSS-module)** The implementation of the , It's component-based development CSS A popular solution for componentization , The configuration is as follows .

options: {
  modules: {
    localIdentName: '[name]__[local]__[hash:base64:5]',
  },
},
 Copy code 

style-loader

style-loader Handle css-loader Returned object , take CSS Put the content in style Under the label , Then put it in DOM Under the tree ( The default is to put <head> Next , Can pass through options.insert Modify the mount location ). Note that there is no CSS file , It's going to be CSS The contents of the file are saved in the script as a string .

In the actual production environment , We still need to extract CSS Of documents . For this, we use MiniCssExtractPlugin.loader.

MiniCssExtractPlugin.loader

mini-css-extract-plugin The function of the plug-in is to extract CSS The content is a separate file . By default, all CSS The content is packaged into one CSS In the document .mini-css-extract-plugin Itself is a plug-in , But it also provides loader. Use loader The corresponding... Must be used at the same time plugin, Otherwise, an error will be reported .

Generally speaking, we will build the environment according to , Be sure to use style-loader still MiniCssExtractPlugin.loader:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = (env) => ({
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          env.production ? MiniCssExtractPlugin.loader : 'style-loader',
          'css-loader',
          // ...
        ]
      }
    ]
  },
  // ...
  plugins: [
    new MiniCssExtractPlugin(),
  ]
})
 Copy code 

If you use html-webpack-plugin plug-in unit , It can recognize mini-css-extract-plugin Generated CSS file name , With link Embedded into the generated html Next .html-webpack-plugin Speaking of :

If you have any CSS assets in webpack's output (for example, CSS extracted with the mini-css-extract-plugin) then these will be included with <link> tags in the HTML head.

postcss-loader

postcss-loader Is a tool for handling styles , Support various easy-to-use plug-ins . Usually we use a separate postcss.config.js To configure ( Of course, you can also directly webpack Configure on the configuration ).

Its strength lies in its ability to use many easy-to-use plug-ins , Such as :

  • autoprefixer: Add browser specific prefixes to selectors or style rules , Dealing with browser compatibility issues . Such as ::placeholder {} Converts to various browser specific selectors , Yes ::-webkit-input-placeholder {} input::-ms-input-placeholder {} etc. . Also like transform attribute .autoprefixer Almost postcss Standard plug-in , Because it handles CSS compatibility .
  • postcss-pxtorem: take css Inside px Convert to rem Company , This is based on rem Adapted to H5 The page needs to use .

less-loader / sass-loader etc.

Usually we don't write directly CSS, But will use less、sass And so on , Mainly to use CSS Not available Selector nesting syntax , This syntax greatly improves our efficiency in writing styles .CSS Preprocessor is standard for almost all projects .

Depending on the project , We will choose to use different CSS The preprocessor , For this, we need to install different preprocessors loader.

Suppose we use less-loader, Then we have to install less-loader, And install less, Otherwise it's importing less An error will be reported when the file is loaded . Other preprocessors loader The same is true . The configuration looks like this

{
  test: /\.less$/,
  use: [
    env.production ? MiniCssExtractPlugin.loader : 'style-loader',
    'css-loader',
    'postcss-loader',
    'less-loader'
  ]
},
 Copy code 

It should be noted that less-loader It must be put in postcss-loader Behind , because loader The execution order of is from right to left , postcss-loader Unable to deal with less The grammar of , such as //, Need to go through first less-loader Convert to CSS after ,postcss-loader To understand and deal with .

file-loader

file-loader The role of the JS The resources imported in the file are renamed using hashes ( By default ), Put it in the build directory . Then you can get the new resource name in the script , Put it where you need it , such as img.url. The configuration is written like this :

{
  test: /\.(png|jpe?g|gif)$/,
  use: 'file-loader'
}
 Copy code 

however webpack 5 The latter one loader Made a built-in ( No additional installation required file-loader), And changed the concept :asset module. stay webpack 5 in , We can write this way :

{
  test: /\.(png|jpe?g|gif)$/,
  type: 'asset/resource'
}
 Copy code 

url-loader

url-loader Will convert the introduced resources into base64 URI. The original resource is not copied to the build directory , It becomes a long, long string encoding .base64 Will 3 Bytes to 4 Bytes , This leads to larger resources , Especially not for large files . For small resources, the loss is low , But it can reduce one HTTP request .base64 Generally used to optimize network requests , Reduce the number of small resource requests .

So usually we give a threshold ( Usually it is 8194 byte , Probably 8K The appearance of ). Use when the file is smaller than the specified size base64(url-loader), Otherwise, just copy resources (file-loader).

{
  test: /\.(png|jpe?g|gif)$/,
  use: [
    {
      loader: 'url-loader',
      options: {
        limit: 8194, //  The unit is byte 
      }
    } 
    //  You don't need to write here  file-loader, But you have to install .
    //  Otherwise, if the file is too large, an error will be reported as :Cannot find module 'file-loader'
  ]
}
 Copy code 

Use the above wording , If the resource is greater than or equal to 8194 byte ,url-loader Will automatically find file-loader To deal with ( have access to options.fallback To specify the... To be used when the conditions are not met loader).

Again ,webpack 5 The built-in test is also carried out loader, be known as asset/inline. It's written as type: asset/inline or type: 'asset', parser: {dataUrlCondition: {maxSize: 8 * 1024}}. The latter is written with a threshold .

raw-loader

raw-loader Responsible for extracting the contents of the file , Convert to string form . Generally used to extract text files , Such as txtjson.webpack 5 Built it in , It's written as type: 'asset/source'.

I tried to extract the contents of the binary file , The result is a pile of garbled code .

common plugin

plugin Can be in webpack Some life cycle hook functions of , Call at the right time webpack Provided API, Change the output .

By using plugin, We can achieve the goal of webpack Function enhancement , solve loader What cannot be handled is interspersed with webpack All kinds of things in the packaging process .

html-webpack-plugin

html-webpack-plugin Is a simplified way to put packaged files into HTML Process plug-ins , Because our packaged files will produce multiple files , There may be a hash value , It might be unpacked , If we all have to introduce them one by one html In the document , It is undoubtedly very cumbersome and easy to make mistakes . This plug-in can help us simplify this work .

clean-webpack-plugin

clean-webpack-plugin The plug-in is used to empty before construction “ Build directory ”(output.path Configure the directory pointed to ). This can prevent some redundant files from remaining , For example, after modifying the source file , Result in a new file after packaging hash The value has changed , Used old hash Keep your old files , It's superfluous .

I see a kind of honey realization clean-webpack-plugin Methods . Is in the package.json Plus the execution script :

"scripts": {
  "prebuild": "rm -rf dist/*",
  // ...
}
 Copy code 

In this way build Before script , It will be executed first prebuild Script , Empty the build directory . In a sense , It can . But if the output directory changes later , It's easy to forget to change here .

copy-webpack-plugin

copy-webpack-plugin The plug-in can copy multiple files or folders to the build directory (build directory, Is the directory where the package file is output ). Use scenarios :

  • Copy static Folder , Put some that don't pass import Introduced resources . For example, some of the smaller ones don't provide ES Third party Library of modular files 、 some SDK. After using the plug-in , We can use the template html The document says <script src="/public/lib-a.js"></script>
  • robot.txt Copies of documents .
new CopyWebpackPlugin([
  {
    from: path.join(__dirname, 'static'), 
    to: 'static',
    ignore: ['.*']
  },
  {
    from: resolvePath('robots.txt'),
    to: 'robots.txt'
  }
]
 Copy code 

webpack.ProvidePlugin

ProvidePlugin yes webpack A built-in plug-in . The function is to automatically load the module , You don't have to write one line at a time import or require, It is applicable to some basic modules that are often imported into other modules . Note that this plug-in does not inject the specified module into the global scope , Just let you write one less line in the module file to introduce logic . Such as :

plugins: [
  new webpack.ProvidePlugin({
    $: 'jquery',
    _map: ['lodash', 'map']
  })
]
 Copy code 

webpack.DefinePlugin

webpack.DefinePlugin yes webpack Built in plug-ins , You can replace the specified variable with other values at compile time . It's kind of like C Macro in language .

If the scope contains a variable with the same name ,DefinePlugin The variable defined in does not overwrite it , You can think of it as a higher scope than the global scope , Of course, in fact, they are not injected into the scope .

In essence , Just replace JS A string in the form of a matching variable in the file , Replace with the specified string .

new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(!!env.production),
  CONSOLE: 'console.log(" I'll just output ")'
})
 Copy code 
//  Source code 
console.log(PRODUCTION)
CONSOLE

//  Production environment use  DefinePlugin  after , Convert to :
console.log(true)
console.log(" I'll just output ")
 Copy code 

terser-webpack-plugin / uglifyjs-webpack-plugin

uglifyjs-webpack-plugin and terser-webpack-plugin They are all code compression plug-ins , The former has been abandoned , The latter is recommended .

When we compress code , It used to be uglify-es(uglify-js I won't support it ES6,uglify-es It is the harmony Branch , Support ES6+), But later uglify-es No more maintenance . So someone fork 了 uglify-es, Created terser, Keep maintaining .

webpack It has built-in code compression plug-in , It used to be uglify-es, stay v4.26.0 Then use terser. The code compression plug-in will only execute in the production environment , Of course, we can set optimization.minimize by false Forcibly turn off the code compression function .

Of course, you can use the latest version of terser Or do some configuration functions , Install a separate terser-webpack-plugin plug-in unit . Different from ordinary plug-ins , The configuration of the code compression plug-in needs to be put into optimization.minimizer Location .

const TerserPlugin = require('terser-webpack-plugin')

optimization: {
  minimizer: [
    new TerserPlugin({
      parallel: true, //  parallel 
      terserOptions: {
        compress: {
          drop_console: false //  lose  console, Reduce memory leaks 
        }
      }
    }),
  ]
}
 Copy code 

ending

The above is a common loader and plugin Explanation , They are used in almost all projects , It is necessary to take time to think and understand .

Practice is the only criterion for testing truth . If you want to better understand these loader and plugin, I still suggest you do it from zero to one webpack To configure , Observe the output results caused by different configurations .

Reference resources

copyright notice
author[fstar],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827054439804a.html

Random recommended