<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mojca Rojko</title>
    <description>The latest articles on DEV Community by Mojca Rojko (@xtrinch).</description>
    <link>https://dev.to/xtrinch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F977567%2Ffb185ca9-c2d5-4110-9a25-82e392055fc6.png</url>
      <title>DEV Community: Mojca Rojko</title>
      <link>https://dev.to/xtrinch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xtrinch"/>
    <language>en</language>
    <item>
      <title>Regex 101: A primer</title>
      <dc:creator>Mojca Rojko</dc:creator>
      <pubDate>Tue, 29 Nov 2022 21:36:28 +0000</pubDate>
      <link>https://dev.to/xtrinch/regex-101-a-primer-18np</link>
      <guid>https://dev.to/xtrinch/regex-101-a-primer-18np</guid>
      <description>&lt;p&gt;Let's examine a regular expression, the kind you could get to fill out live at a technical interview for a variety of languages and frameworks. Why? Because it shows your logic perfectly and it shouldn't take you more than 10 minutes to complete, even if you're rusty on the regular expression logic. You're allowed to use &lt;a href="https://regex101.com"&gt;https://regex101.com&lt;/a&gt;, which has a wonderful help section which you can use. &lt;/p&gt;

&lt;h2&gt;
  
  
  The instructions
&lt;/h2&gt;

&lt;p&gt;Here's an unfinished regular expression:&lt;br&gt;
&lt;code&gt;(?&amp;lt;name&amp;gt;.*)$&lt;/code&gt;&lt;br&gt;
(see and open &lt;a href="https://regex101.com/r/hhwiRl/2"&gt;https://regex101.com/r/hhwiRl/2&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This is your test string:&lt;br&gt;
&lt;code&gt;2-13_oops-i-did-it-again_britney-spears.mp3&lt;br&gt;
3-13_toxic_britney-spears.vaw&lt;br&gt;
hold-it-against-me_britney-spears.flac&lt;br&gt;
unknown.mp3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There is already a baseline provided, I’d like you to finish this regex. Imagine the test input as a text file containing multiple lines of songs on different albums. For each line, we’d like to extract the &lt;strong&gt;edition&lt;/strong&gt; (so which song on the album it is), the song &lt;strong&gt;name&lt;/strong&gt;, the &lt;strong&gt;artist&lt;/strong&gt; name and the &lt;strong&gt;extension&lt;/strong&gt;. The name is the only thing required. Imagine this as extracted metadata in a player like Winamp. The different parts of the filename are separated by underscores and spaces are mimicked with dashes. It is OK if the parts contain the dashes, as you will not be able to replace them within this regex. All the help you need is in the bottom right corner of the webpage so I’d encourage you to use it as nobody knows all of the delimiters by heart.&lt;/p&gt;
&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;What you'd be expected to come up with, is this:&lt;br&gt;
&lt;code&gt;(?&amp;lt;edition&amp;gt;\d{1,8}-\d{1,8})?_?(?&amp;lt;name&amp;gt;[^_.]+)_?(?&amp;lt;artist&amp;gt;[^_.]+)?.(?&amp;lt;extension&amp;gt;[\S]{1,8})?$&lt;/code&gt;&lt;br&gt;
(see &lt;a href="https://regex101.com/r/3qW52u/1"&gt;https://regex101.com/r/3qW52u/1&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;First thing you'll notice is the usage of named groups. In javascript, we'd extract the named groups like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const {
      groups: { edition, name, artist, extension },
    } = /(?&amp;lt;edition&amp;gt;\d{1,8}-\d{1,8})?_?(?&amp;lt;name&amp;gt;[^_.]+)_?(?&amp;lt;artist&amp;gt;[^_.]+)?.(?&amp;lt;extension&amp;gt;[\S]{1,8})?$/.exec(
      filename
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the rest, you can see a very nice explanation that regex101 came up with for our regex:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k570Wl9K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ysba6elzrydyf0qb0s3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k570Wl9K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ysba6elzrydyf0qb0s3t.png" alt="explanation" width="713" height="1030"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here is a visualisation of one of our matches:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o38t-6dt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/epnhwlxbde9173r58qim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o38t-6dt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/epnhwlxbde9173r58qim.png" alt="visualisation" width="652" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Voila!&lt;/p&gt;

</description>
      <category>regex</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Micro frontends using webpack’s module federation with create-react-app</title>
      <dc:creator>Mojca Rojko</dc:creator>
      <pubDate>Mon, 28 Nov 2022 15:04:54 +0000</pubDate>
      <link>https://dev.to/xtrinch/micro-frontends-using-webpacks-module-federation-with-create-react-app-45oe</link>
      <guid>https://dev.to/xtrinch/micro-frontends-using-webpacks-module-federation-with-create-react-app-45oe</guid>
      <description>&lt;p&gt;Module federation enables us to &lt;strong&gt;use multiple separate builds to form a single application&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It was was introduced in Webpack 5 and it is truly a game changer in the world of frontend development. At the very least, it enables component sharing between different frontends for the same product - e.g. admin panel, user website. But further than that - it enables us to &lt;strong&gt;embed frontends into other frontends&lt;/strong&gt;, giving us the ability to have a separate library stack, different code style, structure, et cetera.&lt;/p&gt;

&lt;p&gt;The official docs say it best:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Use cases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separate builds per page&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each page of a Single Page Application is exposed from container build in a separate build. The application shell is also a separate build referencing all pages as remote modules. This way each page can be separately deployed. The application shell is deployed when routes are updated or new routes are added. The application shell defines commonly used libraries as shared modules to avoid duplication of them in the page builds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Components library as container&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many applications share a common components library which could be built as a container with each component exposed. Each application consumes components from the components library container. Changes to the components library can be separately deployed without the need to re-deploy all applications. The application automatically uses the up-to-date version of the components library.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Module federation gives us a truly painless experience with distributing your code over different packages and the amount of configuration is minimal. This makes your code more adaptable and more easily maintanable between different teams.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's build an example application
&lt;/h2&gt;

&lt;p&gt;We'll build an application, that consists of three distinct modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;library&lt;/strong&gt; - contains shared components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;app2&lt;/strong&gt; - a standalone app that makes use of components and is also exposed to be used elsewhere (we'll use it in app1)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;app1&lt;/strong&gt; - a container app that makes use of components and also includes app2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our goal is to use create-react-app, because chances are, you're already using it for all your react projects. We want module federation to complement our already great setup. And surely, we do not wish to eject the create-react-app configuration.&lt;/p&gt;

&lt;p&gt;Since we'll be adding some webpack plugins, we'll need craco too. Craco is the Create React App Configuration Override, an easy and comprehensible configuration layer. For details, see &lt;a href="https://github.com/dilanx/craco"&gt;https://github.com/dilanx/craco&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;two webpack plugins&lt;/strong&gt; that will make this possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;craco-mf (&lt;a href="https://github.com/bfaulk96/craco-mf"&gt;https://github.com/bfaulk96/craco-mf&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It enables us to use module federation in our CRA application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;@cloudbeds/webpack-module-federation-types-plugin (&lt;a href="https://github.com/cloudbeds/webpack-module-federation-types-plugin"&gt;https://github.com/cloudbeds/webpack-module-federation-types-plugin&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Provides us with typesafe development - meaning our apps are not full of ts-ignores and we have an automatic system for sharing typings between the apps. This is necessary for any real-world development scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;There's very little configuration involved. There is however two important files in each of the modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;modulefedration.config.js&lt;/li&gt;
&lt;li&gt;craco.config.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;craco.config.js&lt;/code&gt; will be standard for all packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { join } = require("path");
const cracoModuleFederationPlugin = require("craco-mf");
const { ModuleFederationTypesPlugin } = require( '@cloudbeds/webpack-module-federation-types-plugin' );

module.exports = {
  webpack: {
    plugins: {
      add: [
        new ModuleFederationTypesPlugin({
          downloadTypesWhenIdleIntervalInSeconds: 1,
        }),
      ]
    },
    configure: (webpackConfig) =&amp;gt; {
      webpackConfig.devServer = { static: {} };
      webpackConfig.devServer.static.directory = join(process.cwd(), "public");
      return webpackConfig;
    },
  },
  plugins: [
    {
      plugin: cracoModuleFederationPlugin,
    },
  ],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;modulefederation.config.js&lt;/code&gt; we will configure which packages are shared between the different apps, which components are exposed to other apps and which other apps we wish to reach in our app and where they reside.&lt;br&gt;
For the library app, we'll use this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  name: "library",
  exposes: {
    "./NameContextProvider": "./src/components/NameContextProvider.ts",
    "./Button": "./src/components/Button",
    "./Logo": "./src/components/Logo",
  },
  filename: "remoteEntry.js",
  shared: {
    react: {
      singleton: true,
      requiredVersion: deps["react"],
    },
    "react-dom": {
      singleton: true,
      requiredVersion: deps["react-dom"],
    },
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The config tells us that we'll share one context, a button component and a logo component to the other two apps. It also tells us that we'll share react and react-dom between the three modules.&lt;/p&gt;

&lt;p&gt;For app2, we'll use this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  name: "app2",
  exposes: {
    './App2Index': './src/Homepage',
  },
  filename: "remoteEntry.js",
  remotes: {
    library: `library@http://localhost:3003/remoteEntry.js`,
  },
  shared: {
    react: {
      singleton: true,
      requiredVersion: deps["react"],
    },
    "react-dom": {
      singleton: true,
      requiredVersion: deps["react-dom"],
    },
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This config tells us we'll expose the homepage of app2 to other apps (we'll use it in app1) and also that we'll be using the library remote in this application. This will enable us to use the button and the logo.&lt;/p&gt;

&lt;p&gt;For app1, we'll use the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  name: "app1",
  exposes: {
  },
  remotes: {
    app2: `app2@http://localhost:3002/remoteEntry.js`,
    library: `library@http://localhost:3003/remoteEntry.js`,
  },
  filename: "remoteEntry.js",
  shared: {
    ...deps,
    react: {
      singleton: true,
      requiredVersion: deps["react"],
    },
    "react-dom": {
      singleton: true,
      requiredVersion: deps["react-dom"],
    },
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This config enables us to use the library components and app2.&lt;/p&gt;

&lt;p&gt;Essentially, this is all the configuration we'll need. The only other special thing about this setup is using routing. If we're using app2 as a standalone app, we'll need our own routing wrapper (e.g. &lt;code&gt;BrowserRouter&lt;/code&gt; from &lt;code&gt;react-router-dom&lt;/code&gt;), but if we're embedding app2 into app1, we'll use the routing wrapper from app1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Library module
&lt;/h2&gt;

&lt;p&gt;We'll skip the part on how to create the button and the logo that are exposed from the library. It's all standard react.&lt;br&gt;
We'll expose a simple context too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";

export default React.createContext({
  name: "Mr.Noname" as string,
  setName: (name: string) =&amp;gt; {},
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll share one context, a button component and a logo component to the other two apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  App2 module
&lt;/h2&gt;

&lt;p&gt;The fun part begins in &lt;strong&gt;app2&lt;/strong&gt;! App2 can function as a standalone app or can be included in an another app. Let's see the index component:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import NameContextProvider from "library/NameContextProvider";
import { useState } from "react";
import { BrowserRouter } from "react-router-dom";
import Homepage from "./Homepage";

function App2() {
  const [name, setName] = useState("Mojca");

  return (
    &amp;lt;BrowserRouter&amp;gt;
      &amp;lt;NameContextProvider.Provider value={{ name, setName }}&amp;gt;
        &amp;lt;Homepage /&amp;gt;
      &amp;lt;/NameContextProvider.Provider&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  );
}

export default App2;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we're using out own routing wrapper here, and we're also using our own provider, which is why we do not expose this component to app1, but the homepage component below. App1 will have its own name provider, and when we're embedding app2 into app1, the context will be shared. Magic!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Homepage.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Button from "library/Button";

import NameContextProvider from "library/NameContextProvider";
import React from "react";
import { Route, Routes } from "react-router-dom";

function Homepage() {
  const ctx = React.useContext(NameContextProvider);

  return (
    &amp;lt;Routes&amp;gt;
      &amp;lt;Route
        path="/"
        element={
          &amp;lt;div&amp;gt;
            &amp;lt;div style={{ marginBottom: 20 }}&amp;gt;
              Hello again {ctx.name}. This is app2. The button &amp;amp;amp; context
              used is from components app.
            &amp;lt;/div&amp;gt;
            &amp;lt;div&amp;gt;
              &amp;lt;Button
                text="Change name from app2"
                onClick={() =&amp;gt; ctx.setName("Jozica")}
              /&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        }
        index
      /&amp;gt;
    &amp;lt;/Routes&amp;gt;
  );
}

export default Homepage;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  App1
&lt;/h2&gt;

&lt;p&gt;App1 is the container app that will make our entire project come to life. Let's see the index component:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "./App.css";

import App2 from "app2/App2Index";

import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import Homepage from "./Homepage";

const app2RoutingPrefix = "app2";

function App1() {
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;BrowserRouter&amp;gt;
        &amp;lt;Routes&amp;gt;
          &amp;lt;Route path="/" element={&amp;lt;Homepage /&amp;gt;}&amp;gt;
            &amp;lt;Route index element={&amp;lt;Navigate to={`/${app2RoutingPrefix}`} /&amp;gt;} /&amp;gt;
            &amp;lt;Route path={`/${app2RoutingPrefix}/*`} element={&amp;lt;App2 /&amp;gt;} /&amp;gt;
          &amp;lt;/Route&amp;gt;
        &amp;lt;/Routes&amp;gt;
      &amp;lt;/BrowserRouter&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It holds all the main routing and includes app2.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Homepage.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState } from "react";
import "./App.css";

import Logo from "library/Logo";
import NameContextProvider from "library/NameContextProvider";

import Button from "library/Button";
import { Outlet } from "react-router-dom";

function Homepage() {
  const [name, setName] = useState("Mojca");

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;NameContextProvider.Provider value={{ name, setName }}&amp;gt;
        &amp;lt;React.Suspense fallback="loading"&amp;gt;
          &amp;lt;div style={{ marginBottom: 20, marginTop: 20 }}&amp;gt;
            &amp;lt;Logo style={{ width: 90 }} /&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div style={{ marginBottom: 20 }}&amp;gt;
            Hello {name}. This is app1 - container app. The button &amp;amp;amp; context
            used is from the components app.
          &amp;lt;/div&amp;gt;
          &amp;lt;div style={{ marginBottom: 60 }}&amp;gt;
            &amp;lt;Button
              text="Change name from app1"
              onClick={() =&amp;gt; setName("Lojza")}
            /&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;Outlet /&amp;gt;
        &amp;lt;/React.Suspense&amp;gt;
      &amp;lt;/NameContextProvider.Provider&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Homepage;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the homepage component we provide the context, and use some shared libraries, and provide an outlet for the child routes - app2 is one of those child routes and it will be rendered in its place.&lt;/p&gt;

&lt;p&gt;That's all we need!&lt;/p&gt;

&lt;h2&gt;
  
  
  Running in development
&lt;/h2&gt;

&lt;p&gt;We have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can use &lt;strong&gt;lerna&lt;/strong&gt;, which will run &lt;code&gt;yarn run start&lt;/code&gt; in each of the packages for us&lt;/li&gt;
&lt;li&gt;Each of the apps can also be ran individually by running &lt;code&gt;yarn run start&lt;/code&gt; in their respective repos&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building for production
&lt;/h2&gt;

&lt;p&gt;If we were to deploy the applications to S3, we would deploy each module separately to its own respective S3 bucket.&lt;br&gt;
The only configuration needed is to use the correct remote URLs in &lt;code&gt;modulefederation.config.js&lt;/code&gt; files in each of the packages, which would need to point to S3 URLs instead of localhost URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full source code
&lt;/h2&gt;

&lt;p&gt;The full source code for this example can also be found on github under &lt;a href="https://github.com/xtrinch/create-react-app-module-federation-example"&gt;https://github.com/xtrinch/create-react-app-module-federation-example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>javascript</category>
      <category>react</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
