2

Preface

Everyone knows that webpack will be used when building front-end projects with sass-loader、less-loader、postcss-loader、css-loader、style-loader , but loader play in it? This article mainly explains the role and realization of css-loader and style-loader , and deepens the understanding loader

css-loader

css-loader will @import and url() , just like js parses import/require() , it will generate an array by default to store the processed style strings and export them.

If there are three style files: a.module.scss , b.module.scss , c.module.scss , the dependency between them is as follows:

// a.module.scss
@import './b.module.scss';

.container {
  width: 200px;
  height: 200px;
  background-color: antiquewhite;
}

// b.module.scss
@import url('./c.module.scss');

.text {
  font-size: 16px;
  color: #da2227;
  font-weight: bold;
}

// c.module.scss
.name {
  font-size: 16px;;
  color: #da7777;
  font-weight: bold;
}

Introduce them in the index.jsx

// index.jsx
import React from 'react';

import styles from './a.module.scss';

const Index = () => {
  return <div className={styles.container}>
    <span className={styles.text}><span className={styles.name}>xxx,</span>hello world!!!</span>
  </div>
}

export default Index;

webpack.config.js build script

// webpack.config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
  entry: {
    index: './src/index.jsx'
  },
  output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, './dist'),
    library: 'MyComponent',
    libraryTarget: 'umd',
  },
  resolve: {
    extensions: ['.js', '.jsx', '.tsx'],
  },
  module: {
    rules: [
      { 
        test: /\.(js|jsx)$/, 
        exclude: /node_modules/, 
        loader: "babel-loader" 
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: false, // 禁止css modules
            }
          },
          'sass-loader'
        ]
      },
      { 
        test: /\.(jpg|jpeg|png|gif)$/, 
        use: ['url-loader'] 
      }
    ]
  },
  plugins: [
    new webpack.ProgressPlugin(),
    new CleanWebpackPlugin({
      cleanOnceBeforeBuildPatterns: ['dist']
    }),
  ],
}

.babelrc configuration

// .babelrc
{
  "presets": [
      "@babel/preset-env",
      "@babel/preset-react"
  ],
  "plugins": [
      "@babel/plugin-proposal-class-properties"
  ]
}

In package.json configuring the build command "build:dev": "webpack --mode none" . In order to facilitate the analysis of the code after construction, set mode to none here.

Three types of mode :

developmentDefinePlugin set the value of 0618523dcc94aa in process.env.NODE_ENV development . Enable valid names for modules and chunks, that is, replace the module id with the module name.
image-20211105160434858.png

image-20211105160155947.png
productionDefinePlugin set the value of 0618523dcc9506 in process.env.NODE_ENV production .
enabled certainty for the module and chunk confusing name , FlagDependencyUsagePlugin ,
FlagIncludedChunksPlugin , ModuleConcatenationPlugin ,
NoEmitOnErrorsPlugin and TerserPlugin .
image-20211105160641404.png
noneDo not use any default optimization options

Perform yarn build:dev build, analyze the generated files

(. 1) a.module.scss used @import introduced b.module.scss , is processed into same module array ___CSS_LOADER_EXPORT___ and export

image-20211105185844556.png

(2) b.module.scss uses @import url() introduce c.module.scss , but c.module.scss is processed separately into another module's array ___CSS_LOADER_EXPORT___ and exported

image-20211105190430662.png

(3) a.module.scss and b.module.scss are processed and put into a module array, and c.module.scss is processed separately and put into another module's array, but b.module.scss and c.module.scss are introduced by the relationship. How does this relate to dependencies after construction?

a.module.scss and b.module.scss be processed into module id as 12 array c.module.scss be processed into module id as 15 array module id of 12 module into which a module id to 15 style array, and append it to the module id is 12 , and finally __WEBPACK_DEFAULT_EXPORT__ . The css-loader at this step ends .

In addition, css-loader also provides other functions, such as css modules . If you want to understand, you can refer to the example to open the css modules construction to get a glimpse of its principle. I will not introduce it here.

image-20211105192051078.png

image-20211105191531780.png

css-loader Export method

The imported styles mentioned above are all converted into style strings and placed in the module array. This is the default processing method. In fact, there are two other types.

The configuration item exportType allows the export style to be 'array' , 'string' or 'css-style-sheet' to construct the style (that is, CSSStyleSheet ), the default value: 'array'

CSSStyleSheet interface represents a CSS style sheet, and allows to check and edit the list of rules in the style sheet. It inherits properties and methods from the parent type StyleSheet

A CSS style sheet contains a set of CSSRule objects representing rules. Each CSS rule can be operated by the objects associated with it. These rules are contained in CSSRuleList and can be obtained through the cssRules (en-US) attribute of the style sheet.

For example, CSSStyleRule object might contain this style:

h1, h2 {
  font-size: 16pt;
}

style-loader

style-loader role is to CSS inserted DOM , the process is css-loader array module derived, then the style by style inserted tag or other forms DOM in.

Configuration item injectType can be configured to insert styles DOM , mainly include:

  • styleTag : By using a plurality of <style></style> automatically styles inserted DOM in. This method is the default behavior
  • singletonStyleTag : Automatically insert styles into DOM by using a <style></style>
  • autoStyleTag : Same as styleTag , but when the code IE6-9 , please open singletonStyleTag mode
  • lazyStyleTag : Use multiple <style></style> to insert styles DOM when needed. Recommended lazy style follow use .lazy.css as a suffix naming conventions, style-loader basic usage is .css as the file suffix (other files too, such as: .lazy.less and .less ). When using lazyStyleTag , style-loader inserts the styles . When you need to use styles , you can use style.use() / style.unuse() make style available.
  • lazySingletonStyleTag : By using a <style></style> to automatically styles inserted into DOM , as described above provide an inert support
  • lazyAutoStyleTag : Same as lazyStyleTag , but when the code IE6-9 , please open lazySingletonStyleTag mode
  • linkTag : Use multiple <link rel="stylesheet" href="path/to/file.css"> to insert styles into the DOM. This loader will be used at run time JavaScript dynamically inserted <link href="path/to/file.css" rel="stylesheet"> . To static into <link href="path/to/file.css" rel="stylesheet"> , please use MiniCssExtractPlugin .

We use the styleTag insertion method for analysis:

All the styles mentioned above are added to id as 12 , the following first obtains the module array of the module id as 12 , and then generates the style label and inserts its style into DOM

image-20211105200147804.png

_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default() above figure update method returned by the module in the figure below. This method calls many other methods to insert the style into DOM style

image-20211105200723559.png

refer to:

css-loader

style-loader


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。