专栏首页前端技术分享|前沿资讯|读书分享webpack实战——预处理器(loader)【上篇】

webpack实战——预处理器(loader)【上篇】

写在前面

这是webpack实战系列笔记的第5篇记录,前几篇记录如下:

  • 打包第一个应用
  • 模块化与模块打包
  • 资源输入与输出
  • 一切皆模块

上一篇简单描述了一切皆模块的思想,学以致用,来实践下~

1. 关于 loader

每个loader本质上都是一个函数,可用公式表达其本质:

output = loader(input)

  • input可能是工程源文件的字符串,也可能是上一个loader转化后的结果,包含:
    • 字符串(转化后的结果)
    • source map
    • AST对象(抽象语法树)
  • output同样包含上述几种信息。如果是最后一个loader,其结果直接被送到webpack中做后续处理;否则作为下一个loader的input向后传递

举个例子

当使用 babel-loader 将 ES6+ 代码转化为 ES5 时,带入公式:

ES5 = babel-loader(ES6+)

上述描述说过,loader本身是一个函数那么loader是如何工作的呢?

module.exports = function loader (content, map, meta) {
    var callback = this.async();
    var result = handler(content, map, meta);
    callback(
        null,   // error
        result.content, // 转换后的内容
        result.map, // 转换source-map
        result.meta // 转换后的AST
    )
}

可以看出,该函数对接受到的内容进行转换,然后返回转换后的结果。

2. loader配置

那在应用层面应该如何实施呢?

一切皆模块中说过静态资源的类型是各式各样的,比如静态HTML/CSS/JS、图片字体音视频等,webpack如何处理这各类资源呢?ok,loader的应用场景来了。

loader,字面意思是装载器,但在webpack中实际用途则是预处理器:webpack本身只认识JavaScript,对于其他类型的资源必须先定义一个或多个loader对其进行转译,输出为webpack能够接收的形式再继续进行,因此loader做的实际上是一个预处理的工作。

2.1 引入

那loader到底应该如何使用呢?举例要在js中引入css文件:

// index.js
import './assets/common/css'
/* common.css */

body{
    width: 100vw;
    height: 100vh;
    text-align: center;
    background: gray;
}

ok,现在我们执行打包操作,build一下,会发现在终端报错:

出现报错

为解决报错,我们需要用到的就是loader了~

可以在上图报错内容除看到,提示我们没找到合适的loader来处理,并且给出css-loader提示,我们按提示安装:

// npm
npm install css-loader

// 或者 yarn   与npm二选一即可
yarn add css-loader

安装完成后,仍需在webpack.config.js中进行loader配置:

const path = require('path')

module.exports = {
    entry: {
        index: './src/index.js',
    },

    output: {
        filename: '[name].js'
    },
    mode: 'development',

    // loader配置
    module: {
        rules: [
            // css
            {
                test: /\.css$/,
                use: ['css-loader']
            }
        ]
    }
}

可以看到,对loader进行配置,配置项都在module对象中的rules模块。rules模块是一个数组,代表了要对模块进行处理的规则。在此处,我们使用到的规则有testuse

  • test:接收一个正则表达式或者一个元素为正则表达式的数组,只有正则匹配上的模块才会使用本条规则;
  • use:接收一个数组,代表该规则所使用的loader。

然后进行打包操作:

// npm
npm run build

// 或者 yarn   与npm二选一即可
yarn build

然后发现,打包错误解决。

但,新的问题出现了:此时我们在浏览器打开index.html,发现样式并没有生效。原因是css-loader 的作用是处理css的加载语法而不是做style的样式渲染,因此我们需要添加一个 style-loader 来进行样式渲染。

2.2 链式loader

在上面我们说了需要在引入一个 style-loader 来进行样式渲染处理,先安装:

// npm
npm install style-loader

// 或者 yarn   与npm二选一即可
yarn add style-loader

接着搭配之前的webpack配置,做一些修改:

module.exports = {
    ...

    // loader配置
    module: {
        rules: [
            // css style
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    }
}

可以看到,我们将style-loader写在了use的数组中,并且细心的朋友可能发现写在了css-loader之前,这就是链式loader

那么为什么要区分顺序呢?在前面描述关于loader的公式中我们介绍过:

output = loader(input)

在链式webpack打包中,是按照数组从后往前的顺序将资源交给loader去处理,因此最后生效的应该放在前面。

此时,我们在执行打包操作,然后可以在浏览器中看到index.html页面加载了样式:

样式加载成功

2.3 其他配置

2.3.1 options配置

有些loader会有专门的配置项,形式上可能会有一些不同,如:

module.exports = {
    ...

    // loader配置
    module: {
        rules: [
            // css
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    {
                        loader: 'css-loader',
                        options: {
                            // css-loader相关配置
                            ...
                        }
                    }
                ]
            }
        ]
    }
}

当然,具体配置项参数和值则需要参考相应loader的文档来进行配置,用时参阅该loader文档即可。

2.3.2 exclude 和 include

从字面意思理解,这两个分别是用来排除或者包含指定目录下模块的。

如:

module.exports = {
    ...

    // loader配置
    module: {
        rules: [
            // css
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader'],
                exclude: /node_modules/
            }
        ]
    }
}

上面置顶了exclude: /node_modules/,则代表着该目录下的所有模块都不会被此条规则限制,也就是说node_modules中的模块不会执行该规则。

同样,include用途与此类似:

module.exports = {
    ...

    // loader配置
    module: {
        rules: [
            // css
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader'],
                include: /src/
            }
        ]
    }
}

可以看到此处使用的是include,代表该规则只对正则匹配到的模块生效,也就是说只对src下的模块生效。

excludeinclude同时存在的情况下,exclude优先级更高!

通常情况下,在使用loader时,需要配置它,以此来加速打包速度,不配置的话打包会将所有模块打包,可能拖慢整体的打包速度。

2.3.3 resource 与 issuer

有时候,我们会在项目中看到关于resourceissuer的相关配置,那么这两个配置是做什么的呢?

其实与excludeinclude类似,都是用于规定模块作用范围的配置。但是区别是excludeinclude对规则的作用范围更加的精确。如:

// index.js
import './src/common.css'

在webpack中,我们认为被加载模块是resource,加载者是issuer,在上述代码中,css作为被加载者,而index作为加载者。

那么具体如何使用呢?

module.exports = {
    ...

    // loader配置
    module: {
        rules: [
            // css
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader'],
                exclude: /node_modules/,
                issuer: {
                    test: /\.js$/,
                    include: /src/pages/
                }
            }
        ]
    }
}

在上面我们看到配置了issuer对象,限制是让src/pages目录下js可以引用使用规则css-loader

我们看完后会发现一个风格问题:代码可读性较差。可以稍加改善:

module.exports = {
    ...

    // loader配置
    module: {
        rules: [
            // css
            {
                use: ['style-loader', 'css-loader'],
                resource: {
                    test: /\.css$/,
                    exclude: /node_modules/
                },
                issuer: {
                    test: /\.js$/,
                    exclude: /node_modules/
                }
            }
        ]
    }
}

通过添加resource对象来讲外层配置包裹起来,区分resource和issuer的规则,看上去即可一目了然,但实际本质一样。可选择一种风格进行配置。

小结

本篇介绍了loader的作用和意义,以及在项目中实际使用时的一些配置,如引入、使用过程、链式loader、loader的配置等,从各大小方面均能做到对项目有优化或效率提升。下一篇介绍几个项目常用loader以及如何自定义loader。

本文分享自微信公众号 - 流眸(zxm0146),作者:流眸

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-07-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • webpack实战——预处理器(loader)【下篇】

    在上一篇中根据一切皆模块的思想,学习了解了loader:概述、引入、配置及使用。本篇接着上篇的话题,讲述常用loader。

    流眸
  • webpack实战——样式预处理

    在目前的前端项目中,经常可以看到使用SASS和LESS来对CSS进行处理,那么在webpack中如何配置?

    流眸
  • vue白屏优化方案

      vue项目打包后,在非首次线上替换dist文件时,某些手机/浏览器在之后首次打开页面,可能出现白屏情况。那么该问题产生原因是什么呢?我们又该如何应对呢?

    流眸
  • 我已经会手写没用的loader了

    webpack的loader配置应该谁都会,讲道理,我们会使用loader,会配置loader就够了。今天只是了解loader的基本概念和基本的运行原理,了解了...

    wade
  • Webpack4教程 - 第二部分,使用loader处理scss,图片以及转换JS

    今天继续我们的Webpack 4入门教程。在介绍了Webpack的基本概念之后,是时候更深入一点了。这次我们会涉及Webpack中非常强大的一个东西:loade...

    葡萄城控件
  • Webpack4干货分享(二),使用loader处理scss,图片以及转换JS

    今天继续我们的Webpack 4入门教程。在介绍了Webpack的基本概念之后,是时候更深入一点了。这次我们会涉及Webpack中非常强大的一个东西:loade...

    葡萄城控件
  • Webpack Loader

    Webpack不认识CSS(无法直接处理),就需要先由Loader加工一遍(预处理)

    ayqy贾杰
  • 手把手教你撸一个 Webpack Loader

    文:小 boy(沪江网校Web前端工程师) 本文原创,转载请注明作者及出处 ? 经常逛 webpack 官网的同学应该会很眼熟上面的图。正如它宣传的一样,w...

    iKcamp

扫码关注云+社区

领取腾讯云代金券