Skip to content

CSS处理

提取 Css 成单独文件

CSS 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式

这样对于网站来说,会出现闪屏现象,用户体验不好

我们应该是单独的 CSS 文件,通过 link 标签加载性能才好

1. 下载包

  npm i mini-css-extract-plugin -D

2. 配置

  • webpack.prod.js
js
const path = require('path')
const ESLintWebpackPlugin =  require('eslint-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') 

module.exports = {
  entry: '',
  output: {
    path:path.resolve(__dirname, '../dist'),
    filename: 'static/js/main.js',
    clean: true
  },
  module: {
    rules: [{
      test: /\.css$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader']
    },{
      test: /\.less$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
    },{
      test: /\.s[ac]ss$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
    },{
      test: /\.styl$/,
      use: [MiniCssExtractPlugin.loader, 'css-loader', 'stylus-loader']
    },{
      test: /\.(png|jpe?g|gif|webp)$/,
      type: 'asset',
      parse: {
        dataUrlCondition: {
          maxSize: 10 * 1024
        }
      },
      generator: {
        filename: 'static/image/[hash:10][ext][query]'
      }
    },{
      test: /\.(ttf|woff2|avi|mp3|mp4)$/,
      type: 'asset/resource',
      generator: {
        filename: 'staic/media/[hash:10][ext][query]'
      }
    },{
      test: /\.js$/,
      exclude: 'node_module',
      loader: 'babel-loader'
    }]
  },
  loaders: [
    new ESLintWebpackPlugin({
      context: path.resolve(__dirname, '../src')
    }),
    new HTMLWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    }),
    new MiniCssExtractPlugin()
  ],
  mode: 'production'
}

4. 运行指令

npm run build

CSS兼容性处理

1.下载包

  npm i postcss-loader postcss postcss-preset-env -D

2. 配置

  • webpack.prod.js
js
  const path = require('path')
  const ESLintWebpackPlugin = require('eslint-webpack-plugin')
  const HTMLWebpackPlugin = require('html-webpack-plugin')
  const MiniCssExtractPlugin = require('mini-css-extract-plugin')

  module.exports = {
    entry: './src/main.js',
    output: {
        path:path.resolve(__dirname, '../dist'),
        filename: 'static/js/index.js' 
    },
    module: {
        rules: [{
          test: /\.css$/,
          use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            {
              loader: 'postcss-loader',
              options: {
                postcssOptions: {
                  plugins: [
                    'postcss-preset-env'
                  ]
                }
              }
            }
          ]
        },{
          test: /\.less$/,
          use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            {
              loader: 'postcss-loader',
              options: {
                postcssOptions: {
                  plugins: [
                    'postcss-preset-env'
                  ]
                }
              }
            },
            'less-loader'
          ]
        },{
          test: /\.s[ac]ss$/,
          use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            {
              loader: 'postcss-loader',
              options: {
                postcssOptions: {
                  plugins: [
                    'postcss-preset-env'
                  ]
                }
              }
            },
            'sass-loader'
          ]
        },{
          test: /\.styl$/,
          use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            {
              loader: 'postcss-loader',
              options: {
                postcssOptions: {
                  plugins: [
                    'postcss-preset-env'
                  ]
                }
              }
            },
            'stylus-loader'
          ]
        }, {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        use: {
          loader: 'babel-loader'
        }
      }]
    },
    plugins: [],
    mode: 'production'
  }

3. 控制兼容性(broswerslist)

我们可以在package.json文件中添加broswerslist来控制样式的兼容性做到什么程度

json
// package.json
{
    "broswerslist": ["ie >= 8"]
}

我们可以通过修改broswerslist来改变babelpostcss的兼容性

  • 在package.json中添加broswerslist字段
  • 在根目录添加.broswerslistrc

broswerslist查询语法

具体查看

  • defaults

    默认配置,相当于(>0.5% , last 2 versions, Firefox ESR, not dead)

  • 选择具有特定受众的浏览器

    • 5%: 全球用户比例超过5%的浏览器

    • 5% in US : 在美国用户比例超过5%的浏览器

    • 5% in alt-AS : 在亚洲用户比例超过5%的浏览器

  • 选择最近的浏览器版本

    • last 2 versions: 每个浏览器的最后 2 个版本。
    • last 2 Chrome versions: 谷歌浏览器的最后2个版本
  • 选择特定NodeJS版本

    • node 10:最新的10.X.X版本
    • node 10.4:最新的10.4.X版本
    • node > 16 : 比node16新的版本
    • last node 2 versions: 两个最新的 Node.js 版本
  • 选择特定浏览器版本的

    • Chrome 113:113版本的Chrome浏览器
    • Chrome > 113 : 比113版本更新的Chrome浏览器
    • not Chrome 113: 删除特定版本
  • 选择支持特定功能的浏览器

    • supports es6-module
    • supports css-grid
  • 排除未维护的版本

    • no dead: 排除官方两年未维护的浏览器

4. 合并配置

  • webpack.prod.js
js
const path = require('path')
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

const getStyleLoaders = (loadName) => {
  return [ 
    MiniCssExtractPlugin.loader,
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: ['postcss-preset-env']
        }
      }
    },
    loadName
  ].filter(Boolean)
}

module.exports = {
   entry: '',
   output: {
     path: path.resolve(__dirname, '../dist'),
     filename: 'static/js/index.js'
   },
   module: {
    rules:[{
      test: /\.css$/,
      use: getStyleLoaders()
    },{
      test: /\.less$/,
      use: getStyleLoaders('less-loader')
    },{
      test: /\.s[ac]ss$/,
      use: getStyleLoaders('sass-loader')
    },{
      test: /\.styl$/,
      use: getStyleLoaders('stylus-loader')
    },{
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ]
   },
   plugins: [
    new ESLintWebpackPlugin({
      context: path.resolve(__dirname, '../src')
    }),
    new HTMLWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    })
    new MiniCssExtractPlugin()
   ],
   mode: 'production'
}

5、 运行指令

npm run build

CSS压缩

1. 下载包

 npm i css-minimizer-webpack-plugin -D

2. 配置

js
const path = require('path')
const ESLintWebpackPlugin = require('eslint-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

const getStyleLoaders = (loadName) => {
  return [ 
    MiniCssExtractPlugin.loader,
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        postcssOptions: {
          plugins: ['postcss-preset-env']
        }
      }
    },
    loadName
  ].filter(Boolean)
}

module.exports = {
   entry: '',
   output: {
     path: path.resolve(__dirname, '../dist'),
     filename: 'static/js/index.js'
   },
   module: {
    rules:[{
      test: /\.css$/,
      use: getStyleLoaders()
    },{
      test: /\.less$/,
      use: getStyleLoaders('less-loader')
    },{
      test: /\.s[ac]ss$/,
      use: getStyleLoaders('sass-loader')
    },{
      test: /\.styl$/,
      use: getStyleLoaders('stylus-loader')
    },{
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ]
   },
   plugins: [
    new ESLintWebpackPlugin({
      context: path.resolve(__dirname, '../src')
    }),
    new HTMLWebpackPlugin({
      template: path.resolve(__dirname, '../public/index.html')
    })
    new MiniCssExtractPlugin({
      filename: 'static/css/index.css'
    }),
    new CssMinimizerWebpackPlugin()
   ],
   mode: 'production'
}

KESHAOYE-知识星球