一个loader
能够看作是一个node
模块,也能够看作一个loader
就是一个函数 (loader会导出一个函数),众所周知webpack
只能识别js
文件,loader
在webpack
中担任的角色就是翻译工做,它可让其它非js
的资源(source)能够在webpack
中经过loader
顺利加载。javascript
Loader的方式css
来看一下案例前端
module.exports = () => {
return 343
}
复制代码
上面这种会报错,咱们上面说过laoder
的方式了,统一原则,输出输入必须是字符串。而咱们上面代码则输出是数字,则报错。java
loader导出尽可能别使用箭头函数,loader内部属性都是靠this来获取的,如this.callback,this.syncnode
为何要手写loader
呢,假若有一些loader
插件不知足咱们的需求时,咱们会采用手写loader
来定制化咱们功能。webpack
首先新建一个js
文件git
module.exports = function(source) {
}
复制代码
函数里面暴露了一些方法,this.query
获取loader
传过来的参数github
module.exports = function(source) {
console.log(this.query)
}
复制代码
固然里面还能够引入一个库,来处理参数,该状况用于有时候咱们传给loader
的参数不是一个对象,多是一个字符串。web
module: {
rules: [
{
test: /\.css/,
use: [{
loader: "testLoader",
query: "前端娱乐圈"
}]
}
]
}
复制代码
const loaderUtils = require('loader-utils')
module.exports = function(source) {
console.log(loaderUtils.getOptions(this))
}
复制代码
webpack.config.jsnpm
module: {
rules: [
{
test: /\.css/,
use: [
"testLoader?name=前端娱乐圈"
]
}
]
}
复制代码
可使用上面loaderUtils
内置库获取loader
的参数。
webpack.config.js
module: {
rules: [
{
test: /\.css/,
use: [{
loader: "testLoader?name=前端娱乐圈",
options: {
name: "前端娱乐圈"
}
// or
query: {
name: "前端娱乐圈"
}
}]
}
]
}
复制代码
上面这两种传参形式,若是options
存在,行内参数拼接则无效。上面还写了一种传参形式,query
也是能够传参的,那options
和query
有什么区别的。这俩没啥区别就是,query
是webpack
老版本以前的(2.5),options
是最新支持的方式
loader异步处理,假如说loader里面须要处理一些逻辑操做,但这个操做是异步的,那么loader就会编译失败,必须使用异步执行方法,来等待结果返回后,loader则才回执行成功
module.exports = function(source) {
setTimeout(() => {
this.callback(1, source)
}, 3000)
}
复制代码
官方解释:this.callback参数
this.callback(
err: Error | null, // 错误信息
content: string | Buffer, // 最终生成的源码
sourceMap?: SourceMap, // 对应的sourcemap
meta?: any // 其余额外的信息
);
复制代码
还有一种方法是 this.async,async返回值也是一个callback因此这俩个是同样的
module.exports = function(source) {
const callback = this.async()
setTimeout(() => {
callback(1, source)
}, 3000)
}
复制代码
咱们如今手写的loader都仍是写绝对路径引入进来,那么怎么直接写loader名呢,有两种方法,咱们来看一下
module.exports = {
resolveLoader: {
modules: ["node_modules", "./loaders"]
},
module: {
rules: [
{
test: /\.js/
use: {
loader: "per-loader"
}
}
]
}
}
复制代码
咱们能够看到上面,咱们直接写的per-loader
,咱们是配置了解析loader
路径,会先去node_modules
里面查找,若是node_modules
里面没有则会去loaders
目录下查找。而后咱们下面写loader: per-loader
,注意:这里的per-loader
就是当前loader
的文件名
这种方法直接起别名,把路径引入过来就ok
module.exports = {
resolveLoader: {
"per-loader": path.resolve(__dirname, "./loaders/per-loader.js")
},
module: {
rules: [
{
test: /\.js/
use: {
loader: "per-loader"
}
}
]
}
}
复制代码
首先安装一下node-sass
插件,用于识别scss
语法并编译为css
npm i node-sass
复制代码
新建sassLoader.js
文件,并引入node-sass
插件
const nodeSass = require("node-sass");
const path = require("path")
let result = nodeSass.renderSync({
file: path.resolve(__dirname, "../src/scss/index.scss"),
outputStyle: 'expanded',
});
module.exports = function() {
return result.css.toString()
}
复制代码
上面采用node-sass
官方配置,如异步解析.scss
文件,上面对象中,file
为当前要解析的文件地址,outputStyle
为输出风格包含:nested
(嵌套)、expanded
(展开)、compact
(紧凑,不换行)、compressed
(压缩)。
导出result.css.toString
, 这里为何要toString
,若是不toString
的话返回的是一个Buffer
数据。由于这里的返回值提供给下一个loader
使用,为了下一个loader
(style-loader)更好的使用咱们这里直接处理一下。
更多Api用法请参考node-sass
新建styleLoader.js
文件
module.exports = function(source) {
const style = ` let style = document.createElement("style"); style.innerHTML = ${JSON.stringify(source)}; document.head.appendChild(style) `
return style
}
复制代码
上面导出的函数第一参数(source
)就是咱们sassLoader
的返回值,而后在字符串里面写上建立style元素逻辑代码,并最终返回。注意这里返回值必须是字符串
上,刚开始咱们就说过了,输入输出都必须是字符串。
index.js
console.log("前端娱乐圈")
import "./scss/index.scss"
复制代码
webpack.config.js
const path = require("path");
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
resolveLoader: {
alias: {
"sassLoader": path.resolve(__dirname, "./loaders/sassLoader.js"),
"styleLoader": path.resolve(__dirname, "./loaders/styleLoader.js")
}
},
module: {
rules: [
{
test: /\.scss/,
use: ["styleLoader", "sassLoader"]
}
]
}
}
复制代码
上面配置中咱们用到了解析loader
路径配置(起别名),loader是从右到左,从下到上解析执行。先是把.scss
文件处理成css
语法,而后在传递给styleLoader
配置便可。以上一个简单完整的loader
已实现完毕。若有帮助欢迎点赞+分享哦
欢迎关注个人公众号:前端娱乐圈
谢谢你读完本篇文章,但愿对你能有所帮助,若有问题欢迎各位指正。
我是蛙人(✿◡‿◡),若是以为写得能够的话,请点个赞吧❤。
感兴趣的小伙伴能够加入 [ 前端娱乐圈交流群 ] 欢迎你们一块儿来交流讨论
写做不易,「点赞」+「在看」+「转发」 谢谢支持❤