Modules
An NX file is still a module, but imports now target libraries. A library is a directory whose .nx
files contribute declarations recursively. For the full grammar, see
nx-grammar.md.
File Layout
Section titled “File Layout”- Imports appear at the top of the file and pull in declarations from library directories.
- Local declarations use
let,type,action, orcomponent. - A module may export a root element directly or expose named bindings.
import "./theme"import { Button, Input } from "./ui"import { Stack as Layout.Stack } from "./layout"
let greeting = "Hello"private let <WelcomeMessage/> = <span>Hello World</span>export let accentName = "hello"
<Layout.Stack> <text>{accentName}</text> <WelcomeMessage/> <Button/> <Input/></Layout.Stack>Imports
Section titled “Imports”import "<library>"brings every visible export into scope unqualified.import "<library>" as Namespacekeeps imported symbols underNamespace.import { Name } from "<library>"imports specific declarations without qualification.import { Name as Prefix.Name } from "<library>"adds only a qualification prefix; the final segment must remainName.- Importing the same library path twice in one file is a compile error.
- If two libraries export the same unqualified name, NX reports an error only when that ambiguous name is used.
- Local directory libraries are supported today. Git directory URLs and HTTP zip URLs parse, but currently resolve with a “not yet supported” diagnostic.
Libraries
Section titled “Libraries”- A library is a directory, not a barrel file.
- Every
.nxfile under that directory contributes declarations recursively. - Declarations are internal by default, so helper bindings stay inside the library unless marked
export.
Built-in declarations
Section titled “Built-in declarations”NX’s built-in types are declared in the NX prelude, a module every file imports automatically. Nothing names it and nothing enables it: its exported declarations are simply in scope in every module, in every build — a single file, a workspace, a library, an editor session.
- The prelude lives under the reserved
@nx/root, as the module@nx/prelude.nx. A workspace may not supply a module under that identity. - Its names are shadowable. A declaration of your own, or a name from any import you wrote, takes the name silently, exactly as it would over a wildcard import. There is no diagnostic and no ambiguity: a prelude name is bound last, and only where nothing else claimed it.
- Shadowing a built-in disables the syntax that means it. A module that declares its own
Rangecannot use..or..=there, because those operators construct the prelude’sRange; the element form still works, and every other module is unaffected. - A library’s exports are its own declarations. The prelude is never re-exported.
The prelude is one ordinary NX declaration:
export type Range = { T:type start:T end:T endInclusive:boolean}See Ranges for what Range means and
for for counting over one.
Root Elements
Section titled “Root Elements”- A root element at the end of the file behaves like
main. Tooling can render it immediately or expose it as the module default. - Alternatively, export named bindings and let consumers choose what to render.
Visibility
Section titled “Visibility”| Keyword | Same file | Other library files | Consumers |
|---|---|---|---|
private |
Yes | No | No |
| default | Yes | Yes | No |
export |
Yes | Yes | Yes |
privatekeeps declarations in the current file only.- Omitting a visibility keyword shares declarations across files in the same library or program while hiding them from external consumers.
exportexposes declarations to importing libraries.
See also
Section titled “See also”- Language Tour: Modules & Imports
- Grammar: nx-grammar.md – Module Definition