Babel7 configuration file loading logic blog.csdn.net/weixin_3419…

The configuration file

Configuration file Type

Babel has two parallel configuration file formats that can be used together or independently.

  • Project Scope Configuration
  • File relative configuration
    • .babelrc (and.babelrc.js) files
    • Package. json file with the “Babel” key

Project Scope Configuration

In Babel 7.x, Babel has the concept of a “root” directory, which defaults to the current working directory. For project-scoped configuration, Babel will automatically search for “babel.config.js” in this root directory. Alternatively, the user can override the default configuration file search behavior with an explicit “config file” value.

Because project-wide profiles are separated from their physical location, they are well suited for configurations that must be widely applied, even allowing plug-ins and presets to be easily applied to files in node modules or symbolic link packages that are traditionally configured in Babel6.x. The main disadvantage of this project-scoped configuration is that because it relies on the working directory, it can be more painful to use in Monorepo if the working directory is not the Monorepo root. See the Monorepo documentation for an example of how to use configuration files in this context.

You can also disable project-wide configuration by setting “ConfigFile” to false.

File relative configuration

Babel loads. Babelrc (and. Babelrc.js /package.json_babel) files (subject to the following cautions) by searching the directory structure starting from the “filename” being compiled. This can be powerful, as it allows you to create separate configurations for sub-parts of the package. File-related configurations are also merged at the top of project-wide configuration values, making them potentially useful for a particular override, although this can also be done by “override.” Once the directory containing package.json is found, the search stops, so the relative configuration only applies to a single package. The “file name” in the compilation must be in the “babelrcroots” package, otherwise the search will be skipped entirely.

These considerations mean that.babelrc files only apply to files in your own package. Unless you select “babelrc root s”,.babelrc files in packages that are not part of Babel “root” will be ignored. For more discussion on how to configure MonorePO with multiple packages, see the Monorepo documentation. File relative configuration can also be disabled by setting “babelrc” to false.

X and 7.x. abelrc loading

Users from Babel6.x may encounter these two edge cases, which are new in Babel7.x. These two restrictions have been added to address common problems with Babel6.x:

  • The.babelrc file is applied to node module dependencies, often by accident.
  • The.babelrc file cannot be applied to symbolic link node-_ modules because they are expected to behave like normal dependencies. .babelrc files in node module dependencies will be detected, even though their internal plug-ins and presets are usually not installed and may even be invalid in the Babel version of the file compiled. These situations will mainly cause problems for users of Monorepo structures because if.babelrc packages/ mod1/ package.json SRC /index.js mod2/ package.json SRC /index.js

The configuration will now be completely ignored because it crosses package boundaries. Another option is to use “extends” in each as {“extends”: “.. /.. /.babelrc” }

Unfortunately, this approach can be a bit repetitive, and depending on how Babel is used, you may need to set “babelrcRoots.” In view of this, it may be preferable to rename.babelrc to a project-scoped “babel.config.js”. As mentioned in the project scope section above, this may require explicitly setting “config file” because Babel will not find the configuration file if the working directory is not correct.

Monorepo

Monorepo structured repositories typically contain many packages, which means they often encounter warnings mentioned in file-related configurations and config file loads. This section is intended to help users understand how to handle Monorepo configurations. The core thing to understand about the Monorepo setup is that Babel treats your working directory as its logical “root,” which can cause problems if you want to run Babel tools in specific subpackages instead of applying Babel to the REPO as a whole. It is also important to decide whether to use the.babelrc file or just the central babel.config.js. Subfolder specific configurations do not require.babelrc files, as in Babel 6, so in Babel 7 you usually do not need these files, but babel.config.js.

Root Babel. Config. Js file

The first step in any Monorepo structure should be to create the babel.config.js file in the repository root directory. This establishes the core concept of Babel for the repository’s basic directory. Even if you want to use the.babelrc file to configure each individual package, this must be the place for the REPO level option. You can usually put all the REPO configuration in the root babel.config.js. Using “overrides,” you can easily specify configurations that apply only to certain subfolders of the repository, which is usually easier to perform than creating many. Babelrc files in the REPO. The first problem you might encounter is that by default, Babel expects to load the babel.config.js file as its “root” from a directory set, which means that if you create babel.config.js but run Babel in a single package, for example.

cd packages/some-package; babel src -d dist

In this case, the “root” Babel uses is not monorepo root, and it will not be able to find the babel.config.js file. If all the build scripts are running relative to the repository root, things should already be under way, but if you are running the Babel compilation process in a subpackage, you need to tell Babel where to look for configuration. There are several ways to do this, but the recommended one is the “rootmode” option “up”, which will cause Babel to search up the babel.config.js file from the working directory and use its location as the “root” value. A useful way to test if the configuration is detected is to place a console.log () call in it. Because it is a JS file, the log will be executed the first time Babel loads it. How you set this value varies by project, but here are a few examples: CLI Babel –root-mode upward SRC -d lib

@babel/register require(“@babel/register”)({ rootMode: “upward” });

Webpack module: { rules: [{ loader: “babel-loader”, options: { rootMode: “upward”, } }] }

Jest

Jest is usually installed in the root directory of Monorepo and may not need to be configured, but if it is installed in every package, it can unfortunately be more complicated to configure. The main part is to create a custom Jest Transformer file that wraps the default behavior of Babel Jest so that options can be set, for example. module.exports = require(“babel-jest”).createTransformer({ rootMode: “upward”, });

Once saved somewhere, you will use this file in the jest option instead of Babel Jest: “transform”: {“^.+\.jsx? $”: “./path/to/wrapper.js” },

Therefore, all JS files will be processed using your Babel Jest version, with options enabled.

Others: There are many tools, but the core is that if the working directory is not yet the monorepo root, they need to enable the RootMode option.

Subpackage. Babelrc file

In the same way that the babel.config.js file must be in “root”, by default the. Babelrc file must be in the root package. This means that in the same way that the working directory affects the babel.config.js load, it also affects the.babelrc load. Assuming you have loaded the babel.config.js file correctly as discussed above, Babel will only process the. Babelrc file in the root package (and not the subpackages), For example package.json babel.config.js packages/ mod/ package.json.babelrc index.js

Compiling packages/mod/index.js will not load Packages /mod/.babelrc because.babelrc is in a subpackage, not the root package. To enable the processing of.babelrc, you need to use the “babelrcroots” option in the babel.config.js file. babelrcRoots: [ “.”, “packages/*”, ],

Therefore, Babel will consider allowing all packages /* packages of the.babelrc file to be loaded, as well as the original REPo root.

Configuration format

The individual configuration files themselves are divided into JS files and JSON5 files.

JSON5

Any file that is not a.js file will be resolved to json5 and should contain an object that matches the option format accepted by Babel.

javascript

Any.js file will require() Ed, and should either export the configuration object or return the function that configured it when called. The main benefit is that users can build configuration structures using JS logic, which may make configuration logic easier to share. The.js file can be used for project-wide configuration or for file-specific configuration through the.babelrc.js file. The functions that return configuration have some special capabilities because they have access to the APIS exposed by Babel itself. For more information, see configuring function APIS.

Configuration function API

Module.exports = function(API) {return {}; module.exports = function(API) {return {}; }

The API object exposes everything that Babel itself exposes from its index module, as well as configuration file-specific apis:

  • Api.version Type: string Indicates the version string of the Babel version of the configuration file being loaded.

  • Api.cache JS configurations are great because they compute configurations in real time, but the downside is that it makes caching more difficult. Babel wants to avoid reexecuting the config function every time the file is compiled, because it would also need to reexecute any plug-ins and default functions referenced in that configuration. To avoid this, Babel expects the user of the configuration function to tell it how to manage the cache in the configuration file.

    • Api.cache.forever () – Permacache calculates the configuration without calling the function.
    • Api.cache.never () – Do not cache this configuration and re-execute the function each time.
    • Api.cache. using (() =>process.env.node_env) – Caching based on the node_env value. Each time the using callback returns a value other than the expected value, the overall configuration function is called again and a new entry is added to the cache.
    • Api.cache.invalidate (() =>process.env.node_env) – Caching based on node_env values. Each time the using callback returns a value other than the expected value, the overall configuration function is called again, and all entries in the cache are replaced with results. Since the actual callback results are used to check whether the cache entry is valid, it is recommended that the callback be small and have no side effects. Callbacks should return the smallest possible range of values. For example, the. Using (() =>process.env.node_env) usage above is not ideal because it creates an unknown number of cache entries based on the detected node_env value. It’s safer that way. Use (() =>process.env.node_env== “development”) because the cache entry can only be true or false. Callbacks should be small and have no side effects.
  • API. Env (…). Since node_env is a very common method of switching behavior, Babel also includes an API function specifically for this purpose. This API is used as a quick way to check the “envname” used when Babel is loaded, and the node env is taken into account if no other override environment is set. It takes several different forms: if envname== “production”, api.env (” production “) returns true. Env ([” development “, “test”]) returns true if [” development “, “test”] contains (envname). Api.env () returns the current envname string. If env starts with “test-“, api.env (envname=>envname.starts with (” test- “)) returns true. This function internally uses the api.cache mentioned below to ensure that Babel knows that the build depends on a specific envname.

  • Caller (CB) This API is used as a method to access caller data that has been passed to Babel. Because many instances of Babel may run in the same process with different caller values, the API is designed to automatically configure api.cache in the same way as api.env (). The caller value can be used as the first argument to the callback function. Better to use function isBabelRegister(caller) {return!! (caller && caller.name === “@babel/register”); }

module.exports = function(api) { const isRegister = api.caller(isBabelRegister);

return { // … }; }

Switch configuration behavior based on the specific environment.

  • Api.assertversion (range) While api.version is useful in general, sometimes it’s good to just declare your version. This API exposes a simple way to do this: module.exports = function(API) {api.assertVersion(“^7.2”);

    return { // … }; };