ImportMap

ctx.Response.ImportMap provides access to the import map that will be sent to the browser along with the HTTP response.

The import maps allow you to associate JavaScript module specifications with a URL. This allows you to make imports such as import React from "react" without using relative routes or including the actual location of the module within the client code.

GOX automatically generates an import map when a page uses functionalities that need JavaScript modules, such as Actions, WebSockets or Customer componentsAs a page can only contain an import map, any additional input should be given by ctx.Response.ImportMap.


Execution flow

GOX generates certain inputs during the compilation when it detects that a page needs to use them.

StatusEntrance generated
Always.@gox/websocket
Declares a return function gox.Action@gox/actions
Client framework installedreact, preact, solid, vue, svelte

The inputs generated during the compilation are considered static. ctx.Response.ImportMap allows to add or replace dynamic inputs for the current response.

The element <script type="importmap"> only inserted when the response uses the type of content text/html and contains an element <head></head>.

The responses gox.Page automatically meet these conditions when they produce a full HTML page.


Full example

gox
module main

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

// Agrega "react": "/_gox/client/vendor/react.js"
client Menu react {
    src: "client/menu.jsx"
}

// Agrega "@gox/actions": "/_gox/client/gox-actions.js"
func SaveName(name string, ctx *gox.Context) gox.Action {
    return map[string]any{
        "name": name,
    }
}

func GET(ctx *gox.Context) gox.Page {
    ctx.Response.ImportMap.Set("three", "/scripts/three.js")

    return <html>
        <head></head>
        <body>
            <@Menu hydrate="idle" />
        </body>
    </html>
}

In this example:

  • GOX automatically adds @gox/websocket.
  • The declaration of SaveName makes GOX add @gox/actions.
  • The declaration and use of Menu make GOX add react.
  • The call to ImportMap.Set() adds three.

The import map generated shall be equivalent to:

html
<script type="importmap">
{
    "imports": {
        "@gox/websocket": "/_gox/websocket/client.js",
        "@gox/actions": "/_gox/client/gox-actions.js",
        "react": "/_gox/client/vendor/react.js",
        "three": "/scripts/three.js"
    }
}
</script>

The exact content of the import map depends on the features used by the page. GOX combines the inputs generated during the compilation with the added inputs by ctx.Response.ImportMap.

When a dynamic input uses the same specification as a static input, the dynamic input replaces its URL for that response.


Structure

ctx.Response.ImportMap implement the following API:

text
ImportMap
{
    Set(specifier string, url string)
    Get(specifier string) (string, bool)
    Has(specifier string) bool
    Delete(specifier string)
    Len() int
}

Methods

MethodDescription
Set()Add or replace an input from the import map.
Get()Returns the URL associated with a specific.
Has()It indicates if a specific exists.
Delete()Eliminates a dynamic input from the import map.
Len()Returns the number of dynamic inputs available.

Set()

Firma:func (ImportMap) Set(specifier string, url string)

Set() add a new entry to the import map of the response.

If the specific already exists, the previous URL is replaced by the new one.

gox
func GET(ctx *gox.Context) gox.Page {
    ctx.Response.ImportMap.Set("three", "/scripts/three.js")

    return nil
}

The spaces at the beginning and end of the specifiers and the URL are automatically removed by ctx.Response.ImportMap.

Dynamic inputs have priority over static inputs generated during the compilation. This allows to replace the URL of a module for a specific response.

Use Set() when you need to register an additional JavaScript module or temporarily replace an input generated by GOX.


Get()

Firma:func (ImportMap) Get(specifier string) (string, bool)

Get() returns the URL associated with a specific and indicates whether the dynamic input exists.

gox
func GET(ctx *gox.Context) gox.Page {
    url, ok := ctx.Response.ImportMap.Get("three")

    if !ok {
        return "Module not found"
    }

    return url
}

When the specific does not exist, it returns an empty string and false.

Get() only check the dynamic inputs administered by ctx.Response.ImportMapThe static inputs generated during the compilation are not part of this collection.


Has()

Firma:func (ImportMap) Has(specifier string) bool

Has() indicates whether there is a dynamic input for a specific.

gox
func GET(ctx *gox.Context) gox.Page {
    if ctx.Response.ImportMap.Has("three") {
        return "Module registered"
    }

    return "Module not registered"
}

Returns true where the specific exists and false otherwise.

Use Has() when you only need to check if a dynamic input is registered.


Delete()

Firma:func (ImportMap) Delete(specifier string)

Delete() removes a dynamic input from the import map.

gox
func GET(ctx *gox.Context) gox.Page {
    ctx.Response.ImportMap.Set("three", "/scripts/three.js")
    ctx.Response.ImportMap.Delete("three")

    return nil
}

If the specific does not exist, the operation does not produce any effect.

Delete() only delete the added inputs by ctx.Response.ImportMap. The static inputs generated automatically by GOX during the compilation are not removed.


Len()

Firma:func (ImportMap) Len() int

Len() returns the number of dynamic inputs recorded in the import map.

gox
func GET(ctx *gox.Context) gox.Page {
    ctx.Response.ImportMap.Set("three", "/scripts/three.js")
    ctx.Response.ImportMap.Set("editor", "/scripts/editor.js")

    total := ctx.Response.ImportMap.Len()

    return total
}

Each specific is counted one time, regardless of the number of times it has been updated by Set().

The static inputs generated by GOX during the compilation are not included in the result.


Best practices

  • Use ctx.Response.ImportMap instead of manually adding another element <script type="importmap">.
  • It uses descriptive and stable specifications.
  • Keep the specifications consistent with those used by the instructions import JavaScript.
  • Avoid recording the same specific several times within a response.
  • Use Has() before replacing an input when you need to keep an existing dynamic configuration.
  • Use Delete() only to remove dynamically added inputs during the response.
  • Avoid replacing GOX internal modules unless you understand the consequences for the client runtime.

See also

Next step

Continue with Error to learn to consult the error associated with the current request.

Error