Using ESM in Homey Apps
Since Homey v12.0.1 it's possible to create Homey apps using ECMAScript Modules (ESM). You can refer to the Node.js ESM documentation for more details. ESM brings certain advantages such as improved module isolation and native support for asynchronous loading, making it a more robust choice for modern JavaScript applications.
CommonJS vs. ESM
Before this release, Homey apps used CommonJS (CJS) for module management, requiring modules with require()
and exporting them using module.exports
. However, with ESM, modules are imported and exported using import
and export
statements.
CJS Example:
ESM Example:
Using .mjs
.mjs
Right now there is only one way to opt into using ESM in your Homey app:
Using the
.mjs
extension: Rename all your JavaScript files with the.mjs
extension. This tells Node.js that these files should be treated as ESM modules. You can also go file by file, converting part of your app to ESM without needing to rewrite everything at once. For files still using CommonJS, they can continue usingrequire()
andmodule.exports
while coexisting with the ESM-based parts.
Mixing ESM and CJS: Be cautious when mixing ESM and CommonJS. ESM supports asynchronous loading, while CJS is synchronous, so certain patterns may behave differently.
Example of loading a CommonJS module in ESM:
Migrating from CommonJS to ESM
If you're updating an existing Homey app that uses CommonJS, here are some steps to migrate it to ESM:
Replace
require()
withimport
:
Replace
module.exports
withexport
:
Check for compatibility: Make sure any third-party modules you are using also support ESM.
Upgrade your app's compatibility to v12.0.1 in app.json.
Common Gotchas and Compatibility
When switching to ESM, there are some important considerations:
No
require()
in ESM: If you need to load a CommonJS module from an ESM module, you'll have to useimport()
asrequire()
is not available in ESM.No
__dirname
or__filename
in ESM: In ESM,__dirname
and__filename
are not available. You can use the following workaround:
Mixing ESM and CJS: Be cautious when mixing ESM and CommonJS. ESM supports asynchronous loading, while CJS is synchronous, so certain patterns may behave differently.
Benefits of Using ESM
Here are some reasons why using ESM in your Homey apps can be advantageous:
Asynchronous Module Loading: ESM supports asynchronous loading, which can lead to performance improvements, especially in environments where modules are loaded on-demand.
Compatibility with Modern Syntax: ESM is the standard for JavaScript moving forward, and its syntax is more aligned with other JavaScript features such as
import
andexport
.Improved Developer Experience: ESM simplifies code structure with a cleaner and more intuitive module syntax. Features like named exports make it easier to track what's being imported/exported.
Better Support for Static Analysis: ESM allows tools and IDEs to analyze the structure of your code more effectively, leading to better autocomplete, refactoring, and error-checking features.
Native Support in Browsers: ESM is natively supported in modern browsers without the need for bundlers like Webpack. This can simplify app development for projects that need to run in both Node.js and browser environments.
Strict Mode by Default: All ESM modules run in strict mode by default, enforcing a stricter syntax and catching more common mistakes at runtime.
Top-Level
await
: ESM allows the use ofawait
at the top level, which simplifies asynchronous code in modules without needing to wrap everything in async functions.Future-Proof: ESM is the future of JavaScript module management, meaning you'll be aligned with future developments in the JavaScript ecosystem.
Last updated