当前位置: 首页 > 科技观察

从BabelPreset和EslintConfig看配置继承和重写

时间:2023-03-12 17:30:38 科技观察

继承和重写是面向对象编程语言中的概念,指的是一个类从父类继承并重新实现它的一些属性和方法。这种思想不仅用在编程语言中,也广泛用在配置文件中。本篇我们分别从babel和eslint的配置文件来重新审视继承和重写。Javascript中的继承和重写我们定义了一个Person类,它有三个方法:eat、sleep和getSkills。classPerson{eat(){}sleep(){}getSkills(){}}然后定义一个Guang类,继承Person,重写getSkills方法。classGuangextendsPerson{getSkills(){return['babel','eslint','vscode','node.js']}}创建一个Guang实例对象,有eat和sleep方法,重写了getSkills方法。这是一个重要的语言特性,通过原型链在Javascript中实现。babel配置中的继承与改写babel是微内核架构,所有的代码转换都是通过插件完成的。ES2015需要指定一堆插件,es2016也需要指定一堆插件。为了简化这些插件的配置,eslint支持将一系列的插件打包成一个preset,在配置文件中指定preset来引入具体的插件。所以babel6有preset-es2015、preset-es2016等presets,后来babel7也支持指定目标环境动态指定一系列插件的preset-env。preset就是把一些插件封装在一起。例如:module.exports=function(){return{plugins:["pluginA","pluginB","pluginC"]};};并且预设也可以被继承:module.exports=function(){return{preset:['presetA']plugins:["pluginA","pluginB","pluginC"]};};这就好比Javascript中C继承B,B继承A,在配置上有多重继承。babel插件生效的顺序是先plugin,后preset,从左到右plugin,从右到左preset。这个生效顺序允许配置中的插件覆盖预设中插件的配置,即重写。babel除了插件整体覆盖外,还支持文件级和环境级覆盖:文件级重写:在配置中,可以设置为哪个文件重写哪个配置:overrides:[{test:]。/xxx.js",plugins:['pluginX']}]编译这个文件时,这些选项会合并到主选项中。比如ts和js需要不同的插件、preset等配置,可以通过override分别指定。环境级重写:当文件级配置重写不够时,有时开发环境和生产环境使用不同的插件,所以babel也支持环境级重写:envName:'development',env:{development:{plugins:['pluginA']},production:{plugins:['pluginB']}}通过envName启用不同环境的不同配置,并合并到主配置中。这个envName其实不需要设置,默认就是process.env.BABEL_ENV或者process.env.NODE_ENV的值。可见babel支持将plugins封装成presets,presets也可以继承,因为生效的顺序是先plugin再preset,所以可以达到重写的目的。并且还可以在文件级别和环境级别进行改写,分别通过overrides和env的配置。eslint配置中的继承和重写eslint配置也支持封装,但不叫preset,而是sharableconfig。因为babel的preset更多的是为了简化配置,而eslint的config的目的不是为了简化配置,而是共享配置,所以叫sharableconfig。在eslint中,你可以使用extends来继承一个配置:{"plugins":["react"],"extends":["eslint:recommended","plugin:react/recommended""./aaa/.eslintrc-jsx"],"rules":{"no-set-state":"off"}}sharableconfig的路径可以通过eslint指定:指定内置config,通过plugin:指定插件中的config,并通过相对路径指定任何位置配置。specificconfig包含各种共享配置,也支持继承某个配置。module.exports={rules:{'no-alert':2},extends:'myconfig/lib/defaults'};这里要注意配置规则的合并规则:如果只改写错误级别,则选项会被继承。rule:{ruleA:['error'],//只重写错误级别,option会继承ruleB:['warn','aaa']//错误级别和选项都重写}除了整体配置的重写此外,还支持文件级重写:"overrides":[{"files":["**/*.md/*.js"],"rules":{"strict":"off"}}]这样在linting不同的文件时可以使用不同的规则。比如ts和js需要使用不同的规则。eslint有没有环境级的改写?没有。Babel有环境级别的配置重写,因为它需要生成代码,不同环境生成的代码可能有些不同。而eslint不需要生成代码,只是lints源码,所以不需要环境级的配置重写。eslint也有env配置,但是和babel的env不同:"env":{"es6":true}eslint的env配置指定了运行环境,babel的env配置指定了不同环境下需要重写的配置.两者是不同的角色。可以看出,eslint支持将配置封装成可共享的config,config和config也可以通过extends继承,也支持通过overrides在指定文件级别进行改写,但不需要支持环境级别的改写。总结继承和重写是一个普遍的想法,不仅在编程语言的语法中如此,在配置文件中也是如此。babel和eslint都支持对部分配置进行封装,以达到重用和简化配置的目的,但是在babel中称为preset,在eslint中称为sharableconfig,因为一个主要是为了简化配置,另一个是为了共享。除了重写整体配置,babel还支持文件级重写(overrides)和环境级重写(env),eslint支持文件级重写(overrides)。继承和重写是一种思想,不仅体现在编程语言的语法上,在配置文件领域也有很多应用。