webpack5基础应用(4)

2023-11-13 267 0

一. 管理资源

webpack除了资源模块之外,还可以通过loader去引入其他类型文件。loader可以让webapck其他类型的文件,并且将这些文件转换为有效的模块以供我们应用程序的使用。

1. 什么是loader

loader定义有两个重要的属性:test属性识别哪些文件被转换;use定义转换的时候应该使用哪个loader来进行转化。

2. 加载CSS

src下新建style.css文件,添加css代码:

.hello {
    color: red;
}

在index.js中引入style.css:

import './style.css';

执行npx webpack命令之后出现了错误,无法识别我们的css文件:

我们需要通过loader解决这个问题。

1)安装css-loader

$ npm install css-loader -D

2)在webpack.config.js中配置

module.exports = {
    ... ...

    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                test: /\.css$/,
                use: 'css-loader'
            }
        ],
    },
};

执行npx webpack命令,打包解析成功:

在index.js中,body元素上使用一下css类型:

document.body.classList.add('hello');

再次执行打包命令。启动webpack服务,在浏览器中查看,发现body元素上面的确有名为hello的class类,但是文字并没有变为红色。

检查发现head标签里面并没有通过link去加载外部的css,也没有style标签去定义内部的css,因此样式没有生效。

3)安装style-loader

$ npm install style-loader -D

style-loader会帮我们将css放置到页面上。

4)在webpack.config.js中配置

module.exports = {
    ... ...

    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                test: /\.css$/,
                // use: 'css-loader'
                use: ["style-loader", "css-loader"],
                //先使用css-loader识别css文件,再通过style-loader引入css文件
            }
        ],
    },
};

执行打包命令,启动服务在浏览器查看效果,文字颜色变红,css样式也加载进去了:

需要注意的是:配置文件里面style-loader 和css-loader的顺序一定不能颠倒。先执行css-loader再执行style-loader,也就是说这个是从后往前加载的。webpack支持loader的链式调用,链式的每一个loader都可以对我们的源进行转换,而且转换是逆序的。第一个loader会将结果或者转换后的源传递给下一个loader。

我们以前了解过css还有些预处理的工具。比如像sass,less,stylus等等。那么我们的loader能不能解析sass或者less这样的文件呢?

5)安装less-loader less

$ npm install less-loader less -D

6)修改webpack.config.js

module.exports = {
    ... ...

    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                test: /\.css$/,
                // use: 'css-loader'
                use: ["style-loader", "css-loader", "less-loader"],
                //先使用css-loader识别css文件,再通过style-loader引入css文件
            }
        ],
    },
};

less-loader要放在最后,因为less-loader要去解析css文件,再将解析的css文件传递给css-loader。那么less-loader可以使用.css的扩展名吗?当然也是可以的。但有些时候我们也会去定义一个.less这样的less文件,所以配置的扩展名可以调整一下:

module.exports = {
    ... ...

    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                // test: /\.css$/,
                // use: 'css-loader'
                test: /\.(css|less)$/,
                use: ["style-loader", "css-loader", "less-loader"],
                //先使用css-loader识别css文件,再通过style-loader引入css文件
            }
        ],
    },
};

在src下新建style.less文件,编写代码:

@color: #f9efd4;
body {
    background-color: @color;
}

在index.js里面导入模块:

import './style.less'

执行编译命令,启动服务在浏览器查看,发现背景色加进去了,head标签里面多了个style标签:

3. 抽离和压缩CSS

上面通过loader成功加载了css,但是现在的代码是跟html在一起的,能不能把style里面的代码放置到一个单独的文件里,通过link标签去加载它呢?这个功能需要用一个插件来帮忙。

1)安装mini-css-extract-plugin

$ npm install mini-css-extract-plugin -D

需要注意的是这个插件是基于webpack5构建的,也就是说如果想使用它必须得在webpack5环境下才可以。

2)在webpack.config.js中引入插件

//引入mini-css-extract-plugin插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 
module.exports = {
    ... ...
    //插件配置
    plugins: [
        ... ...
        //实例化插件
        new MiniCssExtractPlugin(),
    ],
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                // test: /\.css$/,
                // use: 'css-loader'
                test: /\.(css|less)$/,
                // use: ["style-loader", "css-loader", "less-loader"],
                //先使用css-loader识别css文件,再通过style-loader引入css文件
                use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
            },
        ],
    },
};

打包编译之后,dist下面多了main.css文件:

这个文件把两个css文件中的代码都合并到一个css文件里了。

打开app.html,发现没有了style标签,但多了一个link标签:

启动服务在浏览器查看,显示正常:

默认main.css打包到了dist根目录下面,那么能不能指定这个css所在的文件夹和文件名称呢?

修改webpack.config.js配置:

//引入mini-css-extract-plugin插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 
module.exports = {
    ... ...
    //插件配置
    plugins: [
        ... ...
        //实例化插件
        new MiniCssExtractPlugin({
            filename: 'styles/[contenthash].css'
        })
    ],
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                // test: /\.css$/,
                // use: 'css-loader'
                test: /\.(css|less)$/,
                // use: ["style-loader", "css-loader", "less-loader"],
                //先使用css-loader识别css文件,再通过style-loader引入css文件
                use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
            },
        ],
    },
};

编译打包后,main.css文件不见了,dist下多了一个styles文件夹,里面有个css文件:

启动服务在浏览器查看,显示正常:

3)安装css-minimizer-webpack-plugin插件压缩css

$ npm install css-minimizer-webpack-plugin -D

4)在配置文件中加载插件

//引入css-minimizer-webpack-plugin插件
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
    ... ...
    // mode: "development", //开发模式
    mode: "production", //生产模式
    ... ...
    ... ...
    //优化
    optimization: {
        minimizer: [
            //实例化插件
            new CssMinimizerPlugin()
        ],
    },
};

打包解析后,发现css文件被压缩了:

4. 加载images图像

如何在css里面加载图片资源?

在style.css里面定义background-image样式:

.block-bg {
    background-image: url(./assets/img02.svg) !important;
}

给block添加样式:

const block = document.createElement("div");
block.classList.add('block-bg');
block.textContent = exampleTxt;
document.body.appendChild(block);

打包编译后,css里面成功加载一个base64的url:

启动服务在浏览器查看,图片成功显示:

5. 加载fonts字体

在css3中新增了一个功能叫webfont,我们可以在css中加载font字体库,然后我i吗可以在代码中定义自己的icon图标,那如何去加载字体这样的资源呢?我们之前的asset module资源模块可以做。资源模块其实可以用于加载任何资源文件包括字体。

在webpack.config.js中添加资源配置:

module.exports = {
   ... ... 
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                type: 'asset/resource'
            }
        ],
    },
    ... ...
};

准备一个iconfont.ttf文件:

在style.css中载入字体文件:

@font-face {
    font-family: 'iconfont';
    src: url(./assets/iconfont.ttf) format('truetype');
}

.icon {
    font-family: 'iconfont';
    font-size: 30px;
}

在html元素上使用:

const span = document.createElement("span");
span.classList.add('icon');
span.innerHTML = '';
document.body.appendChild(span);

打包编译,启动服务在浏览器查看,正常显示:

6. 加载数据

webpack除了加载图片,字体等之外,还可以加载数据。如json文件,CSV,TSV和XML等。类似与nodejs,json支持实际上是内置的,也就是说 import data from './data.json' 默认将正常运行。要导入CSV,TSV和XML可以使用csv-loader和xml-loader。

1)准备两个文件data.xml和data.csv文件

data.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<note>
    <to>Mary</to>
    <form>John</form>
    <heading>Reminder</heading>
    <body>Call Cindy on Tuesday</body>
</note>

data.csv文件:

to,from,heading,body
Mary,John,reminder,Call Cindy on Tuesday
Zoe,Bill,reminder,Buy oraneg juice
Autumn,Lindsey,Letter,I miss you

2)安装csv-loader和xml-loader插件

$  npm install csv-loader xml-loader -D

3)修改webpack.config.js配置

module.exports = {
    ... ...
    //资源模块配置
    module: {
        // 规则配置,数组里面配置多个对象去加载不同类型的资源文件
        rules: [
            ... ...
            {
                test: /\.(csv|tsv)$/, //csv以逗号分隔,tsv以type分隔
                use: 'csv-loader'
            },
            {
                test: /\.xml$/,
                use: 'xml-loader'
            }
        ],
    },
    ... ...
};

在index.js引入模块并打印:

import Data from './assets/data.xml';
import Notes from "./assets/data.csv";
console.log(Data);
console.log(Notes);

打包编译,启动服务在浏览器查看,浏览器控制台打印了两个对象:

由此可以看到,data.xml会转换为js对象,data.csv会转化为数组。

7. 自定义JSON模块parser

通过使用自定义 parser 替代特定的webpack loader,可以将任何 toml,yaml或者 json5 文件作为json模块导入。

1)首先准备几个文件

data.yaml文件(文件有key有value,通过缩进完成子项的设置)

title: YAML Example
owner:
  name: Tom Preston-Werner
  organization: Github
  bio: |-
    GitHub Cofounder & CEO
    Likes tater tots and beer.
  dob: 1979-05-27T07:32:00.000Z

data.taml文件(通过key=value的形式,子项通过中括号的形式定义):

title = "TOML EXamples"

[owner]
name = "Tom Preston-Werner"
organization = "Github"
bio = "Github cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z

data.json5文件(json格式的升级,json格式文件不能加注释,并且key要用双引号,但json5格式不仅可以加注释,key也可以不用双引号,value可以使用单引号,还可以使用类似\n,\r等转义字符):

{
    //comment
    title: 'JSON5 Example',
    owner: {
        name: 'Tom Preston-Werner',
        organization: 'Github',
        bio: 'Github Cofounder & CEO\n\
            Likes tater tots and beer.'
        dob: '1979-05-27T07:32:00.000Z',
    }
}

2)安装模块toml,yaml,json5

$ npm install toml yaml json5 -D

3)在webpack.config.js里面配置模块

//引入toml
const toml = require('toml');
//引入yaml
const yaml = require('yaml');
//引入json5
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,
                },
            },
        ],
    },
    ... ...
};

4)在index.js中使用

import toml from "./assets/data.toml";
import yaml from "./assets/data.yaml";
import json5 from "./assets/data.json5";

console.log(toml.title);
console.log(toml.owner.name);

console.log(yaml.title);
console.log(yaml.owner.name);

console.log(json5.title);
console.log(json5.owner.name);

启动服务在浏览器查看,打印结果正常显示:

相关文章

webpack基础应用(6)
webpack5基础应用(5)
webpack5基础应用(3)
webpack5基础应用(2)
webpack5 基础应用(1)

发布评论