February 12, 2023
Currently on my main job we started working on new big project with three separate teams. And even we decided from the beginning to split backend parts, it took some time to discuss how we are going to work together on frontend part. Someone suggested to use microfrontends and it was a brilliant idea, except just one detail.
No one from us knows, what it is mean.
I would tell upfront, that I still don’t know what is it, but I have seen (and tried) some frameworks, that could be used for that.
This is not a framework, but more like set of tools to setup web components repository.
A component is a reusable, independently source-controlled module, that is stored in scopes and maintained in workspaces
It really reminded me of using git. Developer set up bit workspace (init or clone git repository), created new component, snapped (git committed) changes and them exported or imported (push/pull) into external scope (git repository).
Component can be anything, from smallest tag to complete web application. Good thing is that components could use different web frameworks and the in master application they can be all used together. Actually, there is no master application in this case - any application can connect to scope and reuse its components. This is a very nice way for code reusal and horizontal splitting , but not the one that we needed.
This library provide some components, that can be shared among micro front-ends. Typically, those components are navigation bar, authorisation, user settings and some context switchers. All micro frontends are just separate applications and “main” application contain Luigi-core framework that just show iframes with each micro frontend. Very good for vertical splitting, when all micro frontends doesn’t share any internal components, but still should be accessible on one page. Everything is configurable from just one json file. Besides core, there is also client library, that each sub-application can include and use it to communicate with master app and other frontends.
At the end of our meeting nearly half of developers can pronounce name of this framework almost correctly. This is very similar to previous option, but even simpler: there is no setup for navigation bar or anything else. Just a master application, that contain links to other apps and display iframe into them. Other apps loaded as bundles and only on first open (unlike Luigi, where it needs to be properly configured). This is very simple and extremely easy to use (I’m saying that because I haven’t tried it yet by myself 😋). There are hooks to interact between applications and they can take arguments from parent app on mounting. Best of it - all sub applications can be used separately and then this “master” app with Qiankun added later in development process.
Not sure is any of this can be considered as proper micro-frontend. Of course, it would be nice and fancy to use something shiny like bit.dev, but I guess, benefits from this would only appear once developers amount would be much more than we have currently and once components can be really reused between apps. This way new micro-frontend would be build togegher like a lego from different bricks. But by now I see quantum or Luigi as simple, robust and reliable solution for teams that doesn’t want to share codebase.
June 29, 2022
As I mentioned previously, I was thinking about creating series of posts about different technologies, that I use currently at work. I even created small home project, that contains them all, but as it turned out, it was much more funnier to write code than to write blog post about code. And my explanation was not complete enough, even inaccurate, I guess, because it was already a month since I wrote that proof of concept.
So I decided just to share a link into it here, as an example of simple use of:
enter
for new, exit
for removal, how to update nodes and bind with react.Hope this examples would be usefull for someone. At least, it would be for me, when a couple years later I would try to recall, what have I done.
Link to repo: github
May 31, 2022
Recently I created a small application, that contain most of technology stack, that I’m using at work and/or learned recently: dotnet, react, mobx, d3js & signalR. So I decided to make small series of posts, in which I add some tips for each of these frameworks. I’ll update this list as soon as posts would be available.
Postgress is one of the famous db in the world of software development. Although my knowledge does not allow me do dig deep in differences between databases, I prefer to use postgress for my dotnet projects, because it require less resources than MsSQL and allow db migrations unlike SQLite. Simpliest way to install it would be, of course, official installer on local machine, but I prefer to use docker. This way it’s easier to support multiple versions, add plugins and throw away data, that is not needed. To run postgreSQL from docker:
docker run
-e POSTGRES_USER=user
-e POSTGRES_PASSWORD=pass
-e POSTGRES_DB=d3signal_db
-p 5432:5432
-v db:/var/lib/postgresql/data
-d
postgres:14
-e
flags used to set environment, especially user name, pass and db name, that would be used. -p
is mapping container port to local port. In this case it’s the same, but if I run local Postgres in addition to one in docker, ports can be remapped to avoid confusion. The most interesting param here is -v
, which creates docker volume db
(if it’s not existed) and mounts it into container. When container would be stopped, this volume persisted and data can be saved this way between reboots.
There are many ways to connect dotnet to sql (as well as there are many types of dotnet application). I usually use EntityFramework and include same steps:
Circle
. But still, I added interfacepublic interface ICirclesContext { DbSet<Circle> Circles { get; } Task Save(); }
Name here is better to be pointed to application name, like MyAppContext
. In this case the whole application is about circles 🙂
Implementation:
public class CirclesContext: DbContext, ICirclesContext { public CirclesContext(DbContextOptions options) : base(options) { } public DbSet<Circle> Circles => Set<Circle>(); public async Task Save() => await SaveChangesAsync(); }
WebApplication
) retrieve connection string and register dependency:var connectionString = builder.Configuration.GetConnectionString("db"); builder.Services.AddDbContext<CirclesContext>(ops => ops.UseNpgsql(connectionString)); builder.Services.AddScoped<ICirclesContext>(p => p.GetService<CirclesContext>()!);
Of course, config file should contain connection string (although, in production it usually goes from environment variable where it appear by CI/CD pipeline):
{ "ConnectionStrings": { "db": "Host=localhost;Username=user;Password=pass;Database=d3signal_db" } }
app.Services .CreateScope() .ServiceProvider .GetService<CirclesContext>()? .Database .Migrate();
More about migrations and how to create them can be found in microsoft documentation
Without any other details about .net application type, these are simplest steps to add postgreSQL support to our application.
February 15, 2022
I need to add new feature to my site - posts-links with simple commentary. I was going to write how to use ffmpeg to create amazing gifs, but guys from GIPHY already described everything that I know (and more!) here: How to make GIFs with FFMPEG
With combination of youtube-dl
& ffmpeg
the only limits are imagination and free time. I, as example, finaly created by myself this gif with medic from TF2, that I could not find anywhere.
February 14, 2022
I’m writing on C# for 5 years now and keep finding things, that are not widely used, but they are exist already for a long time. Just recently I found the need of dynamic
keyword.
Usually new variables are defined with var
or with value type directly:
Foo foo = new Foo(); var foo = new Foo();
These are actually two identical lines, compiler would define actual type on second lane from right-hand operator.
But what if type is unknown in compile type? I have met a problem, where actual type is created by external parameter - and there is no common interface that can be used to aggregate possible types. In these uncommon scenarios dynamic
can be very handy.
Suppose, we have a three types:
public record TypeA(string A); public record TypeB(string B); public record TypeC(string C);
Then we can declare a function, which return any of this types by random:
dynamic GetRandomType(Random random) => random.Next(3) switch { 0 => new TypeA("a"), 1 => new TypeB("b"), 2 => new TypeC("c"), _ => throw new Exception("out of random range") };
By making dynamic
return type, we tell a compiler, that he should not care, which type it actually is. Problem here in that compiler agreed and skip any further compile-time checking:
var random = new Random(); var result = GetRandomType(random); result.DoSomething(); // We would get runtime error here
A good thing is, that actual type is available in run time and overloading works even with dynamic type:
public class Foo { public static void Do(TypeA obj) => Console.WriteLine($"Do a: {obj.A}"); public static void Do(TypeB obj) => Console.WriteLine($"Do b: {obj.B}"); public static void Do(TypeC obj) => Console.WriteLine($"Do c: {obj.C}"); }
Foo.Do(result); // correct function would be called, based on result type
This can be very handful for places, where actual behaviour is unknown beforehand. As example, I wrote a event parser, where each event contain a enum with event type and object
payload. And for each actual event the payload would be a completely different DTO, as well as event handlers would have completely different behaviour.
100% JS-free