File Refs

From SocialStack
Revision as of 17:12, 17 January 2023 by Luke (talk | contribs)

Often on a website, images and videos are in a variety of formats or sizes. To represent one file with potentially multiple variants, SocialStack has a small textual file locator called a "ref". The name ref is short for file reference. A standard url is also a kind of file reference, and as a result, a regular http or https url is also a valid ref.

Defining a ref field

In your C# entity file, any string field ending with the exact 3 letters Ref will be displayed as a file selector in the admin panel.

public partial class Page : VersionedContent<uint>
{

    /// <summary>
    /// The main feature image to use for this piece of content.
    /// </summary>
    public string FeatureRef;

}

File selector in general forms

SocialStack has pluggable input fields (which are really only very light wrappers over the native html5 input fields). The file selector module injects itself into 4 different field types:

  • type="upload" - any file at all but as an upload button only. Selecting from previous uploads are not displayed as an option. This is what you'll usually use on the frontend of your site.
  • type="image" - specifically for images.
  • type="icon" - specifically for icons only.
  • type="file" - any file at all and will also display a selector for previously uploaded files or icons.
import Input from 'UI/Input';
import Form from 'UI/Form';

<Form action='page'>
    <Input type="upload" name="featureRef" label={`Upload a feature image`} />
</Form>

Using a ref on the frontend

So far we've seen how to store and generate refs, but not how to use them. Most of the time you would pass a ref through the getRef function, as that can take care of optionally specifying a format or pixel size that you would like to obtain.

Note that the resolving a url through getRef does not require trips to the server. A ref is designed to carry everything needed to be able to expand into a full url on the frontend with no further assistance.

import worldBackgroundRef from './world-background.jpg';
import getRef from 'UI/Functions/GetRef';

...

// The original image as a simple <img> react element:
return getRef(worldBackgroundRef);

And with a specific size. Available image sizes are configured in the Uploader configuration (in the admin panel):

import worldBackgroundRef from './world-background.jpg';
import getRef from 'UI/Functions/GetRef';

...

// A react element but specifically using the 512 size image.
return getRef(page.featureRef, {size: 512});

getRef also returns either a best guess react element or alternatively just a resolved url if you would like one:

import worldBackgroundRef from './world-background.jpg';
import getRef from 'UI/Functions/GetRef';

...

// Get the URL of a static file ref:
var imageUrl = getRef(worldBackgroundRef, {url: true});

Using a ref in the API

Coming very soon!

Static javascript files

getRef works for any file type - it can be an image, video, pdf, json file, js file and so on. However, files that the compiler cares about such as a .js or .css file won't be uploaded to the target server. To make the compiler ignore these files, put them into a folder called /static/ and then when you import it, you'll get a static file ref instead.

import jQueryLibraryRef from './static/jquery.js';
import getRef from 'UI/Functions/GetRef';

...

// Get the URL of a static js file:
var jsFileUrl = getRef(jQueryLibraryRef , {url: true});

This is particularly useful for lazy loading larger libraries, especially if they are used rarely. There is also built in functionality to help with lazy loading too.

What actually is a ref

A ref is a usually very short piece of text which is designed to not carry the hostname of the site (unlike a URL) as that makes them more portable between environments such as from staging to production. Here's an example:

s:ui/header/logo.png

This is a static file ref pointing at a file in the source code tree, specifically at UI/Source/Header/logo.png. You get one of these if you import a static file inside your source code. Most often though you'll be working with public refs, which are uploaded files and look more like this:

public:6DBAE2A6F533051CE199D7FAD982E2D1/16.png

This is a public ref pointing at a file. Because it is an uploaded image, it is available in multiple sizes by default. The URL of the original as-is upload is resolved by getRef to /content/6DBAE2A6F533051CE199D7FAD982E2D1/16-original.png. The long directory name is a simple hash of a server hostname and exists to help minimise collisions in large clusters or in development environments. I.e. 2 developers can upload a png which will take upload ID #16, but they won't get either ref or merge collisions as the directory is different.

For easier compatibility with Linux, a ref is typically lowercased and so also is the deployed file set. If manually manipulating a ref, you should retain the case though, or more ideally, use the getRef.parse function. This is because when a debug development instance is running, static file refs retain their case in order to be able to directly resolve to the filesystem source directory, avoiding a need to copy files around.


Parsing a ref manually

It's highly recommended to use the getRef.parse method as it will factor in any specialty refs or other unforseen cases that you might not be aware of. As with getRef itself, it does not require a trip to the server. The parse method is used by getRef internally too.

import getRef from 'UI/Functions/GetRef';

var refParts = getRef.parse("public:6DBAE2A6F533051CE199D7FAD982E2D1/16.png");

console.log("This ref is part of the '" + refParts.scheme + "' scheme and is for a file with type " + refParts.fileType);
// This ref is part of the 'public' scheme and is for a file with type png

// Note: "Scheme" is the name given to the first part of a standard URI before the colon.
// A "handler" is what the ref system calls the piece of code which will handle a ref for a particular scheme.