webpack学习 --- postcss 和 图片资源打包

1,157 阅读3分钟

postcss

  1. PostCSS是一个通过JavaScript来转换样式的工具
  2. 这个工具可以帮助我们进行一些CSS的转换和适配,比如自动添加浏览器前缀、css样式的重置
  3. 这个工具使用的是微内核架构,所以本身没有太大的功能,如果需要使用其提供的具体功能,需要借助于PostCSS对应的插件

在cli中的使用

需要单独安装一个工具postcss-cli

# 安装
$ npm i postcss postcss-cli -d

# 编译使用
# -o 表示编译后的内容输出到那个文件中环
$ npx postcss ./src/css/index.css -o index.css

# 为浏览器添加前缀 --- 会适配的浏览器:browserslist中查询到的所需要适配的浏览器列表
# 多个插件之间使用空格分隔
$  npx postcss ./src/css/index.css -o index.css --use autoprefixer postcss-preset-env

在webpack中的使用

# 安装
# 可以不用单独安装postcss,因为postcss会作为postcss-loader的依赖一起被安装
$ npm install postcss-loader -D
// 配置(部分)
module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            postcssOptions: {
              plugins: [
                require('autoprefixer')
              ]
            }
          }
        }
      ]
    }
  ]
}

简写:

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'postcss-loader',
          options: {
            postcssOptions: {
              plugins: [
                // 如果这个插件不需要传递参数可以简写为字符串
                // 如果需要传递就只能使用 require('autoprefixer')(参数列表)的方式
                'autoprefixer'
              ]
            }
          }
        }
      ]
    }
  ]
}

postcss-preset-env

postcss-preset-env可以帮助我们将一些现代的CSS特性,转成大多数浏览器认识的CSS,并且会根据目标浏览器或者运行时环 境添加所需的polyfill

可见postcss-preset-env中集成了autoprefixer的相关功能。

# 安装
$ npm install postcss-preset-env -D

配置抽离

我们可能在处理less资源,sass资源,css资源的时候,都需要使用postcss

如果按照之前的配置,我们需要重复在多个地方配置postcss,这是繁琐且重复的

所以我们可以对postcss的配置进行抽取

抽取配置一般为项目根目录下的postcss.config.js (因为postcss只会处理和postcss配置文件同级和对应子目录下的css文件)

// 配置规则和postcssOptions中的配置规则一致
module.exports = {
  plugins: [
    'postcss-preset-env'
  ]
}

webpack.config.js

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
         'postcss-loader' // 这里的配置信息已经被抽离
        ]
     }
  ]
}

postcss-loader的位置

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader',
        'css-loader',
        // 如果postcss-loader和样式的预处理器loader同时存在
        // postcss-loader和预处理器loader没有强制的先后顺序
        // 推荐样式预处理loader写在postcss-loader之后
        'postcss-loader',
        'sass-loader'
        ]
     }
	]
}

importLoaders

/* foo.css  */
.foo {
  user-select: none;
}

/* index.css  */
@import url('./foo.css');

.foo {
  color: #12345678;
}

此时在编译后会发现,color被postcss处理了,但是foo并没有被postcss处理。

// 因为loader的执行是从下往上的,
// 此时执行import代码的时候,已经是被css-loader解析了
// 所以import导入的css文件不会被postcss所解析
[
  'style-loader',
  'css-loader',
  'postcss-loader'
]

此时可以加上importLoaders作为配置参数

[
  'style-loader',
  {
    loader: 'css-loader',
    options: {
      // 表示import引入的资源需要被之前的1个loader所解析(视情况而定,这里只有一个postcss-loader所以值为1)
      importLoaders: 1 
    }
  },
  'postcss-loader'
]

加载和处理其它资源

file-loader

要处理jpg、png等格式的文件资源,我们也需要有对应的loader: file-loader

file-loader的作用就是帮助我们处理import/require()方式引入的一个文件资源,并且会将它放到我们输出的文件夹中

file-loader的默认功能是将文件复制到打包文件夹中并重命名(一般为hash值为名称,避免重复),

在将对应引入的位置修改为打包文件夹中对应的图片

// 配置(部分)
{
  test: /\.(png|jpe?g|gif|svg)/,
  loader: 'file-loader'
}

图片资源的引入方式

// 引入方式2
import webpack from './imgs/webpack.png'

// new Image() 和 document.createElement('img') 都可以创建图片
// 只不过new Image() 可以在创建的时候传递2个参数,分别为图片的宽和图片的高
const dvElem = new Image()
// 引入方式1:
// 老版本的file-loader 引入的直接就是资源路径
// 新版本的file-loader 引入的是一个对象 { default: 资源路径 }
dvElem.src = require('./imgs/webpack.png').default // src方式引入图片
document.body.appendChild(dvElem)

const imgElem = new Image(225, 225)
imgElem.style.background = `url(${webpack})` // 以背景方式引入图片
imgElem.style.backgroundSize = 'contain'
document.body.appendChild(imgElem)

文件的名称规则

我们有的时候需要对打包后的文件资源做一些定制,如指定打包后存放的位置,指定打包后不同资源所对应的命名方式等等,

此时就可以使用file-loader所提供的一系列的placeholder来完成

palceholder功能
[ext]处理文件的扩展名
[name]处理文件的名称
[hash]文件的内容,使用MD4的散列函数(文件摘要算法)处理,生成的一个128位的hash值(32个十六进制)
[contentHash]在file-loader中和[hash]结果是一致的
[hash:length]截图hash的长度,默认32个字符太长了
[path]文件相对于webpack配置文件的路径
{
  test: /\.(png|jpe?g|gif|svg)/,

    use: {
      loader: 'file-loader',

       options: {
         name: '[name].[hash:6].[ext]'
       }
    }
}
{
  test: /\.(png|jpe?g|gif|svg)/,

    use: {
      loader: 'file-loader',

      options: {
        name: '[name].[hash:6].[ext]',
        outputPath: 'img'
      }
    }
}

outputPath一般不单独配置,因为这个配置可以简写为

{
  test: /\.(png|jpe?g|gif|svg)/,

    use: {
      loader: 'file-loader',

      options: {
        name: 'img/[name].[hash:6].[ext]'
      }
    }
}

url-loader

url-loader和file-loader的工作方式是相似的,只不过默认情况下是将图片资源转换为base64编码的方式嵌入到打包后的js文件中

{
  test: /\.(png|jpe?g|gif|svg)/,

    use: {
      loader: 'url-loader', // url-laoder的配置选项和file-loader的配置渲染大体上是一致的

      options: {
        name: 'img/[name].[hash:6].[ext]'
      }
    }
}

开发中我们往往是小的图片需要转换,但是大的图片直接使用图片即可

因为小的图片转换base64之后可以和页面一起被请求,减少不必要的请求过程

大的图片使用链接引入的方式进行引入,避免打包后的js文件过大,影响页面的渲染速度

{
  test: /\.(png|jpe?g|gif|svg)/,

    use: {
      loader: 'url-loader',

      options: {
        name: 'img/[name].[hash:6].[ext]',
        // 如果图片是大于等于100kb的时候,就使用file-loader将其进行编译
        // 如果图片是小于100kb的时候,就将图片资源转换为base64编码,嵌入到打包后的js文件中
        limit: 100 * 1024 // 单位byte 100 * 1024 === 100kb
      }
    }
}