Loader 本质上是一个导出为函数的 JavaScript 模块
loader runner 库会调用这个函数,然后将上一个 loader 产生的结果或者资源文件传入进去
1 2 3 4 5 6 7 8 9 10 11 12
|
module.exports = function (content, map, meda) { console.log("loader1", "---", content, map, meda); return content; };
|
webpack.config.js
1 2 3 4 5 6 7 8
| module: { rules: [ { test: /\.js$/, use: ["./my_loader/my_loader1.js", "./my_loader/my_loader2.js"], }, ], },
|
同步异步
默认创建的 Loader 就是同步的 Loader
这个 Loader 必须通过 return 或者 this.callback 来返回结果,交给下一个 loader 来处理
通常在有错误的情况下,我们会使用 this.callback
this.callback 的用法如下:
- 第一个参数必须是 Error 或者 null
- 第二个参数是一个 string 或者 Buffer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| module.exports = function (content, map, meda) { console.log("loader2", "---", content, map, meda); setTimeout(() => { return content; });
this.callback(null, content + "aaa"); };
module.exports = function (content, map, meda) { console.log("loader2", "---", content, map, meda); const callback = this.async(); setTimeout(() => { callback(null, content + "aaa"); }, 2000); };
|
resolveLoader 属性
更加简洁的去加载自己的 loader 文件夹
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| resolveLoader: { modules: ["./my_loader", "node_modules"], },
module: { rules: [ { test: /\.js$/, use: ["my_loader1.js", "my_loader2.js"], }, ], },
|
传入和获取参数
之前需要 npm install loader-utils -D
现在不用,直接 this.getOptions();可以获取
1 2 3 4 5 6 7 8 9 10 11 12 13
| module: { rules: [ { test: /\.js$/, use: [ "my_loader1.js", "my_loader2.js", { loader: "my_loader3.js", options: { name: "kkk" } }, ], }, ], },
|
1 2 3 4 5 6 7 8 9 10
| module.exports = function (content, map, meda) { const options = this.getOptions(); const callback = this.async(); console.log(options); setTimeout(() => { callback(null, content + "aaa"); }, 2000); };
|
校验参数
npm install schema-utils -D
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const { validate } = require("schema-utils"); module.exports = function (content, map, meda) { const options = this.getOptions(); const callback = this.async(); console.log(options); validate( { type: "object", properties: { name: { type: "string", definition: "输入你的名称" }, }, }, options ); setTimeout(() => { callback(null, content + "aaa"); }, 2000); };
|
案例
md 渲染转换 loader
index.md
1 2 3 4 5 6 7 8
| ## Css
## Js
js 学习
```js var str = "aa";
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| webpack.config.js
```JavaScript const path = require("path"); const htmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { mode: "development", entry: "./src/main.js", output: { path: path.resolve(__dirname, "./build"), filename: "bundle.js", }, module: { rules: [ { test: /\.js$/, use: [ { loader: "my_loader3.js", options: { name: "kkk" } }, ], }, { test: /\.md$/, use: "myMd-loader.js", }, { test: /\.css$/, use: ["style-loader", "css-loader"], }, ], }, plugins: [new htmlWebpackPlugin()], resolveLoader: { modules: ["./my_loader", "node_modules"], }, };
|
myMd-loader.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const { marked } = require("marked"); const hljs = require("highlight.js"); module.exports = function (content) { marked.setOptions({ highlight: function (code, lang) { return hljs.highlight(lang, code).value; }, }); const htmlContent = marked(content); console.log(htmlContent); const innerContet = "`" + htmlContent + "`"; const moduleContent = `var code = ${innerContet}; export default code;`; return moduleContent; };
|
main.js
1 2 3 4 5 6 7 8 9
| const index = require("./index"); import code from "./index.md";
import "highlight.js/styles/default.css"; import "./css/index.css"; const message = "自定义loader"; console.log(message, code); document.body.innerHTML = code;
|
注意如果不用 highlight 默认的代码高亮 css
需要自己编写 css 如:
1 2 3
| .hljs-string{ color:red; }
|
因为这一步
1 2 3 4 5
| marked.setOptions({ highlight: function (code, lang) { return hljs.highlight(lang, code).value; }, });
|
其实就是给对应的标签节点加上对应的 class
