JavaScript

Knowledge Base

JavaScript > Tools

Babel.config.js

Babel / Presets / Plugins und auch core-js müssen zuvor installiert werden, damit Babel wie unten beschrieben funktioniert:

npm i -D @babel/core @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties babel-loader

npm i core-js

---

Babel.config.js ist eine von mehreren Möglichkeiten den Transpile-Vorgang von Babel zu konfigurieren.

Hier können einzelne Babel-Plugins oder Presets definiert werden, die den JavaScript-Code geeignet übersetzen (das Resultat ist wiederrum JavaScript (Transpiling)). JavaScript ist "geeignet", wenn es in der Ziel-Umgebung läuft - also z. B. im Browser oder in einer anderen JavaScript-Umgebung (z. B. Node) - d. h. bei der Entwicklung kann ES2015+ JavaScript Syntax und Elemente verwendet werden, mit dem Transpiling kann es dann aber auch in einem ur-alten Internet Explorer 9 laufen.

Generell sollte deshalb immer das @babel/preset-env (https://babeljs.io/docs/en/babel-preset-env) mit browserslist - entweder mit option "targets" (= Ziel-Umgebung) von @babel/preset-env oder zentraler z. B. in der package.json (weil die browserlist evtl. auch von anderen Tools verwendet werden könnte) konfiguriert werden.

Für React muss zusätzlich das @babel/preset-react (https://babeljs.io/docs/en/babel-preset-react) verwendet werden.

Zusätzlich zu den presets können auch einzelne Plugins hinzugefügt werden, z. B. class properties plugin (https://babeljs.io/docs/en/babel-plugin-proposal-class-properties).

Beispiel für babel.config.js:

/* eslint-disable no-console */
module.exports = function(api) {
    // Should be set in webpack.config.js > babel-loader > option "envName"
    // Currently not clear, how this can be derived from NODE_ENV.
    const isDevelopment = api.env("development");
    api.cache(true);
 
    console.log("Babel is running in " + (isDevelopment ? "DEVELOPMENT" : "PRODUCTION"));
 
    // For readability only - we use pushing of single presets to increase readability
    // (because presets including options are also arrays)
    const presets = [];
 
    // Add preset react (https://babeljs.io/docs/en/babel-preset-react) for transforming JSX code
    presets.push([
        "@babel/preset-react",
        {
            development: isDevelopment, // https://babeljs.io/docs/en/babel-preset-react#development
 
            // development = true automatically activates the plugins:
            // 1. @babel/plugin-transform-react-jsx-source (https://babeljs.io/docs/en/babel-plugin-transform-react-jsx-source):
            // which adds a "__source={ { fileName: 'this/file.js', lineNumber: 10 } }" to each tag which will helps for
            // some error messages (e.g. if a component is created with <ComponentName /> but ComponentName is not a react component,
            // but e. g. an object) to show more information about the source - see also https://github.com/facebook/react/pull/8495
            //
            // 2. @babel/plugin-transform-react-jsx-self:
            // which adds a "__self={this}" to each tag - but we don't know what this is for - according to this page
            // it's also used for warnings maybe in combination with __source: https://www.npmjs.com/package/babel-plugin-transform-react-jsx-self
        },
    ]);
 
    // Adds preset env (https://babeljs.io/docs/en/babel-preset-env) for transforming
    // ES2015+ code to valid code compatible to browsers in browserslist
    // (++ add core-js polyfills (map, generators, promise etc.)
    // where non-available features are used (= where used = "usage"))
    presets.push([
        "@babel/preset-env",
        {
            corejs: 3, // Use core-js 3 for polyfills (core-js 3 must be installed for this option)
 
            // CAUTION: The following fails in case node_modules are not touched by Babel (which is
            // typically the case). So some relevant functions for IE (9-11) and other browsers
            // will fail because the necessary polyfills are not added by default (if not used
            // by your code directly).
            // useBuiltIns: "usage", // Add polyfills only in files where used
 
            // Adds polyfills on entry level based on the defined targets (independent whether they are
            // used or not used in your code) which differs from the option "usage" above which
            // will auto-add polyfills necessary in your own code.
            // https://babeljs.io/docs/en/next/babel-preset-env.html#usebuiltins-entry
            // IMPORTANT: Add this import on the beginning of your entry:
            // import "core-js/stable";
            // import "regenerator-runtime/runtime";
            // "core-js" and "regenerator-runtime" must be installed
            // (=> "npm i core-js regenerator-runtime")
            useBuiltIns: "entry",
 
            //debug: true, // Optional: Shows debug output on command line
 
            // We are using webpack modules (which are already transformed by webpack)
            // so no need to transform them by babel - we could enforce this by setting
            // this option to "false".
            // However, we are also using jest under node where we must transform the
            // ES6 module imports -> therefore we keep auto and let the environment
            // (webpack, jest) decide themselves how to handle ES6 module imports:
            modules: "auto",
 
            targets: {
                // You can use browserlist in package.json - BUT: If you have to specify
                // the target node version for jest (see below) babel will ignore the
                // package.json browserslist settings! Therefore you have to specify
                // the target browsers here:
                browsers: "last 2 versions, not dead, > 0.25%, ie 9, ie 10, ie 11",
 
                // We are adding this for jest - because in case of useBuiltIns: "entry"
                // we have no entry for jest (except we add additional entries to
                // jest.init.js) and it fails with "ReferenceError: regeneratorRuntime
                // is not defined"
                node: "current",
            },
        },
    ]);
 
    const plugins = [
        // Add plugin for class properties (https://babeljs.io/docs/en/babel-plugin-proposal-class-properties)
        "@babel/plugin-proposal-class-properties",
 
        // No longer necessary when preset-env is used:
        // https://babeljs.io/blog/2019/07/03/7.5.0#dynamic-import-9552-https-githubcom-babel-babel-pull-9552-and-10109-https-githubcom-babel-babel-pull-10109
        //"@babel/plugin-syntax-dynamic-import",
    ];
 
    return {
        presets,
        plugins,
    };
};