Developer update by Optimizely Norway
Next year we will celebrate Optimizely having been in Norway for 20 years. During this time we have spent a lot of time advocating to developers about new releases, updates and tips, trix and modules created by the community.
Gathering developers on site, serving beer and snacks, discussing code and showcasing solutions is one of the highlights of my work at Optimizely in Norway. Last week (October 28th) I finally got to do it again after almost 2 years of digital meetings. This blog is an abstract of what we showcased and I am looking forward to more physical events going forward.
GraphQL
We don’t do everything ourselves at these events and when it comes to the upcoming service of GraphQL we just had to invite Jonas Bergqvist from Optimizely Sweden to do his magic. We got a sneak-peak of what might come out of a project that synchronizes your content models and the content itself to a flexible, fast and powerful cloud service.
Exposing all your content through GraphQL allows you to query in both easy and really advanced ways. We got to see several examples of this where some relatively simple-to-write queries retrieved content from an Alloy and a Foundation site.
This can be used in various ways for various use cases, ranging from integrations to headless scenarios. It's going to be interesting to see what becomes of this project that is currently in internal alpha for internal users and of course OMVPs.
DOTNET RUN
The country manager at Optimizely Norway couldn’t let the chance to brush the dust off his coding skills. Steve Celius (who actually is named as a contributor in the book about EPiServer 4 (yes the spelling is correct), which saw the previous big leap to .NET 4)) gave a walkthrough of performance gains, installing and setting up Optimizely on .NET 5! He also showcased that as a frontend developer you now can benefit from using Visual Studio Code and have everything compiled on save. This is a huge benefit that will have backend and frontend developers working even more closely.
Here on World there is an excellent landing page with all the information you need to start off your .NET 5 project on Optimizely, https://world.optimizely.com/net5. One of the tips Steve gave in his presentation was that it is sometimes a good idea to read the documentation… He spent a good few hours writing code to create a user in the database and then realised that running dotnet-episerver add-admin-user <option> on the command line will do the trick in a few seconds :-D
Update: Since our event this excellent blogspot has all you need to know about setting up an Optimizely website on .NET 5, https://beendaved.blogspot.com/2021/10/starting-new-project-with-optimizely.html.
Tips, tricks and modules
The Optimizely community serves a smørgåsbord of innovative, cool and sometimes very nerdy blogs and articles. We have a habit of doing a recap of the things we pick up (in addition to some of our own findings) and below is a list of the things we showcased this time.
Adjust styling for better editor experience
As a developer you should strive to give the editors and marketers the best possible experience to help them create and manage content.
With only 2 lines of css code you can transform a local block from this where the fields are separated with headers and lines to a better editor experience where we decrease the header font size and remove the artificial lines that is used to separate two inline page-blocks (it is a logically split, but not always meaningful to the editor):
.Sleek .epi-form-container__section__row > fieldset > legend { font-size: 18px;}
.Sleek .epi-form-container__section__row fieldset { border-bottom: 0;}
It might not be revolutionary but if editors work in this view daily they will benefit from the smaller heading font size and the removed lines.
EditorDescriptors / UI Hint
Down the same path of making an editor's life easier is this old but still golden blogpost from Tomas Gulla, https://www.gulla.net/no/blog/make-episerver-string-textbox-property-wider/.
The following code
public virtual string Copyright { get; set; }
[UIHint(UIHint.Textarea)]
public virtual string Description { get; set; }
will produce this
where adding this code
[EditorDescriptorRegistration(TargetType = typeof(string), UIHint = "string580")]
public class StringEditorDescriptor : EditorDescriptor
{
public override void ModifyMetadata(
ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
{
// Only target string, not IList<string>
if (metadata.ContainerType == typeof(string))
{
metadata.EditorConfiguration.Add("style", "width: 580px");
}
base.ModifyMetadata(metadata, attributes);
}
}
[UIHint("string580")]
public virtual string Copyright { get; set; }
[UIHint(UIHint.Textarea)]
public virtual string Description { get; set; }
will produce this
Again, nothing too big or fancy, but letting the editor see the whole text instead of having to scroll through the text in a much too small area will make their life easier.
Grid View
https://world.optimizely.com/add-ons/optimizely-labs/ host a bunch of modules and add-ons developed by Optimizely as experimental product trials.
One of these is Grid View that in essence flattens out the tree structure and visualizes content items in an Excel like manner like this:
Viewing content as lists is not only available to pages but also blocks and assets could be displayed like this. It also has a really nice search which enables you to filter and find pages, blocks and assets quickly even in deep content heavy sites. The module is well documented with screenshots and GIF animations <3 and is well worth a look, https://github.com/episerver/episerver-labs-content-manager-docs/blob/master/GridView.md.
In addition to the current documentation, Allan Thraen wrote a blogpost on how to set a default root for Grid View and change which properties are displayed in the grid, https://www.codeart.dk/blog/2021/9/optimizely-gridview-customizations/.
Refresh current editing context on property value change
In CMS UI 11.36.0 it is now possible to annotate any model property with a new attribute from EPiServer.Cms.Shell.UI.ObjectEditing namespace called ReloadOnChangeAttribute. Bartosz Sekula blogged about this with a really cool example https://world.optimizely.com/blogs/bartosz-sekula/dates/2021/7/refresh-current-editing-context-on-property-value-change/.
Optimize Optimizely website for Mobile
With Black Friday coming up and more focus on Core Web Vitals from Google, this blogpost with tips about what to look at when it comes to page speed is a good one: https://www.naveedulhaq.com/index.php/episerver/optimize-optimizely-website-for-mobile/.
Enable SQL commands in clear text
Logging and tracing is fascinating and with Application Insights there are a lot of possibilities.
Adding this bit of code you can have the SQL commands visible in clear text (this code is for CMS 12 on .NET 5):
services.ConfigureTelemetryModule<DependencyTrackingTelemetryModule>((module, o) =>
{
module.EnableSqlCommandTextInstrumentation = true;
});
Add the code to your ConfigureServices(...) call in startup.cs in your .NET 5 project.
Application Insights Profiler for .NET 5 in DXP
In .NET 5 projects you can configure even more of Application Insights directly from your code in an easy manner. For applications in DXP you have access to Application Insights, and the profiler can be run in production.
It'll sample performance profiles as your site is running, and you can inspect them directly in the browser through Application Insights.
For .NET 4.x applications in DXP you can ask Optimizely support to enable the scheduler for you, but with .NET 5 you can just add the following line to your ConfigureServices(...) method.
services.AddServiceProfiler();
The Application Insights configuration will be applied automatically in DXP, and you can enjoy the deep insight you get on slow requests.
Logging to Application Insights
Wouldn't it be nice to see which jobs run directly from the Application Insights logs, or see how many jobs have failed, or the result of the job? With custom events in Application Insights and a logger in the code, this is easy and gives a ton of insights.
Example: Here we have a singleton class that is registered in the service registry (dependency injection):
services.AddSingleton <SchedulerTelemetryLogger> ();
It is instantiated and receives IScheduledJobEvents and TelemetryClient through ctor injection
We listen to the event and log in every time a scheduled job is completed
public class SchedulerTelemetryLogger
{
private readonly IScheduledJobEvents _scheduledJobEvents;
private readonly TelemetryClient _telemetryClient;
public SchedulerTelemetryLogger(IScheduledJobEvents scheduledJobEvents, TelemetryClient telemetryClient)
{
_scheduledJobEvents = scheduledJobEvents;
_telemetryClient = telemetryClient;
//Attach to scheduled job executed event
_scheduledJobEvents.Executed += ExecutedScheduledJob;
}
private void ExecutedScheduledJob(object sender, ScheduledJobEventArgs e)
{
_telemetryClient.TrackEvent("Job executed: " + e.Job.Name, new Dictionary<string, string> {
{ "Name", e.Job.Name},
{ "Status", e.Job.LastExecutionStatus.ToString()},
{ "LastExecutionMessage", e.Job.LastExecutionMessage}
});
}
}
Keep up the good work Optimizely community!
Comments