webpack手写异步loader

  • 对于同步loader中的例子,若Loader中有异步操作,不能立刻返回,那么就会报错
  • 官网:https://www.webpackjs.com/api/loaders/#this-callback
  • 解决方案:

    • 使用异步:let callback = this.async();
    • 调用callback:callback(null, result, map, meta);

      • 第一个参数:Error 或者 null
      • 第二个参数:string 或者 Buffer
      • 第三个参数:必须是一个可以被这个模块解析的 source map,可选
      • 第四个参数:会被 webpack 忽略,可以是任何东西(例如一些元数据),可选
    module.exports = function (source) {
        let options = loaderUtils.getOptions(this);
        
        let callback = this.async();
        setTimeout(function () {
            source = source.replace(/nhw/g, options.name);
            // return source;
            callback(null, source);
        }, 400);
    }

  • 编写less-loader和style-loader

  • index.js:require('./index.less');
  • index.less:

    body {
        width: 100%;
        height: 100%;
    
        div {
            width: 200px;
            height: 200px;
            background: red;
        }
    }
  • less-loader:将less代码转换成css代码

    • 创建less-loader模块:

      const less = require("less");
      
      module.exports = function (source) {
          // render方法中的回调函数是异步操作
          let callback = this.async();
          // render(需要转换的less代码,成功或失败执行的回调函数)
          less.render(source, function (err, obj) {
              // err错误信息,obj成功后的信息,obj.css即将其转换为css代码
              callback(err, obj.css);
          });
      }
  • style-loader:将css代码插入到html的head标签中

    • 创建style-loader模块:

      module.exports = function (source) {
      let style = `
      let style = document.createElement("style");
      // 必须将其通过json转换为字符串后放在style标签中,打包后eval会将字符串内容转换为js并执行
      style.innerHTML = ${JSON.stringify(source)};
      document.head.append(style);
      `
      // loader返回的数据必须是字符串或者二进制
      return style;
      }
  • 在webpack.config.js中添加配置规则:

    const path = require("path");
    
    module.exports = {
        devtool: 'cheap-module-eval-source-map',
        mode: "development",
        entry: "./src/index.js",
        output: {
            filename: "index.js",
            path: path.resolve(__dirname, "bundle")
        },
        resolveLoader: {
            // alias: {
            //     ReplaceLoader: path.resolve(__dirname, "loader/ReplaceLoader.js")
            // }
            modules: ['node_modules', './loader'],
        },
        module: {
            rules: [
                {
                    test: /\.less$/,
                    use: [{
                        loader: 'style-loader'
                    }, {
                        loader: 'less-loader'
                    }]
                }
            ]
        }
    };

最后修改:2021 年 04 月 11 日 02 : 09 AM
如果觉得我的文章对你有用,请随意赞赏!