Skip to main content

Images and Fonts

Images

Raster

To use local images in your project, you should install sharp library separately. It helps us to generate miniatures for images and also process images for pwa icons for PWA module.
We don't install this library by default because of its size and because many developers don't need it.

$ yarn add sharp --save-dev

Supported formats: .png, .jpg, .jpeg, .gif, .webp

Import of raster image emits a separate file, while default export returns URL string and named export returns image object with the following interface:

interface ImageObject {
src: string;
width: number;
height: number;
blurDataURL: string;
}

Example with named export and automatic aspect-ratio calculation based on real image width and height:

import { image } from './images/mountains.jpeg';

const Image = () => {
const { src, width, height } = image;

// <img src="${ASSETS_PREFIX}/dist/client/9930f34d1d49796027f2a18ea89e6ccf.jpeg" width="1104" height="460" />
return <img src={src} width={width} height={height} />;
};

Example with default export:

danger

Usage without width and height attributes not recommended, it will degrade the Cumulative Layout Shift metric

import src from './images/mountains.jpeg';

const Image = () => {
// <img src="${ASSETS_PREFIX}/dist/client/9930f34d1d49796027f2a18ea89e6ccf.jpeg" />
return <img src={src} />;
};

Vector

Import of .svg images emits a separate file and have different behavior on server and client side, because of some legacy coupling with our internal UI-kit library. By default, on server side, it will return image source code as a string, and on client side, it will return an URL string.

This default behavior not very useful, so we recommend to use imports with svgr resource query.

React component

Imports with .svg?react resource query will return React component, created by svgr library:

import Image from './images/logo.svg?react';

const Logo = () => {
// <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80.9 72.2" width="100" height="100">...</svg>
return <Image width="100" height="100" />;
};

All properties to this Image component will be passed to root svg tag.

Optimization

By default, raster images doesn't have any optimization, and you have a few options for it:

For automatic imagemin processing use option imageOptimization:

tramvai.json
{
"projects": {
"appName": {
"imageOptimization": {
// enable image optimization
"enabled": true,
// options for the detailed settings (https://github.com/tcoopman/image-webpack-loader#options)
"options": {}
}
}
}
}

For vector images, on contrast, svgo always enabled.

Typings

To prevent typescript issues with image imports, make sure that your custom types declaration contains @tramvai/cli package reference:

typings.d.ts
/// <reference types="@tramvai/cli" />

Fonts

Simpliest way to add Web Fonts in your project is to use RENDER_SLOTS token, example with Lato Google Font:

import { RENDER_SLOTS, ResourceType, ResourceSlot } from '@tramvai/tokens-render';

provide({
provide: RENDER_SLOTS,
multi: true,
useValue: {
type: ResourceType.style,
slot: ResourceSlot.HEAD_CORE_STYLES,
payload: 'https://fonts.googleapis.com/css2?family=Lato&display=swap',
},
});

Also, for faster text rendering, you can preload used fonts:

import { RENDER_SLOTS, ResourceType, ResourceSlot } from '@tramvai/tokens-render';

provde({
provide: RENDER_SLOTS,
multi: true,
useValue: {
type: ResourceType.preloadLink,
slot: ResourceSlot.HEAD_CORE_SCRIPTS,
payload: 'https://fonts.gstatic.com/s/lato/v20/S6uyw4BMUTPHjx4wXiWtFCc.woff2',
attrs: {
as: 'font',
type: 'font/woff2',
crossOrigin: 'anonymous',
},
},
});

Custom Web Fonts

Supported formats: .woff2

Recommended way to add custom fonts - import nessesary font in @font-face directive:

app.module.css
:global {
@font-face {
font-family: 'CascadiaCode';
src: url('./fonts/CascadiaCodePL.woff2') format('woff2');
}

html {
font-family: CascadiaCode;
}
}

Then just import this CSS file in application entry:

index.ts
import './app.module.css';

Result CSS will looks like this:

@font-face {
font-family: 'CascadiaCode';
src: url(${ASSETS_PREFIX}/dist/client/20d46cabfe465e8d.woff2) format('woff2');
}
html {
font-family: CascadiaCode;
}

And preload your font as in previous example:

import { RENDER_SLOTS, ResourceType, ResourceSlot } from '@tramvai/tokens-render';
import font from './fonts/CascadiaCodePL.woff2';

provide({
provide: RENDER_SLOTS,
multi: true,
useValue: {
type: ResourceType.preloadLink,
slot: ResourceSlot.HEAD_CORE_SCRIPTS,
payload: font,
attrs: {
as: 'font',
type: 'font/woff2',
crossOrigin: 'anonymous',
},
},
});

Typings

To prevent typescript issues with import *.woff2 file, make sure that your custom types declaration contains @tramvai/cli package reference:

typings.d.ts
/// <reference types="@tramvai/cli" />