Skip to content
On this page

Importing assets

Nebula uses Vite to import assets into the frontend. Vite is a frontend build tool that is used to build the frontend assets. Vite is also used to serve the frontend assets during development.

Project structure

The frontend assets are located in the nebula/src directory. The nebula/src directory is structured as follows:

📦nebula/src
 ┣ 📂js
 ┣ 📂public
 ┃ ┣ 📂images
 ┃ ┗ 📂js
 ┣ 📂scss

The nebula/src/js directory contains TypeScript and Vue files that are used to build the frontend.

The nebula/src/public directory contains assets that are used directly by the frontend.

The nebula/src/scss directory contains SCSS files that are used to build the frontend styling.

Note

The nebula/src/public directory is copied as is to the nebula/static directory during production.

Importing assets in html and jinja

Note

This is only used in nebula/templates/index.html to load the Vue app. And likely won’t need to be changed or used anywhere else.

However, since this is a non-standard way of importing assets, it is documented here.

Assets in html and jinja files need to import from different directories depending on the environment. During development, the assets are served by the Vite webserver. During production, the assets are built by Vite and are located in the nebula/static directory.

To help with this difference, the vite template is used to import assets. The vite template is located at nebula/templates/utilities/vite.html.

Usage

The vite template provides the following functions: vite_script, vite_style, vite_asset and vite_public_asset. They can be imported as follows:

html
{% from 'utilities/vite.html' import vite_script with context %}

vite_script

Imports a script. If the script imports any other assets, they will be imported as well.

param: source - The path to the script relative to the nebula/src directory.

Input:

html
{{ vite_script('js/main.ts') }}

Output:

html
<script type="module" src="http://localhost:5173/js/main.ts"></script>
html
<script type="module" src="/static/js/main.js"></script>
<link rel="stylesheet" href="/static/main.css"></link>

vite_style

Imports a style.

param: source - The path to the style relative to the nebula/src directory.

Input:

html
{{ vite_style('scss/main.scss') }}

Output:

html
<link rel="stylesheet" href="http://localhost:5173/scss/main.scss" />
html
<link rel="stylesheet" href="/static/main.css"></link>

vite_asset

Imports an asset. The asset will be imported as is.

param: source - The path to the asset relative to the nebula/src directory.

Input:

html
{{ vite_asset('js/main.js') }}

Output:

html
http://localhost:5173/js/main.js
html
/static/js/main.js

vite_public_asset

Imports a public asset. The asset will be imported as is. When importing a public asset, this function should be used instead of vite_asset. This is because public assets are served from a different location.

param: source - The path to the asset relative to the nebula/src/public directory.

Input:

html
{{ vite_public_asset('images/logo.svg') }}

Output:

html
http://localhost:5173/images/logo.svg
html
/static/images/logo.svg
utilities/vite.html
html
{% macro vite_script(source) -%}
{% if development %}
<script type="module" src="{{'http://localhost:5173/nebula/src/' + source }}"></script>
{% else %}
<script type="module"
    src="{{ url_for('static', filename=(manifest['nebula/src/' + source]['file'])) }}"></script>

{% if manifest['nebula/src/' + source]['css'] %}
{% for css in manifest['nebula/src/' + source]['css'] %}
<link rel="stylesheet" href="{{ url_for('static', filename=css) }}">
{% endfor %}
{% endif %}
{% endif %}
{% endmacro %}

{% macro vite_style(source) -%}
{% if development %}
<link rel="stylesheet" href={{'http://localhost:5173/nebula/src/' + source}}>
{% else %}
<link rel="stylesheet"
    href="{{ url_for('static', filename=(manifest['nebula/src/' + source]['file'])) }}">
{% endif %}
{% endmacro %}

{% macro vite_asset(source) -%}
{% if development %}
{{'http://localhost:5173/nebula/src/' + source }}
{% else %}
{{ url_for('static', filename=(manifest['nebula/src/' + source]['file'])) }}
{% endif %}
{% endmacro %}

{% macro vite_public_asset(source) -%}
{% if development %}
{{'http://localhost:5173/' + source }}
{% else %}
{{ url_for('static', filename=source) }}
{% endif %}
{% endmacro %}

Importing assets in TypeScript and Vue

Assets in TypeScript and Vue files can just be imported the same way as in any other TypeScript or Vue project. Vite will handle the import depending on the environment.

ts
// Import a script from a node module
import { createApp } from "vue";

// Import a local script
import App from "@/App.vue";

// Import a style
import "@scss/main.scss";

// Import an asset
import logo from "@public/images/logo.svg";

Aliases

A few aliases are available to make it easier to import assets. The aliases are defined in nebula/src/js/vite.config.ts.

Creating a new alias is as simple as adding a new entry to the resolve.alias object in vite.config.ts and adding it to "compilerOptions"."paths" in tsconfig.json.

Adding the alias to vite.config.ts ensures that the alias will work in TypeScript and Vue files.

Adding the alias to tsconfig.json will allow editors to resolve the alias.

ts
// vite.config.ts 
export default defineConfig({
    resolve: {
        alias: {
            // ...
            "@": path.resolve(__dirname, "./nebula/src/js"), 
            "@public": path.resolve(__dirname, "./nebula/src/public"),
            "@scss": path.resolve(__dirname, "./nebula/src/scss"),
            // ...
        },
    },
});
json
// tsconfig.json 
{
    "compilerOptions": {
        
        // ...
        "paths": {
            
            // ...
            "@/*": ["nebula/src/js/*"], 
            "@public/*": ["nebula/src/public/*"],
            "@scss/*": ["nebula/src/scss/*"]
            // ...
        }
        // ...
    }
}