前端工程化-loader机制
Posted natsu-cc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端工程化-loader机制相关的知识,希望对你有一定的参考价值。
前言:
loader是用来加载处理各种形式的资源,本质上是一个函数,接受文件作为参数,返回转化后的结构。loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 “加载” 模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 javascript,或将内联图像转换为 dataURL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!
loader和plugin区别:
loader是用来对模块的源代码进行转换,而插件目的在于解决 loader 无法实现的其他事,plugin可以在任何阶段调用,能够跨loader进一步加工loader的输出,在构建运行期间,触发事件,执行预先注册的回调,使用compilation对象做一些更底层的事情。
webpack 核心原理:
- webpack会根据配置将一个文件作为打包的入口(一般为js),根据该入口文件的导入语句,解析推断该文件所依赖的资源模块。
- 解析每个资源模块对应的依赖,最后形成的项目关系之间的依赖树。
- webpack会递归这个依赖树,找到每个节点所对应的资源文件。
- 根据配置文件当中的rules属性去找到模块文件所对应的(loader)加载器,然后加载器加载该模块。
- 将加载器的结果放入bundle.js即打包结果当中,从而实现整个项目的打包。
loader解析:
loader的作用就是加载各种类型的资源文件,并且最终打包成bundle.js文件。
举个例子:
项目使用less编写样式,webpack是怎么加载less文件的呢?我们平时也知道需要webpack中配置style-loader,css-loader,less-loader,那它们的作用分别是什么呢?
- less-loader:
less 代码经过 less-loader 的转换成css代码,再包装一层 module.exports,成为一个 JS module。less-loader 本质上只是调用了 less 本身的 render 方法,由于 less.render 是异步的,less-loader 肯定也得异步,所以需要通过回调函数来获取其解析之后的 css 代码。
// less-loader
const less = require('less');
module.exports = function (source)
// 声明此 loader 是异步的
this.async();
let resultCb = this.callback;
less.render(source, (e, output) =>
if (e)
throw `less解析出现错误: $e, $e.stack`;
resultCb("module.exports = " + JSON.stringify(output.css));
);
- style-loader:
css 代码会被插入到 head 标签中,源自于 node-modules/style-loader/addStyle.js ,也就是说,style-loader将css文件的内容嵌入到html文件中。style-loader 返回的字符串里面又包含了2个 require,分别 require 了 addStyle 和 less-loader!style.less。
// style-loader/index.js
const path = require('path');
module.exports = function (content)
let loaderSign = this.request.indexOf("!");
let rawCss = this.request.substr(loaderSign);
return "require(" + JSON.stringify(path.join(__dirname, 'addStyle')) + ")" +
"(require(" + JSON.stringify(rawCss) + "))";
;
- css-loader:
解释CSS文件中的@import和url()操作符。
loader的用法:
在配置对象的 module 属性中添加一个 rules 数组。这个数组就是我们针对资源模块的加载规则配置:
- 首先是 test 属性,它是一个正则表达式,用来匹配打包过程中所遇到文件路径。
- use 属性,它用来指定匹配到的文件需要使用的 loader。
- options属性,支持更多其他的配置。
常用的loader:
file-loader:
file-loader实际上只将资源文件进行了文件目录的转移,将文件发送到输出文件夹,并返回(相对)URL。
url-loader:
url-loader 功能类似于 file-loader,但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL。
babel-loader:
使用babel-loader处理js文件,会将es5以上的语法进行转义(无法转义es6 API)。
style-loader:
将css文件的内容嵌入到HTML文件中。
css-loader:
css-loader 解释(interpret) @import 和 url() ,会 import/require() 后再解析(resolve)它们。
sass-loader:
sass 代码经过 sass-loader 的转换成css代码,再包装一层 module.exports,成为一个 JS module。
postcss-loader:
许多css样式的书写需要添加厂商前缀,我们可以使用postcss-loader来完成添加厂商前缀的操作。
thread-loader:
把这个 loader 放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker 池(worker pool)中运行。
vue-loader:
解析和转换 .vue 文件,提取出其中的逻辑代码 script、样式代码 style、以及 HTML 模版 template,再分别把它们交给对应的 Loader 去处理。
总结:
loader 本质上是一个函数,输入参数是一个字符串,输出参数也是一个字符串。当然,输出的参数会被当成是 JS 代码,从而被 esprima 解析成 AST,触发进一步的依赖解析。
webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。你可以使用 Node.js 来很简单地编写自己的 loader。
以上是关于前端工程化-loader机制的主要内容,如果未能解决你的问题,请参考以下文章
前端工程化7:自定义实现Webpack中的Loader和Plugin