Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

专题14: 手写一个loader,实现一个可选链(obj?.foo?.bar) #56

Open
luoxue-victor opened this issue Nov 22, 2019 · 0 comments
Labels
webpack 专题 一些系列专题

Comments

@luoxue-victor
Copy link
Owner

luoxue-victor commented Nov 22, 2019

可选链说明

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/%E5%8F%AF%E9%80%89%E9%93%BE

babel 地址

https://www.babeljs.cn/docs/babel-plugin-proposal-optional-chaining

手写一个loader,实现可选链

本章内容

  1. 什么是 webpack loader
  2. 可选链介绍
  3. loader 实现可选链

什么是 webpack loader

webpack loaderwebpack 为了处理各种类型文件的一个中间层,webpack 本质上就是一个 node 模块,它不能处理 js 以外的文件,那么 loader 就帮助 webpack 做了一层转换,将所有文件都转成字符串,你可以对字符串进行任意操作/修改,然后返回给 webpack 一个包含这个字符串的对象,让 webpack 进行后面的处理。如果把 webpack 当成一个垃圾工厂的话,那么 loader 就是这个工厂的垃圾分类!

可选链介绍

这里并不是纯粹意义上的可选链,因为 babelts 都已经支持了,我们也没有必要去写一个完整的可选链,只是来加深一下对 loader 的理解, loader 在工作当中能帮助我们做什么?

用途 当我们访问一个对象属性时不必担心这个对象是 undefined 而报错,导致程序不能继续向下执行

解释? 之前的所有访问链路都是合法的,不会产生报错

const obj = {
  foo: {
    bar: {
      baz: 2
    }
  }
}

console.log(obj.foo.bar?.baz) // 2
// 被转成 obj && obj.foo && obj.foo.bar && obj.foo.bar.baz
console.log(obj.foo.err?.baz) // undefined
// 被转成 obj && obj.foo && obj.foo.err && obj.foo.err.baz

loader 实现可选链

配置loader,options-chain-loader

config/OptionsChainLoader.js

module.exports = (config, resolve) => {
  const baseRule = config.module.rule('js').test(/.js|.tsx?$/);
  const normalRule = baseRule.oneOf('normal');
  return () => {
    normalRule
      .use('options-chain')
      .loader(resolve('options-chain-loader'))
  }
}

其实就是正则替换,loader 将整个文件全部转换成字符串,content 就是整个文件的内容,对 content 进行修改,修改完成后再返回一个新的 content 就完成了一个 loader 转换。是不是很简单?

下面的操作意思就是,我们匹配 obj.foo.bar?. 并把它转成 obj && obj.foo && obj.foo.bar && obj.foo.bar.

options-chain-loader.js

module.exports = function(content) {
  return content.replace(new RegExp(/([\$_\w\.]+\?\.)/,'g'),function(res) {
    let str  = res.replace(/\?\./,'');
    let arrs = str.split('.');
    let strArr = [];
    for(let i = 1; i <= arrs.length; i++) {
      strArr.push(arrs.slice(0,i).join('.')); 
    }
    let compile = strArr.join('&&');
    const done = compile + '&&' + str + '.'
    return  done;
  });
};
@luoxue-victor luoxue-victor added webpack 专题 一些系列专题 labels Nov 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
webpack 专题 一些系列专题
Projects
None yet
Development

No branches or pull requests

1 participant