Import aliases

The import aliases allow the use of stable routes for private GOX modules located within the pages/.

A route that starts with @ is resolved from the directory of the importing file to its ancestors until reaching the root of pages/.

gox
import "@layout.gox"

Declaration

An alias is created when you name a file or directory with the prefix @.

text
pages/
├── @layout.gox
├── @components/
│   └── header.gox
└── index.gox

The modules can be imported using their routes, alias:

gox
import (
    "@layout.gox"
    "@components/header.gox"
)

The prefix is part of the import route and does not change the name declared by module.


Hierarchical resolution

GOX begins the search in the directory containing the importing file. If you do not find the requested route, continue in each ancestral directory until you reach pages/.

text
pages/
├── @layout.gox
└── dashboard/
    └── reports/
        └── index.gox

From pages/dashboard/reports/index.gox:

gox
import "@layout.gox"

The search follows this order:

text
pages/dashboard/reports/@layout.gox
pages/dashboard/@layout.gox
pages/@layout.gox

The first match found is used as an imported module.


Shadowing

One alias closer to the importing file replaces another available in a higher directory.

text
pages/
├── @layout.gox
├── index.gox
└── dashboard/
    ├── @layout.gox
    └── dashboard.gox

The same import produces different results according to the file that uses it:

gox
import "@layout.gox"
ImporterSolved file
pages/index.goxpages/@layout.gox
pages/dashboard/dashboard.goxpages/dashboard/@layout.gox

The root alias remains available for the rest of the tree. The local copy only modifies the resolution of the files located within its own subtree.


Directory aliases

The directories whose name begins with @ allow to group several related modules.

text
pages/
├── @components/
│   ├── header.gox
│   └── footer.gox
└── dashboard/
    ├── @components/
    │   └── menu.gox
    └── dashboard.gox

From pages/dashboard/dashboard.gox:

gox
import (
    "@components/header.gox"
    "@components/menu.gox"
)

Each file is solved independently:

text
@components/header.gox
→ pages/@components/header.gox

@components/menu.gox
→ pages/dashboard/@components/menu.gox

It is not necessary for the local directory to contain all the files in the alias. When a specific file does not exist locally, GOX continues to search for it in the higher directories.


Sibling and descendant directories

The resolution does not seek aliases within sister folders, descendants or independent branches.

text
pages/
├── account/
│   └── @layout.gox
└── dashboard/
    └── dashboard.gox

This import from pages/dashboard/dashboard.gox:

gox
import "@layout.gox"

can't solve:

text
pages/account/@layout.gox

To share the alias between the two areas it must be placed in a common ancestor:

text
pages/
├── @layout.gox
├── account/
└── dashboard/

Mandatory extension

Imports by alias should explicitly include the extension of the .gox.

gox
import "@layout.gox"

The following import is not valid:

gox
import "@layout"

GOX also does not implicitly solve a file index.gox.

text
pages/
└── @components/
    └── index.gox

The full route should be indicated:

gox
import "@components/index.gox"

Private routes

The files and directories whose name begins with @ are private to the routing system.

text
pages/
├── @layout.gox
├── @components/
│   └── header.gox
└── index.gox

They can be imported from other GOX modules, but do not produce HTTP routes. Direct requests to these locations respond to 404.

The prefix @ allows to keep components and auxiliary modules close to the pages that use them without publicly exposing them.


Scope

The import aliases are limited to the directory pages/.

The importing file must be found within the pages/, and the solved file must remain within the same tree. aliases do not search for files within:

text
app/
client/
components/
public/
websocket/

They also do not allow out of pages/ by segments .., absolute routes, backslashes or symbolic links that point out of the directory.


Hot reload

GOX observes the aliases used by the loaded modules.

When a closer alias is created, GOX resolves the import and applies the new shadowing. If the local file is deleted, the resolution automatically returns to the alias available in the top directory.


Full example

The application uses a shared layout, a global header and a specific menu for the dashboard:

text
pages/
├── @layout.gox
├── @components/
│   └── header.gox
├── index.gox
└── dashboard/
    ├── @components/
    │   └── menu.gox
    └── dashboard.gox

The shared layout states:

gox
module layout

import "github.com/gox-lang/gox"

func Title(name string) gox.Component {
    return <h1>Bienvenido, {{name}}</h1>
}

The global header states:

gox
module header

import "github.com/gox-lang/gox"

func Show() gox.Component {
    return <header>GOX</header>
}

The local menu states:

gox
module menu

import "github.com/gox-lang/gox"

func Show() gox.Component {
    return <nav>Dashboard</nav>
}

The page pages/dashboard/dashboard.gox imports the three modules:

gox
module dashboard

import (
    "github.com/gox-lang/gox"
    "@layout.gox"
    "@components/header.gox"
    "@components/menu.gox"
)

func GET(ctx *gox.Context) gox.Page {
    return <html>
        <head>
            <title>Dashboard</title>
        </head>
        <body>
            <&header.Show />
            <&layout.Title name="George" />
            <&menu.Show />
        </body>
    </html>
}

GOX solves:

text
@layout.gox
→ pages/@layout.gox

@components/header.gox
→ pages/@components/header.gox

@components/menu.gox
→ pages/dashboard/@components/menu.gox

The Layout and the header use the ancestral fallback. The menu uses the nearest alias.


Import names and import aliases

The import aliases defined by @ should not be confused with Go's syntactic aliases.

gox
import navigation "@components/menu.gox"

In this case:

  • @components/menu.gox determines which file to load.
  • navigation determines how the module is used within the current file.
gox
<&navigation.Show />

Both mechanisms can be used together.


Integration with Go

The aliases expand the resolution of GOX modules without changing the operation of the Go package imports. Once the file is resolved, its public members are used with the same rules of modules, visibility and identifiers that are familiar to those working with Go.

The hierarchical search belongs exclusively to the files .gox located in pages/. The Go packages continue to be resolved by their usual import route.


Best practices

  • Place at the root of pages/ the aliases shared throughout the application.
  • It creates local aliases when a section needs to replace a shared implementation.
  • Use directories @ to group related modules.
  • It retains consistent names between local and ancestral aliases.
  • Always includes extension .gox.
  • It explicitly writes the name of each file; do not depend on index.gox.
  • Avoid hard-to-identify Shadowing structures.
  • Keep the aliases inside of pages/.
  • Use syntactic aliases when you need to avoid conflict between module names.

To learn more about ImportsSee your documentation. To learn more about ModulesSee your documentation. To learn more about PagesSee your documentation. To learn more about Rupture, check your documentation.


See also

Next step

Continue with Templates to learn how to build interfaces with GOX's declarative syntax.

Template system