# PostCSS 工具

# 什么是 PostCSS

PostCSS 是一个通过 JavaScript 来转换样式的工具,这个工具可以帮助我们进行一些 CSS 的转换和适配,比如自动添加浏览器前缀、css 样式的重置。但是实现这些工具,我们需要借助于 PostCSS 对应的插件。主要用来处理浏览器兼容性问题。

安装 PostCss:

npm install postcss postcss-cli -D

使用:在 webpack 的配置文件中编写相应的 loader 规则,或者直接在命令行中使用。

因为 postcss 是独立于 webpack 的,所以在 webpack.config.js 中配置 postcss 前需要安装相应 loader

npm install postcss-loader -D

配置:

// webpack.config.js -> modules -> rules -> use
{
    loader: "postcss-loader",
    options: {
        postcssOptions: {
            plugins: [
                require('autoprefixer')
            ]
        }
    }
}

# autoprefixer

autoprefixer 可以帮助我们生成兼容各种浏览器的 css 代码,它的主要作用就是给 css 代码添加上相应的浏览器前缀。如:

/* autoprefixer 处理前 */
:fullscreen {
    color: red;
}
.content {
    user-select: none;
}
/* autoprefixer 处理后 */
:-ms-fullscreen {
}
:fullscreen {
}
.content {
    -webkit-user-select: none;
    	-moz-user-select: none;
    		-ms-user-select: none;
    			user-select: none;
}

安装 autoprefixer

npm install autoprefixer -D

单独配置 autoprefixerpostcss.config.js 中配置:

// postcss.config.js
module.exports = {
    plugins: [
        require("autoprefixer")
    ]
}

# postcss-preset-env

postcss-preset-env 也是一个 postcss 的插件。它可以帮助我们将一些现代的 CSS 特性,转成大多数浏览器认识的 CSS,并且会根据目标浏览器或者运行时环境添加所需的 polyfill。也包括会自动帮助我们添加 autoprefixer(所以相当于已经内置了 autoprefixer)。

安装 postcss-preset-env

npm install postcss-preset-env -D

配置 postcss-preset-env

// postcss.config.js
module.exports = {
    plugins: [
        require("postcss-preset-env")
    ]
}

# 加载和处理其它资源

# file-loader

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

安装 file-loader

npm install file-loader -D

配置 file-loader

// webpack.config.js -> modules -> rules
{
    test: /\.(png|jpe?g|gif|svg)$/i,
    use: {
        loader: "file-loader"
    }
}

有时候我们处理后的文件名称按照一定的规则进行显示: 比如保留原来的文件名、扩展名,同时为了防止重复,包含一个 hash 值等。 这个时候我们可以使用 PlaceHolders 来完成,webpack 给我们提供了大量的 PlaceHolders 来显示不同的内容。

常用的 placeholder:

  • [ext]: 处理文件的扩展名
  • [name]:处理文件的名称
  • [hash]:文件的内容,使用 MD4 的散列函数处理,生成的一个 128 位的 hash 值(32 个十六进制)
  • [contentHash]:在 file-loader 中和 [hash] 结果是一致的(在 webpack 的一些其他地方不一样,后面会讲到)
  • [hash:<length>]:截图 hash 的长度,默认 32 个字符太长了
  • [path]:文件相对于 webpack 配置文件的路径

例如将图片文件输出到 /img 下,并且用 文件原名 + hash值前8位 + 扩展名 命名打包好的图片文件。

// webpack.config.js -> modules -> rules
{
    test: /\.(png|jpe?g|gif|svg)$/i,
    use: {
        loader: "file-loader",
        // 写法一
        options: {
            name: "img/[name].[hash:8].[ext]"
        }
        // 写法二
        /*
        options: {
            name: "img/[name].[hash:8].[ext]",
            outputPath: "img"
        }
        */
    }
}

# url-loader

url-loaderfile-loader 的工作方式是相似的,但是可以将较小的文件,转成 base64 的 URI。

安装 url-loader

npm install url-loader -D

配置 url-loader

// webpack.config.js -> modules -> rules
{
    test: /\.(png|jpe?g|gif|svg)$/i,
    use: {
        loader: "url-loader",
        options: {
            limit: 100 * 1024, // 仅将 100Kb 一下的图片转换为 base64
            name: "[name].[hash:8].[ext]",
            outputPath: "img"
        }
    }
}

# asset module type

# 介绍

在 webpack5 之前,加载非 javascriptjson 资源我们需要使用一些 loader,比如 raw-loader 、url-loader、file-loader
在 webpack5 之后,我们可以直接使用资源模块类型(asset module type),来替代上面的这些 loader。

资源模块类型 (asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

  • passet/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现
  • passet/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现
  • passet/source 导出资源的源代码。之前通过使用 raw-loader 实现
  • passet 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源 体积限制实现

# 使用

使用 asset module type 我们可以在 rules 中配置:

// webpack.config.js -> module -> rules
{
    test: /\.(png|jpe?g|svg|gif)$/i,
    type: "asset/resource"
}

自定义文件输出路径和文件名:

// webpack.config.js -> output
// 方法一
output: {
    filename: "js/bundle.js",
    path:path.resolve(__dirname,"./dist"),
    assetModuleFilename: "img/[name].[hash:6][ext]"
}
// webpack.config.js -> module -> rules
// 方法二 在 rule 中添加一个 generator 属性并设置 filename
{
    test: /\.(png|jpe?g|svg|gif)$/i,
    type: "asset/resource",
    generator: {
        filename: "img/[name].[hash:6][ext]"
    }
    // 实现 limit 效果
    /*
    parser: {
        dataUrlCondition: {
            maxSize: 100 * 1024
        }
    }
    */
}

处理字体文件,用 webpack5 中的 asset/resource 来替代 file-loader

// // webpack.config.js -> module -> rules
{
    test: /\.(woff2?|eot|ttf)$/i,
    type: "asset/resource",
    generator: {
        filename: "font/[name].[hash:6][ext]"
    }
}