最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 总会遇到那么几个库是ES6的代码, 怎么办?|七日打卡

    正文概述 掘金(Camol)   2021-01-14   564

    背景

    前几天,笔者把项目里的query-string升级到v6的版本,为了里面一些新特性(比如,字符串的'1'转成数字1)。今天,测试同事和我说,移动端低版本的浏览器跑不起来,我看了报错,发现是编辑完的代码里有箭头函数,心想简单,把query-string纳入babel的编译范围即可。结果,还是有箭头函数。我又检查了一遍,结果是query-string的依赖库也有用es6代码写的。

    这怎么办?总不能让笔者一个一个把依赖库检查一遍吧。。。。

    这是笔者原先的babel-loader配置:

    const babelLoader = {
      test: /\.(js|jsx|ts|tsx|mjs)$/,
      exclude: [/node_modules\/(?![(braft\-editor)|(query\-string)])/, /bower_components/],
      include: [paths.appSrc, resolveApp('node_modules/braft-editor'), resolveApp('node_modules/query-string')],
      use: ['happypack/loader?id=babel-loader'],
    };
    

    怎么处理es6代码写的依赖库?

    当然,还是使用babel-loader,但是每次改完 exclude后,还要去 include 里改,而且可能依赖库的依赖库也有es6的代码,太麻烦了!

    笔者之前使用umi,umi里有个配置字段 nodeModulesTransform, 可以指定编译node_modules目录下的一些依赖库,使用起来就很便捷。

    1. 先定义哪些直接的依赖库要单独编译
    const nodeModulesTransform = {
      type: 'none', // none 不编译node_modules下的;all,编译node_modules下的所有库
      exclude: ['braft-editor', 'query-string'],
    };
    

    all 的逻辑比较简单,就是编译node_modules下的所有文件,这篇就不讲这部分的实现了,主要讲none。(下面的都是自己琢磨的,并没有去参考 umi 这部分的实现, 如果有看过 umi的别杠我 = =)

    1. 获取依赖库的所有dependencies

    由于依赖库的 dependencies 可能也存在 es6 代码,所以宁愿牺牲一点时间,也要用babel把这些dependencies也编译一遍

    const path = require('path');
    const process = require('process');
    function getDeps(moduleName, depMap) {
      try {
        const modulePkg = require(path.join(process.cwd(), `node_modules/${moduleName}/package.json`));
        if(!('dependencies' in modulePkg)) return [];
        const dependencies = modulePkg.dependencies;
        let deps = [];
        for (var key in dependencies) {
          if (key in depMap) continue; // 防止有依赖库重复引用或者循环引用,所以加个hash检查下
          deps = deps.concat(getDeps(key, depMap));
          deps.push(key);
          depMap[key] = 1;
        }
        return deps;
      } catch (e) {
        console.log(e);
        console.log(`${path.join(process.cwd(), `node_modules/${moduleName}/package.json`)} don't exist`);
      }
    }
    
    1. 获取直接依赖库,以及直接依赖库的所有子依赖库
    const getAllDeps = (() => {
      let deps;
      return modules => {
        if (deps) return deps;
        if (modules.length === 0) return [];
        let res = modules.slice();
        let depMap = {}; // 依赖库字典
        for (var i = 0, len = modules.length; i < len; i++) {
        	depMap[modules[i]] = 1;
        }
        for (var i = 0, len = modules.length; i < len; i++) {
          res = res.concat(getDeps(modules[i], depMap));
        }
        res = res.filter(n => {
          if (n.indexOf('babel') > -1) return false;
          if (['regenerator-runtime', 'core-js', 'promise', 'object-assign', 'setimmediate'].includes(n)) {
            return false;
          }
          return true;
        });
    
        deps = res;
        return deps;
      };
    })();
    

    因为最终提供给 babel-loaderexcludeinclude 所涉及的第三方模块是相同的,所以笔者使用 闭包 做了一个 缓存代理

    这里获取所有依赖库的方法,是使用的递归,有可能会爆栈。感兴趣的同学可以使用 广度优先搜索 算法来优化上述代码:)

    1. 提供给 babel-loaderexcludeinclude
    function getNodeModulesTransformExclude() {
      const modules = getAllDeps(nodeModulesTransform.exclude).map(n => {
        return `(${n.replace(/\-/g, '\\-')})`;
      });
      if (modules.length === 0) {
        return /node_modules/;
      }
      return new RegExp(`node_modules\\/(?![${modules.join('|')}])`);
    }
    
    function getNodeModulesTransformInclude() {
      return getAllDeps(nodeModulesTransform.exclude).map(n => `node_modules/${n}`);
    }
    
    

    新的 babel-loader配置如下:

    const babelLoader = {
      test: /\.(js|jsx|ts|tsx|mjs)$/,
      exclude: [getNodeModulesTransformExclude(), /bower_components/],
      include: [paths.appSrc, ...getNodeModulesTransformInclude().map(n => resolveApp(n))],
      use: ['happypack/loader?id=babel-loader'],
    };
    

    以后再遇到某个库使用了es6代码,只需要修改 nodeModulesTransform 中的 exclude 这一处地方即可。


    tips: 这几天都在学 Python, 昨天计划今天讲 Pythonif 语句,但是这部分内容比较简单, 打算和后面看的 字典 一起讲。


    起源地下载网 » 总会遇到那么几个库是ES6的代码, 怎么办?|七日打卡

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元