Webpack中文:
Loader Interface | webpack 中文文档

如何编写一个Loader呢?其实非常的简单,Loader就是一个函数用来处理代码的逻辑。

编写一个 Loader

新建初始化一个项目:

  1. $ npm init -y

安装Webpack

  1. $ npm install webpack webpack-cli -S

到此全部的文件目录

  1. mark-loader
  2. ├─package-lock.json
  3. ├─package.json
  4. ├─webpack.config.js
  5. ├─src
  6. | index.js
  7. ├─loaders
  8. | replaceLoader.js

loaders文件夹下存放所有的自己编写的Loader,我们在index.js文件写自己的业务逻辑:

  1. console.log("hello dll");

方法接收一个source参数:

  1. module.exports = function (source) {
  2. // 接收 js 文件的内容
  3. return source.replace("dll", "dllLee")
  4. }

使用我们新写的Loader:

  1. const path = require("path");
  2. module.exports = {
  3. mode: "development",
  4. entry: "./src/index.js",
  5. output: {
  6. path: path.resolve(__dirname, "dist"),
  7. filename: "[name].js"
  8. },
  9. module: {
  10. rules: [{
  11. test: /\.js/,
  12. // 使用本地的 Loader
  13. use: [path.resolve(__dirname, "./loaders/replaceLoader.js")]
  14. }]
  15. }
  16. }

然后运行npm run build我们就能看到dist/ main.js文件中的输出是dllLee

Loader 的配置项目

我们自己编写的Loader如何进行参数配置呢?
和其他Loader一样新增options属性:

  1. const path = require("path")
  2. module.exports = {
  3. mode: "development",
  4. entry: "./src/index.js",
  5. output: {
  6. path: path.resolve(__dirname, "dist"),
  7. filename: "[name].js"
  8. },
  9. module: {
  10. rules: [{
  11. test: /\.js/,
  12. // 使用本地的 Loader
  13. use: [{
  14. loader: path.resolve(__dirname, "./loaders/replaceLoader.js"),
  15. options: {
  16. name: "test"
  17. }
  18. }]
  19. }]
  20. }
  21. }

现在我们虽然配置options ,那么如何才能获取到它呢?
使用this.query就能获取到optins里面的参数:
Loader Interface | webpack 中文文档

  1. module.exports = function (source) {
  2. // 接收 js 文件的内容
  3. return source.replace("dll", this.query.name)
  4. }

假设我们现在有需求要返回sourcemap怎么做呢?可以使用callback
Loader Interface | webpack 中文文档

  1. module.exports = function (source) {
  2. // 接收 js 文件的内容
  3. let result = source.replace("dll", this.query.name);
  4. this.callback(Error, result, SourceMap, meta)
  5. }

处理异步Loader

假如我们的Loader里面存在异步的方法,就像这样:

  1. module.exports = function (source) {
  2. let result = source.replace("dll", this.query.name)
  3. setTimeout(() => {
  4. this.callback(null, result);
  5. }, 1000)
  6. }

这个时候运行npm run build就会报错,而报错的原因就是说我们没有返回代码的处理结果,而实际上我们是在一秒后才会返回处理的接口,这个时候就需要用this.async()来帮我们解决了。

this.async()的参数配置和this.callback()是一样的:

  1. module.exports = function (source) {
  2. let result = source.replace("dll", this.query.name)
  3. let callback = this.async();
  4. setTimeout(() => {
  5. callback(null, result);
  6. }, 1000)
  7. }

简化 Loader 路径

到目前呀我们就能实现一个自定义的Loader了,但是他的路径非常的长如何才能简化呢?配置resolveLoader

  1. const path = require("path");
  2. module.exports = {
  3. mode: "development",
  4. entry: "./src/index.js",
  5. output: {
  6. path: path.resolve(__dirname, "dist"),
  7. filename: "[name].js"
  8. },
  9. // 寻找 Loader 的路径(从左到右),如果 node_module 下存在就使用 node 下的 Loader
  10. resolveLoader: {
  11. modules: ["node_modules", "./loaders"]
  12. },
  13. module: {
  14. rules: [{
  15. test: /\.js/,
  16. // 使用本地的 Loader
  17. use: [{
  18. loader: "replaceLoader",
  19. options: {
  20. name: "test"
  21. }
  22. }]
  23. }]
  24. }
  25. }