Inheritance and overwriting are concepts in object-oriented programming languages, in which a class extends from its parent class and reimplements some of its properties and methods. This idea is not only used in programming languages, but also in configuration files.

This article takes a fresh look at inheritance and rewriting from the configuration files for Babel and ESLint, respectively.

Inheritance and rewriting in Javascript

We define a Person class that has three methods: eat, sleep, and getSkills.

class Person {
    eat(){}
    sleep() {}
    getSkills(){}}Copy the code

Then define a Guang class that inherits from Person and overrides the getSkills method.

class Guang extends Person {
    getSkills() {
        return ['babel'.'eslint'.'vscode'.'node.js']}}Copy the code

Create an instance of Guang that has the eat, sleep, and rewritten getSkills methods.

This is an important language feature that is implemented in Javascript through prototype chains.

Inheritance and rewriting in the Babel configuration

Babel is a microkernel architecture, and all code transformation is done through plug-ins. Es2015 requires a bunch of preset plug-ins, and ES2016 requires a bunch of preset plug-ins. To simplify the configuration of these plug-ins, ESLint supports packaging a series of plug-ins as a preset, and specifies preset in the configuration file to introduce a specific preset.

Babel6 has preset — ES2015, PRESET — ES2016, and later Supports preset — env, which specifies the target environment to dynamically specify a set of plug-ins.

Preset is the encapsulation of plug-ins together. Such as:

module.exports = function() {
    return { 
        plugins: ["pluginA"."pluginB"."pluginC"]}; };Copy the code

And preset can also inherit preset:

module.exports = function() {
    return { 
        preset: ['presetA']
        plugins: ["pluginA"."pluginB"."pluginC"]}; };Copy the code

This is like Javascript where C inherits FROM B, and B inherits from A, and the configuration is multi-inherited.

The Babel plugin is preset, plugin from left to right, preset from right to left, so that the plugin in the configuration can override the configuration of the plugin inside, that is, preset.

In addition to overall plug-in override, Babel also supports file-level and environment-level override:

File-level rewriting:

In configuration you can set what configuration to override for what files:

overrides: [
    { 
        test: "./xxx.js".plugins: ['pluginX']}]Copy the code

When the file is compiled, these options are merged into the main option.

For example, TS and JS require different plugin, preset, and other configurations, which can be specified by Override.

Environment level rewrite:

When file-level configuration overrides are not enough, sometimes the development environment and production environment use different plug-ins, etc., so Babel also supports environment-level overrides:

envName: 'development'.env: {
    development: {
        plugins: ['pluginA']},production: {
        plugins: ['pluginB']}}Copy the code

EnvName is used to enable different configurations for different environments, incorporated into the master configuration.

The envName does not need to be set. The default is either process.env.babel_env or process.env.node_env.

As can be seen, Babel supports the encapsulation of plug-ins as preset, and preset can be inherited between preset and preset, as the effective order is plugin first followed by preset, so it can be used to preset. It can also be overridden at the file level and environment level, via overrides and env configuration, respectively.

Inheritance and rewriting in ESLint configurations

The ESLint configuration also supports encapsulation, but is called Sharable Config instead of preset. Because Babel preset is more for simplifying configuration, and ESLint’s config is not for simplifying configuration but for sharing configuration, it is called Sharable Config.

Eslint can use extends to inherit a config:

{
    "plugins": [
        "react"]."extends": [
        "eslint:recommended"."plugin:react/recommended"
        "./aaa/.eslintrc-jsx"]."rules": {
       "no-set-state": "off"}}Copy the code

The path to Sharable config can be esLint: to specify the built-in config, plugin: to specify the config in the plugin, and relative path to specify the config anywhere.

The specific config contains various shared configurations and can also be inherited from a configuration.

module.exports = {
    rules: {
        'no-alert': 2
    },
    extends: 'myconfig/lib/defaults'
};
Copy the code

Note the merging rule of the configured rule:

If only the error level is overridden, option inherits.

rule: {
    ruleA: ['error'].// Override only the error level, option inherits
    ruleB: ['warn'.'aaa']// Error levels and options are overwritten
}
Copy the code

In addition to overall configuration overwriting, file-level overwriting is also supported:

"overrides": [{"files": ["**/*.md/*.js"]."rules": {
            "strict": "off"}}]Copy the code

This makes it possible to use different rules for different files in Lint, such as ts and JS requiring different rules.

Are there environment level overrides in ESLint?

No. Babel has configuration overwrites at the environment level because code needs to be generated, which may differ from environment to environment. Eslint doesn’t need to generate code, just source code, so no environment-level configuration rewrite is required.

Eslint also has env configuration, but not the same as Babel’s env:

"env": {
    "es6": true
}
Copy the code

The env configuration of esLint specifies the environment in which it is run, while the env configuration of Babel specifies the configuration to be overridden by different environments.

As you can see, ESLint supports encapsulation of configurations as Sharable Config, extends from config to config, and also supports file-level rewriting via overrides, but does not need to support environment-level rewriting.

conclusion

Inheritance and rewriting is a common idea, not only in the syntax of programming languages, but also in configuration files.

Both Babel and ESLint support encapsulation of a part of the configuration for reuse and simplification of configuration, but Babel is called Sharable Config in ESLint because one is mainly for simplification of configuration and the other is mainly for sharing.

In addition to overall configuration overrides, Babel also supports file-level overrides and environment-level overrides, and file-level overrides are supported in ESLint.

Inheritance and rewriting is an idea that has many applications in configuration files, not just in the syntax of programming languages.