手写webpack系列一:了解认识loader-utils

本文是手写webpack系列的第一篇,主要介绍webpack的module和rules,重点讲解loader-utils的作用和常用API,如parseQuery、getOptions、stringifyRequest等,通过实例演示其用法,为理解webpack核心组件打下基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Created By JishuBao on 2019-03-29 12:38:22
Recently revised in 2019-04-01 12:38:22

 

  欢迎大家来到技术宝的掘金世界,您的star是我写文章最大的动力!GitHub地址     

文章简介:

1、webpack module简介

2、rules的使用

3、loader-utils是什么?

4、api实现

5、未完待续

一、webpack module简介

现在前端的技术日新月异,现在比较火的前端打包工具! webpack,我想各位小伙伴应该也有所了解,那么你知道如何手写webpack吗,作为手写webpack系列的第一篇文章,我将带领大家逐步走进webpack的世界。webpack中有一个及其重要的概念loader,那什么是loader呢?在webpack的官网中,我们可以看到这样一行对Loader的定义,原来是处理js后缀文件名除外的文件。

webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。你可以使用 Node.js 来很简单地编写自己的 loader。

在loader中,咱们可以通过关键词this访问当前执行环境的所有变量

1、同步回调时,可以执行this.callback(),默认第一个参数是err错误信息(不报错时返回null),第二个参数是解析完模块后的返回结果,第三个参数是sourceMap(可选),在链式调用时可将sourceMap传给下一个loader;

2、异步回调时,可以执行this.async(),参数同上;

3、this.addDependency(filePath)可以把对应filePath的文件添加到webpack的依赖树,webpack可以监测它的文件变动并刷新(filePath要是绝对路径);

4、this.resolve()可以解析处理文件路径;

5、this.query:获取loader的配置选项。

了解或者使用过webpack的小伙伴都知道loader是使用在weboack的module里面的,用于处理module文件的。我们来看下module属性对应的一些常用api!

  • module.noParse

noParse 配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析和处理,这样做的好处是能提高构建性能。 原因是一些库例如 jQuery 、ChartJS 它们庞大又没有采用模块化标准,让 Webpack 去解析这些文件耗时又没有意义。noParse 是可选配置项,类型需要是 RegExp、[RegExp]、function 其中一个.例如想要忽略掉 jQuery 、ChartJS,可以使用如下代码:

// 使用正则表达式
noParse: /jquery|chartjs/

// 使用函数,从 Webpack 3.0.0 开始支持
noParse: (content)=> {
  // content 代表一个模块的文件路径
  // 返回 true or false
  return /jquery|chartjs/.test(content);
}
复制代码
  • module.rules

配置模块的读取和解析规则,通常用来配置 Loader。其类型是一个数组,数组里每一项都描述了如何去处理部分文件。 配置一项 rules 时大致通过以下方式:

1.条件匹配:通过 test 、 include 、 exclude 三个配置项来命中 Loader 要应用规则的文件。

2.应用规则:对选中后的文件通过 use 配置项来应用 Loader,可以只应用一个 Loader 或者按照从后往前的顺序应用一组 Loader,同时还可以分别给 Loader 传入参数。

3.重置顺序:一组 Loader 的执行顺序默认是从右到左执行,通过 enforce 选项可以让其中一个 Loader 的执行顺序放到最前或者最后。 下面来通过一个例子来说明具体使用方法:

module: {
  rules: [
    {
      // 命中 JavaScript 文件
      test: /\.js$/,
      // 用 babel-loader 转换 JavaScript 文件
      // ?cacheDirectory 表示传给 babel-loader 的参数,用于缓存 babel 编译结果加快重新编译速度
      use: ['babel-loader?cacheDirectory'],
      // 只命中src目录里的js文件,加快 Webpack 搜索速度
      include: path.resolve(__dirname, 'src')
    },
    {
      // 命中 SCSS 文件
      test: /\.scss$/,
      // 使用一组 Loader 去处理 SCSS 文件。
      // 处理顺序为从后到前,即先交给 sass-loader 处理,再把结果交给 css-loader 最后再给 style-loader。
      use: ['style-loader', 'css-loader', 'sass-loader'],
      // 排除 node_modules 目录下的文件
      exclude: path.resolve(__dirname, 'node_modules'),
    },
    {
      // 对非文本文件采用 file-loader 加载
      test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
      use: ['file-loader'],
    },
  ]
}
复制代码

在 Loader 需要传入很多参数时,你还可以通过一个 Object 来描述,例如在上面的 babel-loader 配置中有如下代码:

use: [
  {
    loader:'babel-loader',
    options:{
      cacheDirectory:true,
    },
    // enforce:'post' 的含义是把该 Loader 的执行顺序放到最后
    // enforce 的值还可以是 pre,代表把 Loader 的执行顺序放到最前面
    enforce:'post'
  },
  // 省略其它 Loader
]
复制代码

上面的例子中 test include exclude 这三个命中文件的配置项只传入了一个字符串或正则,其实它们还都支持数组类型,使用如下:

{
  test:[
    /\.jsx?$/,
    /\.tsx?$/
  ],
  include:[
    path.resolve(__dirname, 'src'),
    path.resolve(__dirname, 'tests'),
  ],
  exclude:[
    path.resolve(__dirname, 'node_modules'),
    path.resolve(__dirname, 'bower_modules'),
  ]
}
复制代码

数组里的每项之间是或的关系,即文件路径符合数组中的任何一个条件就会被命中。

  • parser

因为 Webpack 是以模块化的 JavaScript 文件为入口,所以内置了对模块化 JavaScript 的解析功能,支持 AMD、CommonJS、SystemJS、ES6。 parser 属性可以更细粒度的配置哪些模块语法要解析哪些不解析,和 noParse 配置项的区别在于 parser 可以精确到语法层面, 而 noParse 只能控制哪些文件不被解析。 parser 使用如下:

module: {
  rules: [
    {
      test: /\.js$/,
      use: ['babel-loader'],
      parser: {
      amd: false, // 禁用 AMD
      commonjs: false, // 禁用 CommonJS
      system: false, // 禁用 SystemJS
      harmony: false, // 禁用 ES6 import/export
      requireInclude: false, // 禁用 require.include
      requireEnsure: false, // 禁用 require.ensure
      requireContext: false, // 禁用 require.context
      browserify: false, // 禁用 browserify
      requireJs: false, // 禁用 requirejs
      }
    },
  ]
}
复制代码

二、rules的使用

根据上文我们已经基本了解了rule的使用,里面放一些loader处理对应的文件。随意打开一个文件,这里已常用的loader file-loader举例。

我们如果打开大部分loader的源码,基本上你可以发现一个规律,基本上每个loader里面都有这样一句,引入了 loader-utils这个工具类。

那么utils-loader究竟是什么呢?

三、loader-utils是什么?

loader-utils是一个webpack工具类,通过一些方法配合loader处理文件。让我们一起来解读一下。 本文旨在通过手写loader-utils来了解loader-utils的内容。新建文件夹loader-utils,执行命令npm init初始化一个npm项目

npm init
复制代码

新建index.js作为webpack打包入口文件,内容为空。新建webpack.conf.js作为webpack配置文件,内容如下:

const path=require('path');
//path是node.js的一个模块,提供了一些用于处理文件路劲的小工具
module.exports={
    entry:{
        main:"./index.js"//入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的
    },
    resolve:{
    },
    module:{
        rules:[
            {
                test:/\.js$/,//通过loader来预处理文件 允许你打包除了js之外的任何静态资源
                use:[
                    {
                        loader:path.resolve('./loader-util.js'),
                        options:{
                            name:'wjb'
                        }
                    }
                ]
            },
        ]
    },
    plugins:[
        
    ]

}
复制代码

新建loader-utils.js文件作为webpack解析的loader。内容如下:

"use strict";

const loaderUtils=require("loader-utils");

function loader(content) {

    var publicPath="a";
   
    console.log('进入了loader内部');

    return `${publicPath};`;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值