美文网首页webpack
babel-loader实现

babel-loader实现

作者: 成熟稳重的李先生 | 来源:发表于2019-07-17 23:57 被阅读0次

    上一节学习了loader的概念,这节我来接着完成一个简易的babel-loader
    接着上一节的代码,首先安装“@babel/core”(babel核心模块)和“@babel/preset-env”,因为我要实现“babel-loader”,所以这里就不装loader了

    //webpack.config.js
    module: {
        rules: [
          {
            test: /\.js$/,
            use: {
              loader: "babel-loader",   // 这个loader使我们自己写的,不引用官方的
              options: {
                presets: ["@babel/preset-env"]   // 转换规则
              }
            }
          }
        ]
      }
    //loader文件夹下新建babel-loader.js文件
    let babel = require('@babel/core');  // 引入babel核心块
    function loader(source) {
      return source
    }
    module.exports = loader;
    

    @babel/core是babel的核心模块,编译器。提供转换的API。
    以上babel-loader.js中,我已经引入了babel/core,然后我们需要告诉webpack,要以什么规则(方式)转换我们的js文件,es-2015,stage-2,env...。可以看到webpack配置文件中,我已经给了presets-env,那么我们需要在babel-loader.js中引入这个预设规则。引入规则的前提,需要安装包loader-utils(用来拿传递的参数)

    let babel = require("@babel/core");
    let loaderUtils = require("loader-utils");
    function loader(source) {
      //参数“this”,指代loader的上下文--loaderContext
      // console.log(Object.keys(this));
      let options = loaderUtils.getOptions(this);
      console.log(options);
      return source;
    }
    module.exports = loader;
    

    运行:

    image.png
    如果,拿到了我们所配置的预设,接着继续babel-loader.js,要看到转换效果,我们需要改写index.js
    //index.js
    class Lc {
      constructor() {
        this.name = "lc";
      }
      getName() {
        return this.name;
      }
    }
    let lc = new Lc();
    console.log(lc.getName());
    

    运行,查看结果:

    image.png
    新建html文件,并且引入这个打包好的js文件,并且在浏览器中运行
    image.png
    转换成功,看看source-map
    image.png
    确实达到了源码映射的效果,但这个unknow又是个什么鬼?只需加个filename就可以解决:
    //babel-loader.js
    babel.transform(
        source,
        {
          ...options, // presets: options.presets
          sourceMap: true, //但是,如果要真正有sourceMap的效果,webpack中也必须配置devtool字段
          filename: "index.js"
        },
        function(err, result) {
          // 转换是个异步的过程,因此像下边“return source”这种是不行的
          cb(err, result.code, result.map); //固定参数
        }
      );
    

    如果你的js也只有一个,那么这样写“index.js”没有问题,但是一般来说不会只有一个js,我们可以使用this.resourcePath来获取源码的绝对路径。如下

    //index.js
    function loader(source) {
      //参数“this”,指代loader的上下文--loaderContext
      // console.log(Object.keys(this));
      let options = loaderUtils.getOptions(this);
      let cb = this.async(); //原生的函数,有一个flag,如果是同步,那么loader中会自动调用这个函数,异步的话,需要自己手动调用
      console.log(this.resourcePath); // 打印查看绝对路径
      babel.transform(
        source,
        {
          ...options, // presets: options.presets
          sourceMap: true, //但是,如果要真正有sourceMap的效果,webpack中也必须配置devtool字段
          filename: this.resourcePath.split("/").pop() //文件名
        },
        function(err, result) {
          // 转换是个异步的过程,因此像下边“return source”这种是不行的
          cb(err, result.code, result.map); //固定参数
        }
      );
    }
    
    image.png
    然后使用字符串的方法来拿到对应源码文件名。这样就很灵活的生成了source-map

    相关文章

      网友评论

        本文标题:babel-loader实现

        本文链接:https://www.haomeiwen.com/subject/euoxlctx.html