Использование ES6 модулей является фундаментом для построения современных приложений на Lit. Модули позволяют разделять код на независимые, легко поддерживаемые части, обеспечивая повторное использование компонентов и снижение сложности проекта.
ES6 модули вводят синтаксис import и
export, позволяющий явно управлять зависимостями между
файлами. Каждый модуль имеет собственную область видимости, что
предотвращает конфликт глобальных переменных.
// my-component.js
export class MyComponent extends HTMLElement {
connectedCallback() {
this.innerHTML = `<p>Hello from MyComponent</p>`;
}
}
// main.js
import { MyComponent } from './my-component.js';
customElements.define('my-component', MyComponent);
В Lit компоненты чаще всего экспортируются как классы, наследующие
LitElement. Это упрощает интеграцию с другими модулями и
позволяет использовать компоненты в различных частях приложения без
дублирования кода.
Существует несколько способов экспорта:
export const API_URL = 'https://api.example.com';
export function fetchData() { /* ... */ }
Импорт конкретной сущности:
import { API_URL, fetchData } from './api.js';
export default class AppRoot extends LitElement { /* ... */ }
Импорт по умолчанию:
import AppRoot from './app-root.js';
Разделение приложения на модули делает архитектуру более предсказуемой и поддерживаемой. Обычно выделяют следующие уровни модульности:
import { LitElement, html, css } from 'lit';
export class ButtonComponent extends LitElement {
static styles = css`button { background-color: blue; color: white; }`;
render() {
return html`<button><slot></slot></button>`;
}
}
export async function getUserData(userId) {
const response = await fetch(`/users/${userId}`);
return response.json();
}
export const COLORS = {
primary: '#3498db',
secondary: '#2ecc71'
};
export function formatDate(date) {
return new Date(date).toLocaleDateString();
}
ES6 поддерживает динамический импорт через import(), что
позволяет загружать модули только при необходимости. В Lit это
используется для ленивой загрузки компонентов и снижения времени
первоначальной загрузки приложения:
button.addEventListener('click', async () => {
const { HeavyComponent } = await import('./heavy-component.js');
customElements.define('heavy-component', HeavyComponent);
});
Стандартная структура модульного Lit-приложения может выглядеть так:
src/
├── components/
│ ├── button-component.js
│ ├── modal-component.js
│ └── app-root.js
├── services/
│ ├── api.js
│ └── auth.js
├── utils/
│ ├── format.js
│ └── constants.js
└── main.js
Каждый каталог отвечает за отдельную функциональность. Это повышает читаемость и упрощает навигацию в проекте.
Модули могут импортировать друг друга без ограничений, при этом важно избегать циклических зависимостей, которые могут привести к ошибкам при загрузке:
// services/logger.js
export function log(message) { console.log(message); }
// components/app-root.js
import { log } from '../services/logger.js';
export class AppRoot extends LitElement {
connectedCallback() {
super.connectedCallback();
log('AppRoot mounted');
}
}
Циклические зависимости могут появляться, если, например,
logger.js импортирует AppRoot. Решение —
выделение общей функциональности в отдельный модуль.
Современные сборщики, такие как Vite, Webpack или Rollup, работают с ES6 модулями, что обеспечивает:
// vite.config.js
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig({
root: 'src',
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'src/main.js')
}
}
}
});
Модульная архитектура вместе с ES6 модулями делает приложения на Lit масштабируемыми, производительными и простыми в поддержке. Каждая часть системы изолирована, что позволяет легко расширять проект, подключать сторонние библиотеки и внедрять новые компоненты без риска поломать существующий функционал.