В проектах, использующих Chart.js, структура файлов определяется способом подключения библиотеки, масштабом приложения и выбранной системой сборки. Независимо от подхода, основная цель структуры — разделение ответственности между HTML-разметкой, логикой визуализации данных, конфигурациями графиков и статическими ресурсами.
При использовании Chart.js через CDN или локальное подключение библиотека интегрируется напрямую в HTML-документ. Такой подход характерен для небольших проектов, прототипов и учебных задач.
project/
│
├── index.html
├── css/
│ └── styles.css
├── js/
│ ├── app.js
│ └── charts.js
└── assets/
└── data.json
index.html содержит подключение Chart.js и точку
инициализации графиков. Основная логика разделяется между файлами
app.js и charts.js, где первый отвечает за
запуск приложения, а второй — за создание и конфигурацию графиков.
Пример подключения библиотеки:
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
Разделение JavaScript-кода на несколько файлов позволяет изолировать логику построения графиков от бизнес-логики приложения.
При использовании современных возможностей JavaScript структура становится более гранулированной. Chart.js подключается как модуль, что позволяет организовать код в виде независимых компонентов.
project/
│
├── index.html
├── src/
│ ├── main.js
│ ├── charts/
│ │ ├── lineChart.js
│ │ ├── barChart.js
│ │ └── pieChart.js
│ ├── services/
│ │ └── dataService.js
│ └── utils/
│ └── formatters.js
├── styles/
│ └── main.css
└── data/
└── dataset.json
main.js выполняет роль точки входа. В нём происходит инициализация приложения и вызов модулей графиков.
charts/ содержит изолированные модули графиков. Каждый файл отвечает за конкретный тип визуализации. Такой подход снижает связанность кода и упрощает поддержку.
Пример модуля линейного графика:
import { Chart } from 'chart.js/auto';
export function createLineChart(ctx, data) {
return new Chart(ctx, {
type: 'line',
data: data,
options: {
responsive: true,
plugins: {
legend: {
display: true
}
}
}
});
}
services/dataService.js отвечает за получение и подготовку данных. В крупных проектах этот слой часто интегрируется с API.
export async function fetchChartData() {
const response = await fetch('/data/dataset.json');
return await response.json();
}
utils/ используется для вспомогательных функций: форматирование чисел, преобразование дат, фильтрация данных перед визуализацией.
При использовании сборщиков структура становится более ориентированной на модули и окружение разработки.
project/
│
├── public/
│ └── index.html
│
├── src/
│ ├── main.js
│ ├── components/
│ │ └── ChartContainer.js
│ ├── charts/
│ │ ├── salesChart.js
│ │ └── usersChart.js
│ ├── api/
│ │ └── apiClient.js
│ ├── store/
│ │ └── state.js
│ └── styles/
│ └── app.css
│
├── package.json
└── vite.config.js
public/index.html служит шаблоном, куда внедряется собранный JavaScript-бандл.
src/main.js становится центральной точкой входа, где происходит:
components/ содержит переиспользуемые визуальные блоки. Например, контейнер графика может отвечать за создание canvas-элемента и управление его жизненным циклом.
export function createChartContainer(id) {
const container = document.createElement('div');
const canvas = document.createElement('canvas');
canvas.id = id;
container.appendChild(canvas);
return { container, canvas };
}
store/ применяется при наличии глобального состояния (например, фильтры данных, выбранные диапазоны дат, типы метрик).
В структурированных проектах конфигурации графиков часто выносятся отдельно, чтобы обеспечить переиспользуемость.
src/
├── config/
│ ├── defaultOptions.js
│ ├── colors.js
│ └── scales.js
Пример конфигурации:
export const defaultOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
enabled: true
}
}
};
Такой подход позволяет централизованно управлять визуальным стилем графиков без изменения логики их построения.
В проектах, где отображается несколько графиков, структура часто расширяется за счёт фабрик или менеджеров графиков.
src/
├── managers/
│ └── chartManager.js
Пример менеджера:
export class ChartManager {
constructor() {
this.charts = new Map();
}
add(id, chartInstance) {
this.charts.set(id, chartInstance);
}
destroy(id) {
const chart = this.charts.get(id);
if (chart) {
chart.destroy();
this.charts.delete(id);
}
}
}
Такой слой предотвращает утечки памяти и упрощает управление жизненным циклом визуализаций.
Одним из ключевых принципов является изоляция данных от графического слоя. Данные не должны зависеть от Chart.js напрямую.
data/
├── raw/
│ └── sales.json
├── transformed/
│ └── sales.monthly.json
Сырые данные сохраняются отдельно от преобразованных, которые уже готовы для передачи в Chart.js.
При развитии проекта структура может приблизиться к компонентной модели:
src/
├── components/
│ ├── LineChart/
│ │ ├── index.js
│ │ ├── view.js
│ │ └── controller.js
│ ├── BarChart/
│ └── PieChart/
Каждый компонент включает:
Такое разделение позволяет масштабировать систему визуализаций без увеличения сложности отдельных модулей.
Стили графиков и контейнеров часто выносятся отдельно, поскольку Chart.js работает внутри canvas и требует внешнего управления размерами.
styles/
├── layout.css
├── charts.css
└── themes/
└── dark.css
Контейнеры графиков определяют поведение адаптивности, а не сам Chart.js.
В структурированном проекте на Chart.js присутствует несколько уровней организации:
Такая архитектура обеспечивает независимость модулей и предсказуемость взаимодействия между данными и графиками.