Module Linking
Module Linking is Esmx’s cross-application code sharing solution. It relies on native ESM so multiple apps can share modules without extra runtime libraries.
Key Advantages
- Zero runtime overhead
- Efficient sharing via Import Maps
- Version isolation across apps
- Simple configuration compatible with native ESM
Quick Start
Basic Example
export default {
modules: {
exports: [
'pkg:axios',
'root:src/utils/format.ts'
]
}
} satisfies EsmxOptions;
export default {
modules: {
links: { 'shared-modules': '../shared-modules/dist' },
imports: { 'axios': 'shared-modules/axios' }
}
} satisfies EsmxOptions;
Usage:
import axios from 'axios';
import { formatDate } from 'shared-modules/src/utils/format';
export async function fetchOrders() {
const response = await axios.get('/api/orders');
return response.data.map(order => ({
...order,
date: formatDate(order.createdAt)
}));
}
Core Configuration
Configuration lives under modules in entry.node.ts.
links
export default {
modules: {
links: {
'shared-modules': '../shared-modules/dist',
'api-utils': '/var/www/api-utils/dist'
}
}
} satisfies EsmxOptions;
imports
export default {
modules: {
links: {
'shared-modules': '../shared-modules/dist'
},
imports: {
'axios': 'shared-modules/axios',
'lodash': 'shared-modules/lodash',
'storage': {
client: 'shared-modules/storage/client',
server: 'shared-modules/storage/server'
}
}
}
} satisfies EsmxOptions;
scopes
Directory scope mapping
export default {
modules: {
scopes: {
'vue2/': {
'vue': 'shared-modules/vue2',
'vue-router': 'shared-modules/vue2-router'
}
}
}
} satisfies EsmxOptions;
Package scope mapping
export default {
modules: {
scopes: {
'vue': {
'@vue/shared': 'shared-modules/@vue/shared'
}
}
}
} satisfies EsmxOptions;
exports
export default {
modules: {
exports: [
'pkg:axios',
'pkg:lodash',
'root:src/utils/date-utils.ts',
'root:src/components/Chart.js',
{
'api': './src/api.ts',
'store': './src/store.ts'
}
]
}
} satisfies EsmxOptions;
Prefix behavior:
pkg:axios keeps original package imports
root:src/utils/date-utils.ts rewrites to module-relative path
root: supports .js, .mjs, .cjs, .jsx, .mjsx, .cjsx, .ts, .mts, .cts, .tsx, .mtsx, .ctsx. Extensions are removed; pkg: and bare strings keep extensions.
Advanced
Environment-differentiated builds
exports: [
{
'src/storage/db': {
client: './src/storage/indexedDB',
server: './src/storage/mongoAdapter'
}
},
{
'src/client-only': {
client: './src/client-feature',
server: false
}
}
]
exports: [
'pkg:axios',
'root:src/utils/format.ts',
{ 'api': './src/api/index.ts' },
{ 'components': './src/components/index.ts' },
{
'storage': {
client: './src/storage/browser.ts',
server: './src/storage/node.ts'
}
}
]
Complete Example
shared-modules
import type { EsmxOptions } from '@esmx/core';
export default {
modules: {
exports: [
'pkg:@esmx/router',
{
vue: 'pkg:vue/dist/vue.runtime.esm-browser.js',
'@esmx/router-vue': 'pkg:@esmx/router-vue',
vue2: 'pkg:vue2/dist/vue.runtime.esm.js',
'vue2/@esmx/router-vue': 'pkg:@esmx/router-vue'
}
],
scopes: {
'vue2/': {
vue: 'shared-modules/vue2'
}
}
}
} satisfies EsmxOptions;
vue3-app
import type { EsmxOptions } from '@esmx/core';
export default {
modules: {
links: {
'shared-modules': '../shared-modules/dist'
},
imports: {
'vue': 'shared-modules/vue',
'@esmx/router': 'shared-modules/@esmx/router',
'@esmx/router-vue': 'shared-modules/@esmx/router-vue'
},
exports: [
'root:src/routes.ts'
]
}
} satisfies EsmxOptions;
vue2-app
import type { EsmxOptions } from '@esmx/core';
export default {
modules: {
links: {
'shared-modules': '../shared-modules/dist'
},
imports: {
'vue': 'shared-modules/vue2',
'@esmx/router': 'shared-modules/vue2/@esmx/router',
'@esmx/router-vue': 'shared-modules/vue2/@esmx/router-vue'
},
exports: [
'root:src/routes.ts'
]
}
} satisfies EsmxOptions;
business-app
import type { EsmxOptions } from '@esmx/core';
export default {
modules: {
links: {
'shared-modules': '../shared-modules/dist',
'vue2-app': '../vue2-app/dist',
'vue3-app': '../vue3-app/dist'
},
imports: {
'@esmx/router': 'shared-modules/vue2/@esmx/router'
}
}
} satisfies EsmxOptions;
This composition demonstrates:
- Shared modules: provide multi-version framework support with version isolation via scope mappings
- Vue3 app: uses Vue 3 and exports only route configuration
- Vue2 app: dedicated Vue 2 app that exports only route configuration
- Aggregator app: unified entry orchestrating different versions and coordinating imports