06. 管理资源

84 阅读2分钟

相关代码

一、什么是 loader

Webpack 默认只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。但是通过 loader,能够让 Webpack 去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。

image.png

loader 有两个属性:

  • test:识别出哪些文件会被转换。
  • use:定义出在进行转换时,应该使用哪个或哪些 loader。

如:

module.exports = {
    module: {
        rules: [
            { 
                test: /\.txt$/, 
                use: 'raw-loader'
            }
        ],
    },
}

以上代码,告诉 Webpack 当遇到以 .txt 结尾的文件时,在打包之前先使用 raw-loader 转换一下。

二、加载 CSS

1. css

要想在 JavaScript 模块中引入 CSS 文件,就要用到 style-loadercss-loader

npm install --save-dev style-loader css-loader
module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
        ]
    },
}

loader 是逆序链式调用的,链中的每个 loader 都将对资源进行转换,并将转换后的资源传递给下一个 loader 进行处理,Webpack 期望链中的最后一个 loader 返回 JavaScript。

以上代码,当遇到以 .css 结尾的文件时,会先使用 css-loader,后使用 style-loader

在浏览器中查看结果:

image.png

2. less 和 sass

要使用 less 或 sass,就需要使用相应的 loader,下面以 less 为例:

npm install less less-loader --save-dev
module.exports = {
    module: {
        rules: [
            {
                test: /\.less$/,
                use: ['style-loader', 'css-loader', 'less-loader']
            }
        ]
    },
}

在浏览器中查看结果:

image.png

三、抽离和压缩 CSS

1. 将 CSS 文件抽离成单独的文件

使用 mini-css-extract-plugin 插件(需要 webpack5 才能正常工作):

npm install mini-css-extract-plugin --save-dev
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader'],
            },
        ]
    },
    plugins: [
        // new MiniCssExtractPlugin()    // 默认打包到 dist 目录下的 main.css
        new MiniCssExtractPlugin({       // 传入配置对象,修改打包目录及文件名
            filename: 'styles/[contenthash].css'
        })
    ],
}

2. 压缩 CSS

使用 css-minimizer-webpack-plugin 插件:

npm install css-minimizer-webpack-plugin --save-dev
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')

module.exports = {
    mode: 'production',  // 开发模式
    optimization: {      // 优化配置
        minimizer: [new CssMinimizerWebpackPlugin()],
    }
}

四、加载 images 图像

内置的 Asset Modules 让我们在 CSS 中可以直接引入图片资源。

style.css:

.block {
    border: 1px solid red;
    width: 200px;
    height: 200px;
    background: url("./assets/svg-1.svg") no-repeat center;
    background-size: 100% auto;
}

入口文件 index.js:

import './style.css'

index.html:

<div class="block"></div>

在浏览器中查看效果:

image.png

五、加载 fonts 字体

内置的 Asset Modules 让我们在 CSS 中可以直接引入字体资源。

webpack.config.js:

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            { 
                test: /\.(woff|woff2|eot|ttf|otf)$/, 
                type: 'asset/resource'
            }
        ]
    },
}

iconfont.css:

@font-face {
  font-family: "iconfont"; /* Project id  */
  src: url('./assets/iconfont.ttf?t=1650766084662') format('truetype');
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-airplane:before { content: "\e8db"; }
.icon-bus:before { content: "\e8dc"; }
.icon-bottle:before { content: "\e8dd"; }
.icon-book:before { content: "\e8de"; }

入口文件 index.js:

import './iconfont.css'

index.html:

<ul>
    <li><span class="iconfont icon-airplane"></span></li>
    <li><span class="iconfont icon-bus"></span></li>
    <li><span class="iconfont icon-bottle"></span></li>
    <li><span class="iconfont icon-book"></span></li>
</ul>

在浏览器中查看效果:

image.png

六、加载数据

JSON 数据在 Webpack 中是默认支持的,如果要加载其他类型的数据,如 CSV、TSV、XML 等,可以使用 csv-loaderxml-loader

npm install --save-dev csv-loader xml-loader

webpack.config.js:

module.exports = {
    module: {
        rules: [
            { 
                test: /\.(csv|tsv)$/, 
                use: 'csv-loader', 
            }, 
            { 
                test: /\.xml$/, 
                use: 'xml-loader', 
            },
        ]
    },
}

入口文件 index.js:

import helloWorld from './hello-world.js'
import data from './assets/data.xml'
import notes from './assets/data.csv'

helloWorld()
console.log('data:', data)
console.log('notes:', notes)

在浏览器中查看效果:

image.png

七、自定义 JSON 模块 parser

通过使用自定义 parser 替代特定的 webpack loader,可以将任何 tomlyamljson5 文件作为 JSON 模块导入。

npm install toml yaml json5 --save-dev

webpack.config.js:

const toml = require('toml')
const yaml = require('yamljs')
const json5 = require('json5')

module.exports = {
    module: {
        rules: [
            { 
                test: /\.toml$/, 
                type: 'json', 
                parser: { 
                    parse: toml.parse, 
                }, 
            },
            { 
                test: /\.yaml$/, 
                type: 'json', 
                parser: { 
                    parse: yaml.parse, 
                }, 
            },
            { 
                test: /\.json5$/, 
                type: 'json', 
                parser: { 
                    parse: json5.parse, 
                }, 
            },
        ]
    },
}

入口文件 index.js:

import helloWorld from './hello-world.js'
import toml from './assets/json/data.toml'
import yaml from './assets/json/data.yaml'
import json5 from './assets/json/data.json5'

helloWorld()
console.log('toml:', toml)
console.log('yaml:', yaml)
console.log('json5:', json5)

在浏览器中查看效果:

image.png