DEV Community

Cover image for What's new in Piral #2
Florian Rappl
Florian Rappl

Posted on

What's new in Piral #2

Piral is an open-source framework for microfrontends based on React. It brings everything to create amazing frontends using a scalable development approach.

This is the second blog post about our progress on Piral. We will continue to describe our progress and future plans here on dev.to.

The agenda should be almost identical in each post. We'll use

  • Current progress to explain what has been done since the last post
  • Future plans to explain what we are currently working on or have in our direct pipe
  • Other thoughts to list some of the thoughts for future development

Please reach out to us in case of any feedback, ideas, or criticism. We'd love to improve!

Current Progress

This week we shipped Piral 0.9.3. The changelog is - as expected for a patch - quite short. So all in all we are still confident on the general direction:

Making Piral the ultimate choice for creating microfrontend solutions

As anticipated v0.9 is a step in the right direction, however, it also came with challenges that partially still require some thought.

Right now the major challenges are:

  1. Generation of useful TypeScript declarations.
  2. Ensure a compatible development package not only in the app shell, but also across pilets.
  3. Dependency management.

As far as the generation of useful TypeScript declarations is concerned: We will develop a new engine for this purpose alone. We already started crafting ideas and we are eager to see this fly. It will, however, take some more effort to get it fully working and we require additional testing time.

Challenge Accepted

The compatible development package effort is split in multiple parts. We already have a local-first detection (and usage) inside the Piral CLI. What we added with 0.9.3 is another sanity check to ensure the right app shell development package is used.

Now in 0.10 we try also to ensure compatibility across the board. So if the app shell was packaged using the Piral CLI 0.10 authors of pilets will see a warning if they use, e.g., the Piral CLI 0.9.

But that does not go far enough. We will also try our best to dynamically make the Piral CLI compatible with a given app shell. As such, a provided version should automatically be able to adjust itself. Scaffolding a new pilet with the global version should just work - independent of what version was used by its app shell.

Compatible

Last, but not least dependency management. Yes, this one is a struggle for long. Not that its new, but obviously some parts are more difficult.

So what's our angle on this one? We think there are three major ways of "sharing" dependencies.

  1. Just bundle the dependency in (i.e., only share the code, but not the lib)
  2. Use the same URL (i.e., prevent multiple downloads, but execute multiple times)
  3. Share via the app shell (i.e., just use what's given)

While (1) and (3) just work out-of-the-box, we have no (special) support for (2). But let's take this to future plans.

Future Plans

Well, support for (2) is already there in some form. In Parcel you can just do

await import("https://unpkg.com/.../some.umd.js");

and it will work as you'd expect (i.e., it will first load the package from the given URL and then resolve the promise).

But there is a but. This way sucks. And that has multiple reasons: For once, this will (as already mentioned) run the script twice if loaded from multiple pilets (and even if used twice within the same bundle). The side-effects may be unwanted or even destroy using the lib at all.

As a result only helper / utility libraries (e.g., lodash) or component libraries will work fine. All others are at risk. And even the mentioned ones may not work as anticipated.

Another reason why this sucks: Let's say pilet A wants to use version 1.2.3 of a lib and pilet B wants to use version 1.2.4. Why should both be loaded? Maybe 1.2.4 is good enough. It's a patch after all. But, alright - we don't know. So maybe let's rephrase: If pilet A wants to use ~1.2.3 and pilet B has 1.2.4 then obviously 1.2.4 is acceptable.

So here's the deal, we will bring this to the tooling level with some runtime support.

We will support either standard imports such as

import * from 'lodash';

or asynchronous calls such as

await import('lodash');

as if these dependencies are part of the bundle. Except they are not. They are also not delivered by the app shell.

Dependency Management in Piral

So how can we solve this? We will solve this via the Piral CLI in conjunction with Piral / the app shell.

It could look a bit as follows:

function resolveUrlDependency(packageName: string, versionDescriptor: string) {
  // detect against a set of already loaded or loading dependencies
  // potentially aborting / replacing an existing loading proposal
  // if already available return the existing promise
  const promise = import(`https://unpkg.com/${packageName}/${versionDescriptor}`);
  // store the promise to re-use it
  return promise;
}

Obviously, this one needs to be wired with a pilet (or a side-bundle) loading. Also since the dependency resolution above is always async it needs to be resolved before the pilet (or one of its side-bundles) is actually run.

All in all this leads to a bundle loading modification. The URL dependencies (specified in the package.json) need to be loaded before the pilet is evaluated. One way around this requirement is that URL dependencies have to be loaded asynchronously. This sounds acceptable at first, but since Piral is all about developer-first we always strive to make the dev xp as convenient as possible.

Maybe there is a way to support both options.

Other Thoughts

With 0.10 around the corner a lot more integrations are prepared. The list now includes:

  • React (base framework)
  • Vue
  • Angular
  • Angular.js
  • Hyperapp
  • Inferno
  • Preact
  • Aurelia (coming in 0.10)
  • Ember.js (coming in 0.10)
  • Mithril.js (coming in 0.10)
  • LitElement (coming in 0.10)
  • Elm (coming in 0.10)
  • Svelte (coming in 0.10)

The last two are actually already supported - as they are more compile-time than runtime frameworks. As such they could be just added - Parcel supports compiling them (either directly of via some Parcel plugin). All we will provide here is a webcomponent for providing extension support within these frameworks.

Bringing everything together

For v1 we will most likely also add some more:

  • Riot
  • Cycle
  • Nerv

The plugins are also listed directly in the documentation.

We still think Piral should be used exclusively with React if possible. Use integrations with care - only when you actually need to support another framework.

The new logo is also on the way! For 0.10 we will switch to our new official logo...

New Piral Logo

Time to let this one fly!

... one last thing. We may change our state container. Actually using React Atom was a nice experience so far, but we fear that there are actually "better" (i.e., smaller, potentially better performing) solutions out there. We'll evaluate a large portion of these soon (among the candidates are Zustand, React Tracked, Constate and storeon).

A dedicated blog post on these state containers will follow!

Conclusion

Piral reaching v0.9 was already a major milestone towards the v1. Right now we are positive that 0.10 can still be reached this year, but independent if we still release 0.10 in December or early next year we think Piral has made great progress this year. The v1 is also in sight, even though we will not ship it this year.

We started with the vision of generalizing our architecture / setup for microfrontends in a flexible yet powerful framework. Over time some of the ideas became reality, while others had to shift or be discarded. We are happy with the outcome as it is a powerful yet simple way to create microfrontends without much trouble.

Discussion (2)

Collapse
carvinlo profile image
carvin

Hi, great piral
How about reactn, a global state management. npmjs.com/package/reactn
I use it in my project

Collapse
florianrappl profile image
Florian Rappl Author

Looks great, will check it out in more detail!

Two things I noticed right away:

I will include this in our experiments!