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举例。
那么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};`;
}