构建webpack5.x 知识体系:2、基础之样式配置

269 阅读7分钟

这是一个系列文的分享记录,本篇主要是webpack的基础之样式资源的配置,如css、less、sass。加载css,打包样式资源。loader的加载顺序,是怎么加载到head中的。

webpack 开箱即用,可以无需使用任何配置文件。然而,webpack 会假定项目的入口起点为 src/index.js,然后会在 dist/main.js 输出结果,并且在生产环境开启压缩和优化。

webpack文档推荐:webpack.docschina.org/plugins/ter…

正式开始:

预备技能

基本nodejs知识和npm指令

注意:版本问题导致不同,本系列实战中用到的webpack版本是:"webpack": "^5.68.0", "webpack-cli": "^4.9.2",

前置知识

我们知道直接打包样式的时候会报错,在上一篇也有验证,这个时候需要配置loader。那loader是什么呢?

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

Warning

webpack 的其中一个强大的特性就是能通过 import 导入任何类型的模块(例如 .css 文件),其他打包程序或任务执行器的可能并不支持。我们认为这种语言扩展是很有必要的,因为这可以使开发人员创建出更准确的依赖关系图。

在更高层面,在 webpack 的配置中,loader 有两个属性:

  1. test 属性,识别出哪些文件会被转换。

  2. use 属性,定义出在进行转换时,应该使用哪个 loader。

    webpack.config.js

    const path = require('path');module.exports = {
      output: {
        filename: 'my-first-webpack.bundle.js',
      },
      module: {
        rules: [{ test: /.txt$/, use: 'raw-loader' }],
      },
    };
    

    以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:testuse。这告诉 webpack 编译器(compiler) 如下信息:

    “嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 '.txt' 的路径」时,在你对它打包之前,先 use(使用) raw-loader 转换一下。”

    Warning

    重要的是要记住,在 webpack 配置中定义 rules 时,要定义在 module.rules 而不是 rules 中。为了使你便于理解,如果没有按照正确方式去做,webpack 会给出警告。

    Warning

    请记住,使用正则表达式匹配文件时,你不要为它添加引号。也就是说,/.txt$/'/.txt$/'"/.txt$/" 不一样。前者指示 webpack 匹配任何以 .txt 结尾的文件,后者指示 webpack 匹配具有绝对路径 '.txt' 的单个文件; 这可能不符合你的意图。

loader

在上一篇基础概念中有简单介绍了一下loader的概念。

Loader:模块转换器,用于把模块原内容按照需求转换成新内容。比如:让 webpack 能够去处理那些非 JS 的文件,比如样式文件、图片文件(webpack 自身只理解JS)

loader的常用属性

  • test:匹配处理文件的扩展名的正则表达式
  • use:loader名称,就是你要使用模块的名称
  • include/exclude:手动指定必须处理的文件夹或屏蔽不需要处理的文件夹
  • query:为loaders提供额外的设置选项

loader三种写法

1、loader

loader:['style-loader','css-loader']

2、use

  use:['style-loader','css-loader']

3、use+loader

use: [{
        loader: 'style-loader',
        options: {
            insert:'top'
        }
        },'css-loader'
     ]

打包样式资源

我们在前端不可避免的要用到样式资源css,或者less、sass来让我们的页面更美观。那这些资源该如何处理打包呢?

1、创建文件

在上一篇已经创建了文件,src/index.css和src/index.less

2、下载安装包

为了webpack能够识别css文件,我们需要配置css-loader,所以需要安装css-loader包

npm install -D css-loader

3、修改配置文件webpack.config.js

const path = require('path');
module.exports = {
    // webpack 配置
    // 入口起点
    entry: './src/index.js',
    // 输出
    output: {
        //  输出路径 __dirname nodejs变量 代表当前文件的目录绝对路径
        path: path.resolve(__dirname, 'build'),
        // 输出ming
        filename: 'built.js'
    },
    // loader 配置
    module: {
        rules: [
​
            {
                //匹配以css结尾的文件
                test: /.css$/,
                //采用css-loader进行处理,让webpack能够识别
                loader: 'css-loader'
            }
​
        ]
    },
    // plugins 的配置 
    plugins: [
​
​
    ],
​
​
    mode: 'development', //开发模式
    // mode: 'production', //生产模式
}

4、运行

  • 再执行webpack编译

image.png

我们可以看到成功了。

  • 在查看built.js

image.png

css样式文件打包进去了。

  • 在查看浏览器。

image.png

🤷‍♀️问题:哇哦, 此时样式并没有生效。页面背景没有变色。这是怎么回事呢?

原来css-loader只负责把css处理为webpack能够识别的字符串,要想样式生效,就要借助于style-loader

安装style-loader

npm install -D style-loader

修改配置文件webpack.config.js

const path = require('path');
module.exports = {
    // webpack 配置
    // 入口起点
    entry: './src/index.js',
    // 输出
    output: {
        //  输出路径 __dirname nodejs变量 代表当前文件的目录绝对路径
        path: path.resolve(__dirname, 'build'),
        // 输出ming
        filename: 'built.js'
    },
    // loader 配置
    module: {
        rules: [
​
            {
                //匹配以css结尾的文件
                test: /.css$/,
                //采用css-loader进行处理,让webpack能够识别 
                //单个loader使用loader属性
                //loader: 'css-loader'
​
                //多个loader处理一个文件,需要使用use
                //use属性的执行顺序为逆序,也就是数组尾->数组首的顺序
                use: ['style-loader', 'css-loader']
​
​
            }
​
        ]
    },
    // plugins 的配置 
    plugins: [
​
​
    ],
​
​
    mode: 'development', //开发模式
    // mode: 'production', //生产模式
}

ps:代码讲解:

  • use属性的执行顺序为逆序,也就是数组尾->数组首的顺序,就是先执行'css-loader'在执行'style-loader'
  • css-loader 将css文件变成commonjs模块加载到js中 里边内容是样式字符串
  • style-loader 创建style标签,将js中的样式资源插入进行,添加到head中生效

运行webpack

image.png

查看浏览器:

image.png

可以看到在head里动态插入了style标签,正好就是我们index.css的内容

5、使用less

  • 修改./src/index/js
//./src/index/js
import dataJson from './data.json';
import './index.css';
import './index.less';
// 引入样式文件
function add(x, y) {
  return x + y;
}
console.log(add(1, 2));
console.log(dataJson, 'dataJson');
  • 修改完毕,再执行webpack编译

image.png 报错!!!

  • 原因是,webpack不识别.less文件的,此时我们还需要引入less-loader, 因为less-loader又依赖less进行编译,我们呢需要安装两个依赖包
npm install  less less-loader -D
  • 修改webpack.config.js
const path = require('path');
module.exports = {
    // webpack 配置
    // 入口起点
    entry: './src/index.js',
    // 输出
    output: {
        //  输出路径 __dirname nodejs变量 代表当前文件的目录绝对路径
        path: path.resolve(__dirname, 'build'),
        // 输出ming
        filename: 'built.js'
    },
    // loader 配置
    module: {
        rules: [
​
            {
                //匹配以css结尾的文件
                test: /.css$/,
                //采用css-loader进行处理,让webpack能够识别 
                //单个loader使用loader属性
                //loader: 'css-loader'
​
                //多个loader处理一个文件,需要使用use
                //use属性的执行顺序为逆序,也就是数组尾->数组首的顺序
                use: ['style-loader', 'css-loader']
​
​
            },
            {
                //匹配以.less结尾的文件
                test: /.less$/,
                //  less-loader 讲less文件变成成css文件 (需要下载两个依赖 less和less-loder)
                // css-loader 将css文件变成commonjs模块加载到js中 里边内容是样式字符串
                // style-loader 创建style标签,将js中的样式资源插入进行,添加到head中生效
                // use数组执行顺序是倒叙,就是先执行'style-loader',在执行'css-loader'在执行'style-loader'
                use: ['style-loader', 'css-loader', 'less-loader']
            }
​
        ]
    },
    // plugins 的配置 
    plugins: [
​
​
    ],
​
​
    mode: 'development', //开发模式
    // mode: 'production', //生产模式
}
  • 修改完毕,再执行webpack编译

发现打包成功,在查看浏览器,字体也变颜色了~~~

image.png

6、打包sass

通过上边的less我们知道了,需要特殊安装相应的loader,而sass也是需要安装相应的sass的loader的。

sass-loader ,因为sass-loader又依赖sass进行编译,我们呢需要安装两个依赖包

npm install sass-loader sass -D
  • 新增sass文件

./src/index.scss

#title {
    font-size: 20px;
}
  • 修改./src/index.js
// ./src/index/js
import dataJson from './data.json';
import './index.css';
import './index.less';
import './index.scss';
// 引入样式文件
function add(x, y) {
  return x + y;
}
console.log(add(1, 2));
console.log(dataJson, 'dataJson');
  • 修改配置文件webpack.config.js
const path = require('path');
module.exports = {
    // webpack 配置
    // 入口起点
    entry: './src/index.js',
    // 输出
    output: {
        //  输出路径 __dirname nodejs变量 代表当前文件的目录绝对路径
        path: path.resolve(__dirname, 'build'),
        // 输出ming
        filename: 'built.js'
    },
    // loader 配置
    module: {
        rules: [
​
            {
                //匹配以css结尾的文件
                test: /.css$/,
                //采用css-loader进行处理,让webpack能够识别 
                //单个loader使用loader属性
                //loader: 'css-loader'
​
                //多个loader处理一个文件,需要使用use
                //use属性的执行顺序为逆序,也就是数组尾->数组首的顺序
                use: ['style-loader', 'css-loader']
​
​
            },
            {
                //匹配以.less结尾的文件
                test: /.less$/,
                //  less-loader 讲less文件变成成css文件 (需要下载两个依赖 less和less-loder)
                // css-loader 将css文件变成commonjs模块加载到js中 里边内容是样式字符串
                // style-loader 创建style标签,将js中的样式资源插入进行,添加到head中生效
                // use数组执行顺序是倒叙,就是先执行'style-loader',在执行'css-loader'在执行'style-loader'
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            {
                //匹配以.scss结尾的文件
                test: /.scss$/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            }
​
        ]
    },
    // plugins 的配置 
    plugins: [
​
​
    ],
​
​
    mode: 'development', //开发模式
    // mode: 'production', //生产模式
}
  • 修改完毕,再执行webpack编译

发现打包成功,在查看浏览器,字体变大了~~~

image.png

7、其他常用样式

常用的样式资源主要是css、less、sass、styus

上边已经介绍了css、less、sass;

处理styus文件用到的loader主要是style-loader、css-loader、styus-loader (需要安装styus)

跟之前一样的步骤,我就不再这赘述了。

ps:删除原来的插件

为了使每次打包后删除原来的文件重新生成新的文件,需要用到clean-webpack-plugin插件

安装

npm install clean-webpack-plugin -D

修改配置

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
    // webpack 配置
    // 入口起点
    entry: './src/index.js',
    // 输出
    output: {
        //  输出路径 __dirname nodejs变量 代表当前文件的目录绝对路径
        path: path.resolve(__dirname, 'build'),
        // 输出ming
        filename: 'built.js'
    },
    // loader 配置
    module: {
        rules: [
​
            {
                //匹配以css结尾的文件
                test: /.css$/,
                //采用css-loader进行处理,让webpack能够识别 
                //单个loader使用loader属性
                //loader: 'css-loader'
​
                //多个loader处理一个文件,需要使用use
                //use属性的执行顺序为逆序,也就是数组尾->数组首的顺序
                use: ['style-loader', 'css-loader']
​
​
            },
            {
                //匹配以.less结尾的文件
                test: /.less$/,
                //  less-loader 讲less文件变成成css文件 (需要下载两个依赖 less和less-loder)
                // css-loader 将css文件变成commonjs模块加载到js中 里边内容是样式字符串
                // style-loader 创建style标签,将js中的样式资源插入进行,添加到head中生效
                // use数组执行顺序是倒叙,就是先执行'style-loader',在执行'css-loader'在执行'style-loader'
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            {
                //匹配以.scss结尾的文件
                test: /.scss$/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            }
​
        ]
    },
    // plugins 的配置 
    plugins: [
        new CleanWebpackPlugin(),
​
    ],
​
​
    mode: 'development', //开发模式
    // mode: 'production', //生产模式
}

运行webpack

ps:注意遇到的坑啊:

如果错误提示:

TypeError: CleanWebpackPlugin is not a constructorn

那就是可能是你的clean-webpack-plugin版本;、

const CleanWebpackPlugin = require('clean-webpack-plugin');
 
module.exports = {
    plugins: [
        new CleanWebpackPlugin(['dist'])
    ]
};

正确的是:

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
 
module.exports = {
    plugins: [
        new CleanWebpackPlugin()
    ]
}

哎呀,把整个build文件内部的文件都删了,index.html也删除了,其实我们工作中,index.html并不在build文件中,这个文件就是每次自己创建的,html在外部,应该每次自己打包进去,该如何操作呢?我们在一下篇中将讲解

第二种方案:推荐

我们使用 output.clean 配置项实现这个需求。

这个明显比较简单,因为不需要下载相关依赖模块,引入,使用,直接让output.clean=true

修改配置:webpack.config.js

 // 输出
        output: {
            //  输出路径 __dirname nodejs变量 代表当前文件的目录绝对路径
            path: resolve(__dirname, 'build'),
            // 输出ming
            filename: 'built.js',
            clean:true
        },

可以看到简单,推荐使用这种,减少plugin

感谢

到此,本篇介绍到此结束,之后将陆续整理 webpack 知识体系的内容分享,尽情期待,感谢您的阅读~~