Back to the Front-end: Exploring the Future of the Umbraco UI (Part 6 - ES Modules)
Tags: umbraco, frontend, esmodules, javascript
Published: 2022-10-21 07:26:51

So in [the last blog post we introduced Vite](https://dev.to/mattbrailsford/back-to-the-front-end-exploring-the-future-of-the-umbraco-ui-part-5-vite-5g91) and briefly mentioned that it is based around ES Modules, however as this isn't a concept most will be using in the current Angular Umbraco UI, I thought this probably deserved a post of it's own.

## About ES Modules
Essentially, ES Modules are the ECMAScript standard for working with modular code. It is often simplified to the `import/export` syntax, and similar to Web Components, offers us another form of "encapsulation".

Prior to ES Modules, scripts loaded into a page / application would be globally accessible, meaning all variables, functions and classes defined in them could be accessed by any other script running on the page, and vica versa.

ES Modules however are executed in their own scope, and only varibles, functions and classes explicitly `exported` would be externally visible. Conversly, these are only consumed when they are explicitly `imported` in the consuming code base.

## Defining a Module
ES Modules are regular old JavaScript files, but have one or more root level `import` and/or `export` statements.

Any JavaScript that contains at least one root level `export` will automatically be assumed to be a module by the runtime. If there are no root level `export` statements, then the runtime will treat the file as a regulard script file.

## Exporting
Any root level variable, class or function prefixed with the `export` keyword will become visible to consumers. All root level variables, classes or functions without the `export` keyword will only be accessible within the module itself.

```javascript
// @filename: math.js

// Example private variable
const startIndex = 0;

// Example private fuction
function add(num1, num2) {
  return num1 + num2;
}

// Example variable export
export const pi = 3.142;

// Example class export
export class RandomNumberGenerator {}
 
// Example function export
export function absolute(num) {
  if (num < 0) return num * -1;
  return num;
}
```

As per the example above, ES Modules can contain multiple exports. ES Modules can also declare a default export with the `export default` prefix

```javascript
// @filename: hello.js

// Example default export
export default function helloWorld() {
  console.log("Hello, world!");
}
```

## Importing
To consume a variable, class or function exported by another module, we can import them at the top of our script.

```javascript
// Import exports from the math module
import { pi, absolute } from "./maths.js";

// Use the imported variables / functions
console.log(pi);
console.log(absolute(pi));
```

If we just want to import the default export of a module, the curly braces are no longer required:

```javascript
// Import the default export of the hello module
import helloWorld from "./hello.js";

// Execute the function
helloWorld();
```

If you need to import both a default export, and one or more non default exports, these can be combined in the import statement

```javascript
// @filename: maths.ts
export const pi = 3.14;
export default class RandomNumberGenerator {}
 
// @filename: app.ts
import RandomNumberGenerator, { pi } from "./maths.js";
```

### Import Aliasing
If an import would conflict with a locally declared resource, or you'd prefer to access it via an alternative name, you can alias a an import with the following syntax

```javascript
// Import the pi variable from the math module, but use the local alias `π`
import { pi as π } from "./maths.js";

// Use our imported variable by it's alias
console.log(π);
```

### Import All Exports
You can also import all exports of a module into a single namespace with the following syntax.

```javascript
// Import all exports from the math module, giving the a `math` namespace
import * as math from "./maths.js";

// Use an imported resource prefixed with the namespace
console.log(math.pi);
```

## Conclusion
There is more that you can do with ES Modules, but I think this covers the core use cases that most will need day to day. 

Coming from a C# background the `import` syntax is not that disimilar to the `using` syntax so it's not an entirely new concept.

Nevertheless, this is likely to be relatively new to those who are only familiar with extending the back office in Angular so it's yet another concept you will need to get to grips with.

## Additional Resources
- [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)