Options
- Primary options
- Config Loading options
- Plugin and Preset configuration
- Config Merging options
- Source Map options
- Misc options
- Code Generator options
- AMD / UMD / SystemJS options
- Option concepts
- The filename is exposed to plugins. Some plugins may require the presence of the filename.
-
Options like
"test"
,"exclude"
, and"ignore"
require the filename for string/RegExp matching. -
.babelrc.json
or.babelrc
files are loaded relative to the file being compiled. If this option is omitted, Babel will behave as ifbabelrc: false
has been set. -
The base directory when checking for the default
"configFile"
value -
The default value for
"babelrcRoots"
. -
"root"
- Passes the"root"
value through as unchanged. -
"upward"
- Walks upward from the"root"
directory, looking for a directory containing ababel.config.json
file, and throws an error if ababel.config.json
is not found. -
"upward-optional"
- Walk upward from the"root"
directory, looking for a directory containing ababel.config.json
file, and falls back to"root"
if ababel.config.json
is not found. -
true
to generate a sourcemap for the code and include it in the result object. -
"inline"
to generate a sourcemap and append it as a data URL to the end of the code, but not include it in the result object. -
"both"
is the same as inline, but will include the map in the result object. -
true
will write the map to a.map
file on disk -
"inline"
will write the file directly, so it will have adata:
containing the map -
"both"
will write the file with adata:
URL and also a.map
. -
"script"
- Parse the file using the ECMAScript Script grammar. Noimport
/export
statements allowed, and files are not in strict mode. -
"module"
- Parse the file using the ECMAScript Module grammar. Files are automatically strict, andimport
/export
statements are allowed. -
"unambiguous"
- Consider the file a "module" ifimport
/export
statements are present, or else consider it a "script". -
key
is a simple opaque string that represents the plugin being executed. -
nodeType
is the type of AST node currently being visited. -
fn
is the visitor function itself. -
string
- A file path with simple support for*
and**
as full slug matches. Any file or parent folder matching the pattern counts as a match. The path follow's Node's normal path logic, so on POSIX is must be/
-separated, but on Windows both/
and\
are supported. -
RegExp
- A regular expression to match against the normalized filename. On POSIX the path RegExp will run against a/
-separated path, and on Windows it will be on a\
-separated path. -
(filename: string | void, context: { caller: { name: string } | void, envName: string, dirname: string }) => boolean
is a general callback that should return a boolean to indicate whether it is a match or not. The function is passed the filename orundefined
if one was not given to Babel. It is also passed the currentenvName
andcaller
options that were specified by the top-level call to Babel anddirname
that is either a directory of the configuration file or the current working directory (if the transformation was called programmatically). -
EntryTarget
- Individual plugin -
[EntryTarget, EntryOptions]
- Individual plugin w/ options -
[EntryTarget, EntryOptions, string]
- Individual plugin with options and name (see merging for more info on names) -
ConfigItem
- A plugin configuration item created bybabel.createConfigItem()
. -
string
- Arequire
-style path or plugin/preset identifier. Identifiers will be passed through name normalization . -
{} | Function
- An actual plugin/preset object or function after it has beenrequire()
ed. - Absolute paths pass through untouched.
-
Relative paths starting with
./
pass through untouched. - References to files within a package are untouched.
-
Any identifier prefixed with
module:
will have the prefix removed but otherwise be untouched. -
plugin-
/preset-
will be injected at the start of any@babel
-scoped package that doesn't have it as a prefix. -
babel-plugin-
/babel-preset-
will be injected as a prefix any unscoped package that doesn't have it as a prefix. -
babel-plugin-
/babel-preset-
will be injected as a prefix any@
-scoped package that doesn't have it anywhere in their name.
Options can be passed to Babel in a variety of ways. When passed directly to Babel, you can just pass the options object. When Babel is used via a wrapper, it may also be necessary, or at least more useful, to pass the options via configuration files .
If passing options via
@babel/cli
you'll need to
kebab-case
the names. i.e.
npx babel --root-mode upward file.js # equivalent of passing the rootMode config option
Primary options
These options are only allowed as part of Babel's programmatic options, so
they are primarily for use by tools that wrap around Babel, or people calling
babel.transform
directly. Users of Babel's integrations, like
babel-loader
or
@babel/register
are unlikely to use these.
cwd
Type:
string
Default:
process.cwd()
The working directory that all paths in the programmatic options will be resolved relative to.
caller
Type: An object with the shape of
interface CallerData {
name: string;
supportsStaticESM?: boolean;
supportsDynamicImport?: boolean;
supportsTopLevelAwait?: boolean;
supportsExportNamespaceFrom?: boolean;
}
History
Version | Changes |
---|---|
v7.11.0 |
Add
supportsExportNamespaceFrom
|
v7.7.0 |
Add
supportsTopLevelAwait
|
v7.5.0 |
Add
supportsDynamicImport
|
Utilities may pass a
caller
object to identify themselves to Babel and pass
capability-related flags for use by configs, presets and plugins. For example
babel.transformFileSync("example.js", {
caller: {
name: "my-custom-tool",
supportsStaticESM: true,
},
});
would allow plugins and presets to decide that, since ES modules are supported, they will skip compilation of ES modules into CommonJS modules.
filename
Type:
string
The filename associated with the code currently being compiled, if there is one. The filename is optional, but not all of Babel's functionality is available when the filename is unknown, because a subset of options rely on the filename for their functionality.
The three primary cases users could run into are:
filenameRelative
Type:
string
Default:
path.relative(opts.cwd, opts.filename)
(if
"filename"
was passed)
Used as the default value for Babel's
sourceFileName
option, and used
as part of generation of filenames for the AMD / UMD / SystemJS module transforms.
code
Type:
boolean
Default:
true
Babel's default return value includes
code
and
map
properties with the
resulting generated code. In some contexts where multiple calls to Babel
are being made, it can be helpful to disable code generation and instead
use
ast: true
to get the AST directly in order to avoid doing unnecessary work.
ast
Type:
boolean
Default:
false
Babel's default is to generate a string and a sourcemap, but in some contexts it can be useful to get the AST itself. The primary use case for this would be a chain of multiple transform passes, along the lines of
const filename = "example.js";
const source = fs.readFileSync(filename, "utf8");
// Load and compile file normally, but skip code generation.
const { ast } = babel.transformSync(source, {
filename,
ast: true,
code: false,
});
// Minify the file in a second pass and generate the output code here.
const { code, map } = babel.transformFromAstSync(ast, source, {
filename,
presets: ["minify"],
babelrc: false,
configFile: false,
});
Note: This option is not on by default because the majority of users won't need it and because we'd like to eventually add a caching layer to Babel. Having to cache the AST structure will take significantly more space.
cloneInputAst
Type:
boolean
Default:
true
Added in
v7.11.0
By default
babel.transformFromAst
will clone the input AST to avoid mutations.
Specifying
cloneInputAst: false
can improve parsing performance if the input AST
is not used elsewhere.
Config Loading options
Loading configuration can get a little complex as environments can have several types of configuration files, and those configuration files can have various nested configuration objects that apply depending on the configuration.
root
Type:
string
Default:
opts.cwd
Placement: Only allowed in Babel's programmatic options
The initial path that will be processed based on the
"rootMode"
to determine the conceptual root folder for the current Babel project.
This is used in two primary cases:
rootMode
Type:
"root" | "upward" | "upward-optional"
Default:
"root"
Placement: Only allowed in Babel's programmatic options
Added in:
v7.1.0
This option, combined with the
"root"
value, defines how Babel
chooses its project root. The different modes define different ways that
Babel can process the
"root"
value to get the final project root.
Note:
babel.config.json
is supported from Babel 7.8.0. In older Babel 7 versions, only
babel.config.js
is supported.
"root"
is the default mode because it avoids the risk that Babel will
accidentally load a
babel.config.json
that is entirely outside of the current
project folder. If you use
"upward-optional"
, be aware that it will walk up the
directory structure all the way to the filesystem root, and it is always
possible that someone will have a forgotten
babel.config.json
in their home
directory, which could cause unexpected errors in your builds.
Users with monorepo project structures that run builds/tests on a per-package basis
may well want to use
"upward"
since monorepos often have a
babel.config.json
in the project root. Running Babel in a monorepo subdirectory without
"upward"
,
will cause Babel to skip loading any
babel.config.json
files in the project root, which can lead to unexpected errors and compilation failure.
envName
Type:
string
Default:
process.env.BABEL_ENV || process.env.NODE_ENV || "development"
Placement: Only allowed in Babel's programmatic options
The current active environment used during configuration loading. This value
is used as the key when resolving
"env"
configs, and is also
available inside configuration functions, plugins, and presets, via the
api.env()
function.
configFile
Type:
string | boolean
Default:
path.resolve(opts.root, "babel.config.json")
, if it exists,
false
otherwise
Placement: Only allowed in Babel's programmatic options
Defaults to searching for a default
babel.config.json
file, but can be passed
the path of any JS or JSON5 config file.
NOTE: This option does
not
affect loading of
.babelrc.json
files, so while
it may be tempting to do
configFile: "./foo/.babelrc.json"
, it is not recommended.
If the given
.babelrc.json
is loaded via the standard
file-relative logic, you'll end up loading the same config file twice, merging it with itself.
If you are linking a specific config file, it is recommended to stick with a
naming scheme that is independent of the "babelrc" name.
babelrc
Type:
boolean
Default:
true
as long as the
filename
option has been specified
Placement: Allowed in Babel's programmatic options, or inside of the loaded
"configFile"
. A programmatic option will override a config file one.
true
will enable searching for
configuration files
and the legacy
.babelignore
file relative to the
"filename"
provided to Babel.
A
babelrc
value passed in the programmatic options will override one set
within a configuration file.
Note:
.babelrc.json
files are only loaded if the current
"filename"
is inside of
a package that matches one of the
"babelrcRoots"
packages.
babelrcRoots
Type:
boolean | MatchPattern | Array<MatchPattern>
Default:
opts.root
Placement: Allowed in Babel's programmatic options, or inside of the loaded
configFile
. A programmatic option will override a config file one.
By default, Babel will only search for
.babelrc.json
files within the
"root"
package
because otherwise Babel cannot know if a given
.babelrc.json
is meant to be loaded, or
if it's
"plugins"
and
"presets"
have even been installed, since the file being
compiled could be inside
node_modules
, or have been symlinked into the project.
This option allows users to provide a list of other packages that should be considered
"root" packages when considering whether to load
.babelrc.json
files.
For example, a monorepo setup that wishes to allow individual packages to have their own configs might want to do
babelrcRoots: [
// Keep the root as a root
".",
// Also consider monorepo packages "root" and load their .babelrc.json files.
"./packages/*",
];
Plugin and Preset options
plugins
Type:
Array<PluginEntry | Plugin>
(
PluginEntry
)
Default:
[]
An array of plugins to activate when processing this file. For more information on how
individual entries interact, especially when used across multiple nested
"env"
and
"overrides"
configs, see
merging
.
Note: The option also allows
Plugin
instances from Babel itself, but
using these directly is not recommended. If you need to create a persistent
representation of a plugin or preset, you should use
babel.createConfigItem()
.
presets
Type:
Array<PresetEntry>
(
PresetEntry
)
Default:
[]
An array of presets to activate when processing this file. For more information on how
individual entries interact, especially when used across multiple nested
"env"
and
"overrides"
configs, see
merging
.
Note: The format of presets is identical to plugins, except for the fact that
name normalization expects "preset-" instead of "plugin-", and presets cannot
be instances of
Plugin
.
passPerPreset
Type:
boolean
Default:
false
Status:
Deprecated
Instructs Babel to run each of the presets in the
presets
array as an
independent pass. This option tends to introduce a lot of confusion around
the exact ordering of plugins, but can be useful if you absolutely need to run
a set of operations as independent compilation passes.
Note: This option may be removed in future Babel versions as we add better support for defining ordering between plugins.
Output targets
targets
Type:
string | Array<string> | { [string]: string }
Default:
{}
Placement: Allowed in Babel's programmatic options, or in config files
Added in:
v7.13.0
History
Version | Changes |
---|---|
v7.20.0
|
Support
deno
target
|
v7.15.0
|
Support
rhino
target
|
Describes the environments you support/target for your project.
This can either be a browserslist-compatible query (with caveats ):
{
"targets": "> 0.25%, not dead"
}
Or an object of minimum environment versions to support:
{
"targets": {
"chrome": "58",
"ie": "11"
}
}
Supported environments:
android
,
chrome
,
deno
,
edge
,
electron
,
firefox
,
ie
,
ios
,
node
,
opera
,
rhino
,
safari
,
samsung
.
If a minor version is not specified, Babel will interpret it as
MAJOR.0
. For example,
"node": 12
will be considered as Node.js 12.0.
No targets
When no targets are specified: Babel will assume you are targeting the oldest browsers possible. For example,
@babel/preset-env
will transform all ES2015-ES2020 code to be ES5 compatible.
We recommend setting
targets
to reduce the output code size.
{
"presets": ["@babel/preset-env"]
}
Because of this, Babel's behavior is different than
browserslist
: it does
not
use the
defaults
query when there are no targets are found in your Babel
or
browserslist config(s). If you want to use the
defaults
query, you will need to explicitly pass it as a target:
{
"targets": "defaults"
}
We recognize this isn’t ideal and will be revisiting this in Babel v8.
targets.esmodules
Type:
boolean
You may also target browsers supporting
ES Modules
. When the
esmodules
target is specified, it will intersect with the
browsers
target and
browserslist
's targets. You can use this approach in combination with
<script type="module"></script>
to conditionally serve smaller scripts to users (
https://jakearchibald.com/2017/es-modules-in-browsers/#nomodule-for-backwards-compatibility
).
browsers
and the esmodules target, they will be intersected.
{
"targets": {
"esmodules": true
}
}
targets.node
Type:
string | "current" | true
.
If you want to compile against the current node version, you can specify
"node": true
or
"node": "current"
, which would be the same as
"node": process.versions.node
.
Alternatively, you can specify the node version in a browserslist query:
{
"targets": "node 12" // not recommended
}
In this case, browserslist will resolve it to the
latest
version available in the
node-releases
library. Because Node.js may support new language features in minor releases, a program generated for Node.js 12.22 may throw a syntax error on Node.js 12.0. We recommend that you always specify a minor version when using node queries with browserslist:
{
"targets": "node 12.0"
}
targets.safari
Type:
string | "tp"
.
If you want to compile against the
technology preview
version of Safari, you can specify
"safari": "tp"
.
targets.browsers
Type:
string | Array<string>
.
A query to select browsers (ex: last 2 versions, > 5%, safari tp) using browserslist .
Note, browsers' results are overridden by explicit items from
targets
.
targets.deno
Type:
string
.
The minimum supported version is 1.0.
{
"targets": {
"deno": "1.9"
}
}
browserslistConfigFile
Type:
boolean
Default:
true
Placement: Allowed in Babel's programmatic options, or in config files
Added in:
v7.13.0
Toggles whether or not browserslist config sources are used, which includes searching for any browserslist files or referencing the browserslist key inside package.json. This is useful for projects that use a browserslist config for files that won't be compiled with Babel.
If a string is specified, it must represent the path of a browserslist configuration file. Relative paths are resolved relative to the configuration file which specifies this option, or to
cwd
when it's passed as part of the programmatic options.
browserslistEnv
Type:
string
Default:
undefined
Placement: Allowed in Babel's programmatic options, or in config files
Added in:
v7.13.0
The Browserslist environment to use.
Config Merging options
extends
Type:
string
Placement: Not allowed inside of presets
Configs may "extend" other configuration files. Config fields in the current config will be merged on top of the extended file's configuration.
env
Type:
{ [envKey: string]: Options }
Placement: May not be nested inside of another
env
block.
Allows for entire nested configuration options that will only be enabled
if the
envKey
matches the
envName
option.
Note:
env[envKey]
options will be
merged
on top of the options specified in
the root object.
overrides
Type:
Array<Options>
Placement: May not be nested inside of another
overrides
object, or within an
env
block.
Allows users to provide an array of options that will be
merged
into the current
configuration one at a time. This feature is best used alongside the
"test"
/
"include"
/
"exclude"
options to provide conditions for which an override should apply. For example:
overrides: [{
test: "./vendor/large.min.js",
compact: true,
}],
could be used to enable the
compact
option for one specific file that is known
to be large and minified, and tell Babel not to bother trying to print the file nicely.
test
Type:
MatchPattern | Array<MatchPattern>
(
MatchPattern
)
If all patterns fail to match, the current configuration object is considered
inactive and is ignored during config processing. This option is most useful
when used within an
overrides
option object, but it's allowed anywhere.
Note: These toggles do not affect the programmatic and config-loading options in earlier sections, since they are taken into account long before the configuration that is prepared for merging.
include
Type:
MatchPattern | Array<MatchPattern>
(
MatchPattern
)
This option is a synonym for
"test"
.
exclude
Type:
MatchPattern | Array<MatchPattern>
(
MatchPattern
)
If any of patterns match, the current configuration object is considered
inactive and is ignored during config processing. This option is most useful
when used within an
overrides
option object, but it's allowed anywhere.
Note: These toggles do not affect the programmatic and config-loading options in earlier sections, since they are taken into account long before the configuration that is prepared for merging.
ignore
Type:
Array<MatchPattern>
(
MatchPattern
)
Placement: Not allowed inside of presets
If any of the patterns match, Babel will immediately stop all processing of the current build. For example, a user may want to do something like
ignore: ["./lib"];
to explicitly disable Babel compilation of files inside the
lib
directory.
Note: This option disables
all
Babel processing of a file. While that has
its uses, it is also worth considering the
"exclude"
option as a less aggressive
alternative.
only
Type:
Array<MatchPattern>
(
MatchPattern
)
Placement: Not allowed inside of presets
If all of the patterns fail to match, Babel will immediately stop all processing of the current build. For example, a user may want to do something like
only: ["./src"];
to explicitly enable Babel compilation of files inside the
src
directory
while disabling everything else.
Note: This option disables
all
Babel processing of a file. While that has
its uses, it is also worth considering the
"test"
/
"include"
options as a less aggressive alternative.
Source Map options
inputSourceMap
Type:
boolean | SourceMap
Default:
true
true
will attempt to load an input sourcemap from the file itself, if it
contains a
//# sourceMappingURL=...
comment. If no map is found, or the
map fails to load and parse, it will be silently discarded.
If an object is provided, it will be treated as the source map object itself.
sourceMaps
Type:
boolean | "inline" | "both"
Default:
false
@babel/cli
overloads some of these to also affect how maps are written to disk:
Note: These options are bit weird, so it may make the most sense to just use
true
and handle the rest in your own code, depending on your use case.
sourceMap
This is an synonym for
sourceMaps
. Using
sourceMaps
is recommended.
sourceFileName
Type:
string
Default:
path.basename(opts.filenameRelative)
when available, or
"unknown"
The name to use for the file inside the source map object.
sourceRoot
Type:
string
The
sourceRoot
fields to set in the generated source map, if one is desired.
Misc options
sourceType
Type:
"script" | "module" | "unambiguous"
Default: "module"
unambiguous
can be quite useful in contexts where the type is unknown, but it can lead to
false matches because it's perfectly valid to have a module file that does not use
import
/
export
statements.
This option is important because the type of the current file affects both
parsing of input files, and certain transforms that may wish to add
import
/
require
usage to the current file.
For instance,
@babel/plugin-transform-runtime
relies on the type of the current document to decide whether to insert
an
import
declaration, or a
require()
call.
@babel/preset-env
also does the same for its
"useBuiltIns"
option. Since Babel defaults to treating files
are ES modules, generally these plugins/presets will insert
import
statements. Setting
the correct
sourceType
can be important because having the wrong type can lead to cases
where Babel would insert
import
statements into files that are meant to be CommonJS
files. This can be particularly important in projects where compilation
of
node_modules
dependencies is being performed, because inserting an
import
statements can cause Webpack and other tooling to see a file
as an ES module, breaking what would otherwise be a functional CommonJS file.
Note: This option will not affect parsing of
.mjs
files, as they are currently
hard-coded to always parse as
"module"
files.
assumptions
Type:
{ [assumption: string]: boolean }
Default:
{}
Added in:
v7.13.0
Placement: Allowed in programmatic options, config files and presets.
Set assumptions that Babel can make in order to produce smaller output:
{
"assumptions": {
"iterableIsArray": true
},
"presets": ["@babel/preset-env"]
}
For more informations, check the assumptions documentation page.
highlightCode
Type:
boolean
Default:
true
Highlight tokens in code snippets in Babel's error messages to make them easier to read.
wrapPluginVisitorMethod
Type:
(key: string, nodeType: string, fn: Function) => Function
Allows users to add a wrapper on each visitor in order to inspect the visitor process as Babel executes the plugins.
Users can return a replacement function that should call the original function after performing whatever logging and analysis they wish to do.
parserOpts
Type:
{}
An opaque object containing options to pass through to the parser being used.
For available parser options, see Parser Options .
generatorOpts
Type:
{}
An opaque object containing options to pass through to the code generator being used. See Code Generator Options for most used options.
Code Generator options
retainLines
Type:
boolean
Default:
false
Babel will make an effort to generate code such that items are printed on the same line that they were on in the original file. This option exists so that users who cannot use source maps can get vaguely useful error line numbers, but it is only a best-effort, and is not guaranteed in all cases with all plugins.
compact
Type:
boolean | "auto"
Default:
"auto"
"auto" will set the value by evaluating
code.length > 500_000
All optional newlines and whitespace will be omitted when generating code in compact mode.
minified
Type:
boolean
Default:
false
Includes
compact: true
, omits block-end semicolons, omits
()
from
new Foo()
when possible, and may output shorter versions of literals.
auxiliaryCommentBefore
Type:
string
Allows specifying a prefix comment to insert before pieces of code that were not present in the original file.
Note: The definition of what is and isn't present in the original file can get a little ugly, so usage of this option is not recommended . If you need to annotate code somehow, it is better to do so using a Babel plugin.
auxiliaryCommentAfter
Type:
string
Allows specifying a prefix comment to insert after pieces of code that were not present in the original file.
Note: The definition of what is and isn't present in the original file can get a little ugly, so usage of this option is not recommended . If you need to annotate code somehow, it is better to do so using a Babel plugin.
comments
Type:
boolean
Default:
true
Provides a default comment state for
shouldPrintComment
if no function
is given. See the default value of that option for more info.
shouldPrintComment
Type:
(value: string) => boolean
Default without
minified
:
(val) => opts.comments || /@license|@preserve/.test(val)
Default with
minified
:
() => opts.comments
A function that can decide whether a given comment should be included in the output code from Babel.
Advanced Usage
For more code generator options, see Generator Options .
AMD / UMD / SystemJS module options
moduleIds
Type:
boolean
Default:
!!opts.moduleId
Enables module ID generation.
moduleId
Type:
string
A hard-coded ID to use for the module. Cannot be used alongside
getModuleId
.
getModuleId
Type:
(name: string) => string
Given the babel-generated module name, return the name to use. Returning
a falsy value will use the original
name
.
moduleRoot
Type:
string
A root path to include on generated module names.
Options Concepts
MatchPattern
Type:
string | RegExp | (filename: string | void, context: { caller: { name: string } | void, envName: string, dirname: string ) => boolean
Several Babel options perform tests against file paths. In general, these options support a common pattern approach where each pattern can be
Importantly, if either of these are used, Babel requires that the
filename
option be present,
and will consider it an error otherwise.
Merging
Please refer to How Babel merges config items .
Plugin/Preset entries
PluginEntry
/
PresetEntry
Individual plugin/preset items can have several different structures:
The same
EntryTarget
may be used multiple times unless each one is given a different
name, and doing so will result in a duplicate-plugin/preset error.
That can be a little hard to read, so as an example:
plugins: [
// EntryTarget
'@babel/plugin-transform-classes',
// [EntryTarget, EntryOptions]
['@babel/plugin-transform-arrow-functions', { spec: true }],
// [EntryTarget, EntryOptions, string]
['@babel/plugin-transform-for-of', { loose: true }, "some-name"],
// ConfigItem
babel.createConfigItem(require("@babel/plugin-transform-spread")),
],
EntryTarget
Type:
string | {} | Function
A plugin/preset target can come from a few different sources:
EntryOptions
Type:
undefined | {} | false
Options are passed through to each plugin/preset when they are executed.
undefined
will be
normalized to an empty object.
false
indicates that an entry is entirely disabled. This can be useful in contexts where ordering
is important, but a separate condition is needed to decide if something is enabled. For instance:
plugins: [
'one',
['two', false],
'three',
],
overrides: [{
test: "./src",
plugins: [
'two',
]
}]
would enable the
two
plugin for files in
src
, but
two
would still execute between
one
and
three
.
Name Normalization
By default, Babel expects plugins to have a
babel-plugin-
or
babel-preset-
prefix in their name.
To avoid repetition, Babel has a name normalization phase will automatically add these prefixes
when loading items. This boils down to a few primary rules: