ESLint в flat config-архитектуре рассматривает глобальные переменные
как часть контекста выполнения кода, задаваемого явно через
languageOptions.globals. Это принципиально отличается от
старого .eslintrc, где глобальные переменные часто
задавались через env, а сами окружения скрыто добавляли
наборы глобалов.
Глобальные переменные в JavaScript появляются из разных источников:
window, document,
fetch)process, Buffer,
__dirname)describe, it,
jest)Проблема возникает в статическом анализе: линтер должен понимать,
какие идентификаторы допустимы без объявления. Без этого правило
no-undef начинает ошибочно помечать валидный код как
ошибочный.
В flat config глобальные переменные задаются через
languageOptions.globals:
export default [
{
files: ["**/*.{js,mjs,cjs}"],
languageOptions: {
globals: {
window: "readonly",
document: "readonly",
fetch: "readonly"
}
}
}
];
Каждое имя глобальной переменной задаётся как ключ объекта, а значение определяет уровень доступа:
"readonly" — переменная доступна только для чтения"writable" — переменная может быть переопределенаundefined (не рекомендуется явно использовать) —
отсутствие глобалаЭта модель делает конфигурацию более прозрачной: вместо абстрактных
env: browser теперь явно перечисляется поверхность
глобального API.
Правило no-undef в ESLint опирается на список глобальных
переменных, доступных в текущем конфиге. При использовании flat config
логика становится строго детерминированной:
globalsimport/requireто он считается ошибкой.
Пример:
export default [
{
languageOptions: {
globals: {
console: "readonly"
}
}
}
];
console.log("ok"); // допустимо
myGlobalVar(); // ошибка no-undef
В старой конфигурации:
env: {
browser: true
}
это автоматически добавляло десятки глобальных переменных.
В flat config этот механизм заменяется явным перечислением или
использованием пакета globals:
import globals from "globals";
export default [
{
languageOptions: {
globals: {
...globals.browser
}
}
}
];
Такой подход устраняет скрытую магию: теперь видно, какие именно идентификаторы добавлены в область видимости.
Типичный набор:
windowdocumentnavigatorlocationfetchКонфигурация:
import globals from "globals";
export default [
{
languageOptions: {
globals: {
...globals.browser
}
}
}
];
Включает:
processBuffer__dirnamemodulerequireimport globals from "globals";
export default [
{
languageOptions: {
globals: {
...globals.node
}
}
}
];
Используется в Web Workers и Service Workers:
selfpostMessageimportScriptslanguageOptions: {
globals: {
...globals.worker
}
}
Flat config позволяет тонко управлять тем, можно ли перезаписывать глобальные значения:
globals: {
Math: "readonly",
myDebug: "writable"
}
Такой подход важен для предотвращения случайного переопределения встроенных объектов:
Math = {}; // потенциальная ошибка, если readonly
Flat config поддерживает условные блоки через files:
export default [
{
files: ["src/**/*.js"],
languageOptions: {
globals: {
...globals.browser
}
}
},
{
files: ["scripts/**/*.js"],
languageOptions: {
globals: {
...globals.node
}
}
}
];
Это позволяет разделять контексты внутри одного проекта без конфликтов.
Тестовые фреймворки добавляют собственные глобалы:
describe, test,
expectdescribe, itПример:
languageOptions: {
globals: {
describe: "readonly",
it: "readonly",
expect: "readonly"
}
}
Или через globals пакет:
import globals from "globals";
globals.jest;
В некоторых проектах глобальные переменные вводятся явно через bundler (например, Webpack DefinePlugin) или runtime injection.
languageOptions: {
globals: {
__APP_VERSION__: "readonly",
API_BASE_URL: "readonly"
}
}
Такие переменные часто используются как compile-time константы, но линтеру необходимо явно сообщить о них, иначе они будут трактоваться как неопределённые.
В проектах с TypeScript глобальные переменные могут дублироваться
декларациями *.d.ts, но ESLint не читает типы напрямую для
определения глобалов.
Поэтому даже при наличии:
declare const API_URL: string;
в ESLint flat config всё равно требуется:
globals: {
API_URL: "readonly"
}
Если одновременно подключены:
globals.browserможет возникнуть конфликт прав доступа.
Разрешение writable для стандартных API приводит к
скрытым багам:
document = null; // ломает окружение
В монорепозиториях разные пакеты могут требовать разные глобальные
контексты. Flat config требует явного разделения через
files, иначе возникает загрязнение окружения.
Общий набор безопасных глобалов:
globals: {
console: "readonly",
setTimeout: "readonly",
clearTimeout: "readonly"
}
{
files: ["**/*.test.js"],
languageOptions: {
globals: {
...globals.jest
}
}
}
Разделение браузера и Node.js в одном проекте:
{
files: ["server/**/*.js"],
languageOptions: {
globals: {
...globals.node
}
}
}
{
files: ["client/**/*.js"],
languageOptions: {
globals: {
...globals.browser
}
}
}
Flat config в ESLint делает акцент на прозрачности: глобальные переменные больше не «подмешиваются» окружением, а становятся частью конфигурационного графа анализа.
Это приводит к следующим свойствам модели: