Для расширения имени файла js нет исполняющего ядра

Обновлено: 21.11.2024

В модульной системе Node.js каждый файл рассматривается как отдельный модуль. Например, рассмотрим файл с именем foo.js:

В первой строке foo.js загружает модуль circle.js, который находится в том же каталоге, что и foo.js.

Вот содержимое circle.js:

Модуль circle.js экспортировал функции area() и окружность() . Функции и объекты добавляются в корень модуля путем указания дополнительных свойств в специальном объекте экспорта.

Переменные, локальные для модуля, будут частными, так как модуль обернут в функцию Node.js (см. оболочку модуля). В этом примере переменная PI является частной для circle.js .

Свойству module.exports можно присвоить новое значение (например, функцию или объект).

Ниже в bar.js используется модуль Square, который экспортирует класс Square:

Квадратный модуль определен в Square.js:

Модульная система CommonJS реализована в основном модуле модуля.

Node.js имеет две модульные системы: модули CommonJS и модули ECMAScript.

По умолчанию Node.js будет рассматривать следующие модули CommonJS:

Файлы с расширением .cjs;

Файлы с расширением .js, если ближайший родительский файл package.json содержит поле верхнего уровня "type" со значением "commonjs" .

Файлы с расширением .js, если ближайший родительский файл package.json не содержит поле верхнего уровня "тип" . Авторы пакетов должны включать поле «тип» даже в пакеты, где все исходники — CommonJS. Явное указание типа пакета облегчит средствам сборки и загрузчикам определение того, как следует интерпретировать файлы в пакете.

Файлы с расширением, отличным от .mjs , .cjs , .json , .node или .js (если ближайший родительский файл package.json содержит поле верхнего уровня «тип» со значением «модуль» , эти файлы будут распознаваться как модули CommonJS, только если они требуются, а не при использовании в качестве точки входа в командную строку программы).

Вызов require() всегда использует загрузчик модулей CommonJS. Вызов import() всегда использует загрузчик модулей ECMAScript.

Когда файл запускается непосредственно из Node.js, для параметра require.main устанавливается его модуль . Это означает, что можно определить, запускался ли файл напрямую, проверив require.main === module .

Для файла foo.js это будет true, если он запускается через узел foo.js, и false, если запускается с помощью require('./foo') .

Если точка входа не является модулем CommonJS, require.main не определено и основной модуль недоступен.

Семантика функции Node.js require() была разработана так, чтобы быть достаточно общей для поддержки разумных структур каталогов. Мы надеемся, что программы-менеджеры пакетов, такие как dpkg , rpm и npm, смогут создавать нативные пакеты из модулей Node.js без изменений.

Ниже мы даем рекомендуемую структуру каталогов, которая может работать:

Допустим, мы хотим, чтобы папка /usr/lib/node// содержала содержимое определенной версии пакета.

Пакеты могут зависеть друг от друга. Чтобы установить пакет foo, может потребоваться установить определенную версию пакета bar. Пакет bar сам по себе может иметь зависимости, а в некоторых случаях они могут даже конфликтовать или образовывать циклические зависимости.

  • /usr/lib/node/foo/1.2.3/ : содержимое пакета foo, версия 1.2.3.
  • /usr/lib/node/bar/4.3.2/ : содержимое пакета bar, от которого зависит foo.
  • /usr/lib/node/foo/1.2.3/node_modules/bar : символическая ссылка на /usr/lib/node/bar/4.3.2/ .
  • /usr/lib/node/bar/4.3.2/node_modules/* : символические ссылки на пакеты, от которых зависит bar.

Таким образом, даже если встречается цикл или возникают конфликты зависимостей, каждый модуль сможет получить версию своей зависимости, которую он может использовать.

Когда код в пакете foo требует('bar') , он получит версию, связанную символической ссылкой в ​​/usr/lib/node/foo/1.2.3/node_modules/bar . Затем, когда код в пакете bar вызовет require('quux') , он получит версию с символической ссылкой в ​​/usr/lib/node/bar/4.3.2/node_modules/quux .

Кроме того, чтобы сделать процесс поиска модулей еще более оптимальным, вместо размещения пакетов непосредственно в /usr/lib/node мы могли бы поместить их в /usr/lib/node_modules//. Тогда Node.js не будет искать отсутствующие зависимости в /usr/node_modules или /node_modules .

Чтобы сделать модули доступными для Node.js REPL, может быть полезно также добавить папку /usr/lib/node_modules в переменную среды $NODE_PATH. Поскольку поиск модулей с использованием папок node_modules является относительным и основан на реальном пути к файлам, выполняющим вызовы require() , сами пакеты могут находиться где угодно.

Из-за синхронного характера функции require() невозможно использовать ее для загрузки файлов модуля ECMAScript.Попытка сделать это вызовет ошибку ERR_REQUIRE_ESM. Вместо этого используйте import().

Расширение .mjs зарезервировано для модулей ECMAScript, которые нельзя загрузить с помощью require() . Дополнительную информацию о том, какие файлы анализируются как модули ECMAScript, см. в разделе «Определение модульной системы».

Чтобы получить точное имя файла, который будет загружен при вызове require(), используйте функцию require.resolve().

Объединяя все вышеперечисленное, вот высокоуровневый алгоритм в псевдокоде того, что делает функция require():

Модули кэшируются после первой загрузки. Это означает (среди прочего), что при каждом вызове require('foo') будет возвращаться один и тот же объект, если он разрешается в один и тот же файл.

При условии, что require.cache не изменен, многократные вызовы require('foo') не приведут к многократному выполнению кода модуля. Это важная особенность. С его помощью можно возвращать «частично выполненные» объекты, что позволяет загружать транзитивные зависимости, даже если они вызывают циклы.

Чтобы модуль выполнял код несколько раз, экспортируйте функцию и вызовите эту функцию.

Модули кэшируются на основе разрешенных имен файлов. Поскольку модули могут разрешаться в другое имя файла в зависимости от местоположения вызывающего модуля (загрузка из папок node_modules), это не гарантия, что require('foo') всегда будет возвращать один и тот же объект, если бы он разрешался в разные файлы.

Кроме того, в файловых системах или операционных системах, нечувствительных к регистру, разные разрешенные имена файлов могут указывать на один и тот же файл, но кэш по-прежнему будет рассматривать их как разные модули и перезагружать файл несколько раз. Например, require('./foo') и require('./FOO') возвращают два разных объекта, независимо от того, являются ли ./foo и ./FOO одним и тем же файлом.

Добавлен узел: поддержка импорта в require(. ) .

В Node.js есть несколько модулей, скомпилированных в двоичный файл. Эти модули более подробно описаны в других разделах этой документации.

Основные модули определяются в исходном коде Node.js и находятся в папке lib/.

При наличии циклических вызовов require() модуль может не завершить выполнение на момент возврата.

Рассмотрите такую ​​ситуацию:

Когда main.js загружает a.js , тогда a.js, в свою очередь, загружает b.js . В этот момент b.js пытается загрузить a.js. Чтобы предотвратить бесконечный цикл, незаконченная копия объекта экспорта a.js возвращается в модуль b.js. Затем b.js завершает загрузку, и его объект экспорта передается в модуль a.js.

К тому времени, когда main.js загрузит оба модуля, они оба готовы. Таким образом, вывод этой программы будет таким:

Требуется тщательное планирование, чтобы обеспечить правильную работу зависимостей циклических модулей в приложении.

Если точное имя файла не найдено, Node.js попытается загрузить требуемое имя файла с добавленными расширениями: .js , .json и, наконец, .node . При загрузке файла с другим расширением (например, .cjs) его полное имя должно быть передано в require(), включая расширение файла (например, require('./file.cjs')).

Файлы .json анализируются как текстовые файлы JSON, файлы .node интерпретируются как скомпилированные дополнительные модули, загружаемые с помощью process.dlopen() . Файлы с любым другим расширением (или вообще без расширения) анализируются как текстовые файлы JavaScript. Обратитесь к разделу Определение модульной системы, чтобы понять, какая цель синтаксического анализа будет использоваться.

Обязательный модуль с префиксом '/' представляет собой абсолютный путь к файлу. Например, require('/home/marco/foo.js') загрузит файл в /home/marco/foo.js .

Обязательный модуль с префиксом './' относится к файлу, вызывающему require() . То есть, Circle.js должен находиться в том же каталоге, что и foo.js, чтобы функция require('./circle') могла его найти.

Без начальных '/' , './' или '../' для обозначения файла модуль должен быть либо основным модулем, либо загружаться из папки node_modules.

Если указанный путь не существует, функция require() выдаст ошибку MODULE_NOT_FOUND.

Существует три способа передачи папки функции require() в качестве аргумента.

Во-первых, нужно создать файл package.json в корне папки, в котором указан основной модуль. Пример файла package.json может выглядеть так:

Если бы это было в папке ./some-library , то require('./some-library') попытается загрузить ./some-library/lib/some-library.js .

Если в каталоге нет файла package.json или если «основная» запись отсутствует или не может быть разрешена, то Node.js попытается загрузить файл index.js или index.node из этого каталога. каталог. Например, если в предыдущем примере не было файла package.json, то require('./some-library') попытается загрузить:

  • ./some-library/index.js
  • ./some-library/index.node

Если эти попытки не увенчаются успехом, Node.js сообщит об отсутствии всего модуля с ошибкой по умолчанию:

Во всех трех случаях вызов import('./some-library') приведет к ошибке ERR_UNSUPPORTED_DIR_IMPORT. Использование экспорта подпутей пакетов или импорта подпутей может обеспечить те же преимущества организации сдерживания, что и папки в качестве модулей, и работает как для require, так и для import .

Если идентификатор модуля, переданный в require(), не является основным модулем и не начинается с '/' , '../' или './' , то Node.js запускается в каталоге текущего module, добавляет /node_modules и пытается загрузить модуль из этого места. Node.js не будет добавлять node_modules к пути, который уже заканчивается на node_modules .

Если он там не найден, то он перемещается в родительский каталог и так далее, пока не будет достигнут корень файловой системы.

Например, если файл в '/home/ry/projects/foo.js' вызывается require('bar.js') , то Node.js будет искать в следующих местах в этом порядке:

  • /home/ry/projects/node_modules/bar.js
  • /home/ry/node_modules/bar.js
  • /home/node_modules/bar.js
  • /node_modules/bar.js

Это позволяет программам локализовать свои зависимости, чтобы они не конфликтовали.

Можно потребовать определенных файлов или подмодулей, распространяемых вместе с модулем, включив суффикс пути после имени модуля. Например, require('example-module/path/to/file') разрешает путь/к/файлу относительно того, где расположен пример-модуль. Путь с суффиксом следует той же семантике разрешения модуля.

Если для переменной среды NODE_PATH задан список абсолютных путей, разделенных двоеточием, Node.js будет искать модули по этим путям, если они не будут найдены где-либо еще.

В Windows NODE_PATH разделяется точкой с запятой ( ; ) вместо двоеточия.

NODE_PATH изначально был создан для поддержки загрузки модулей с разных путей до того, как был определен текущий алгоритм разрешения модулей.

NODE_PATH по-прежнему поддерживается, но теперь он менее необходим, поскольку экосистема Node.js приняла соглашение о расположении зависимых модулей. Иногда развертывания, которые полагаются на NODE_PATH, демонстрируют удивительное поведение, когда люди не знают, что NODE_PATH должен быть установлен. Иногда зависимости модуля изменяются, что приводит к загрузке другой версии (или даже другого модуля) при поиске NODE_PATH.

Кроме того, Node.js будет искать в следующем списке GLOBAL_FOLDERS:

  • 1: $HOME/.node_modules
  • 2: $HOME/.node_libraries
  • 3: $PREFIX/библиотека/узел

Где $HOME – это домашний каталог пользователя, а $PREFIX – настроенный Node.js node_prefix .

В основном это связано с историческими причинами.

Настоятельно рекомендуется размещать зависимости в локальной папке node_modules. Они будут загружаться быстрее и надежнее.

Перед выполнением кода модуля Node.js поместит в него оболочку функции, которая выглядит следующим образом:

При этом Node.js достигает нескольких целей:

  • Он сохраняет переменные верхнего уровня (определенные с помощью var , const или let ) привязанными к модулю, а не к глобальному объекту.
  • Это помогает предоставить некоторые глобальные переменные, которые на самом деле специфичны для модуля, например:
    • Модуль и экспортирует объекты, которые разработчик может использовать для экспорта значений из модуля.
    • Вспомогательные переменные __filename и __dirname , содержащие абсолютное имя файла модуля и путь к каталогу.

    Имя каталога текущего модуля. Это то же самое, что и path.dirname() для __filename .

    Пример: запуск node example.js из /Users/mjr

    Имя файла текущего модуля. Это абсолютный путь к текущему файлу модуля с разрешенными символическими ссылками.

    Для основной программы это не обязательно совпадает с именем файла, используемым в командной строке.

    См. __dirname для имени каталога текущего модуля.

    Запуск node example.js из /Users/mjr

    Даны два модуля: a и b , где b – это зависимость от a, а структура каталогов состоит из:

    • /Users/mjr/app/a.js
    • /Users/mjr/app/node_modules/b/b.js

    Ссылки на __filename в b.js возвращают /Users/mjr/app/node_modules/b/b.js, а ссылки на __filename в a.js возвращают /Users/mjr/app/a.js .

    Ссылка на module.exports, который короче по типу. Подробнее о том, когда использовать экспорт и когда использовать module.exports, см. в разделе о ярлыке экспорта.

    Ссылка на текущий модуль, см. раздел об объекте модуля. В частности, module.exports используется для определения того, что модуль экспортирует и делает доступным через require() .

    Используется для импорта модулей, JSON и локальных файлов. Модули можно импортировать из node_modules. Локальные модули и файлы JSON можно импортировать по относительному пути (например, ./, ./foo, ./bar/baz, ../foo ), который будет разрешен для каталога с именем __dirname (если он определен) или текущего рабочего каталога. Относительные пути в стиле POSIX разрешаются независимо от ОС, а это означает, что приведенные выше примеры будут работать в Windows так же, как и в системах Unix.

    Модули кэшируются в этом объекте, когда они требуются. При удалении значения ключа из этого объекта следующее требование перезагрузит модуль. Это не относится к нативным надстройкам, повторная загрузка которых приведет к ошибке.

    Также возможно добавление или замена записей. Этот кеш проверяется перед нативными модулями, и если в кеш добавляется имя, соответствующее нативному модулю, только вызовы node: -prefixed require будут получать нативный модуль. Используйте с осторожностью!

    Проинструктируйте require о том, как обращаться с определенными расширениями файлов.

    Обрабатывать файлы с расширением .sjs как .js :

    Устарело. В прошлом этот список использовался для загрузки модулей, отличных от JavaScript, в Node.js путем их компиляции по требованию. Однако на практике есть гораздо лучшие способы сделать это, например загрузить модули через какую-либо другую программу Node.js или заранее скомпилировать их в JavaScript.

    Избегайте использования require.extensions . Использование может привести к незначительным ошибкам, и разрешение расширений становится все медленнее с каждым зарегистрированным расширением.

    Объект модуля, представляющий сценарий входа, загружаемый при запуске процесса Node.js, или неопределенный, если точка входа программы не является модулем CommonJS. См. «Доступ к основному модулю».

    В скрипте entry.js:

    Теперь поддерживается параметр paths.

    • request Путь к модулю для разрешения.
    • параметры
      • paths Пути для разрешения местоположения модуля. Если они присутствуют, эти пути используются вместо путей разрешения по умолчанию, за исключением GLOBAL_FOLDERS, таких как $HOME/.node_modules, которые всегда включаются. Каждый из этих путей используется в качестве отправной точки для алгоритма разрешения модулей, что означает, что иерархия node_modules проверяется из этого расположения.

      Используйте внутренний механизм require() для поиска местоположения модуля, но вместо загрузки модуля просто верните разрешенное имя файла.

      Если модуль не может быть найден, выдается ошибка MODULE_NOT_FOUND.

      В каждом модуле свободная переменная модуля является ссылкой на объект, представляющий текущий модуль. Для удобства module.exports также доступен через файл exports module-global. модуль на самом деле не является глобальным, а скорее локальным для каждого модуля.

      Объекты модуля, необходимые для этого в первый раз.

      Объект module.exports создается системой модулей. Иногда это неприемлемо; многие хотят, чтобы их модуль был экземпляром некоторого класса. Для этого назначьте нужный объект экспорта в module.exports. Назначение нужного объекта экспорту просто перепривязывает локальную переменную экспорта, что, вероятно, не совсем то, что нужно.

      Например, предположим, что мы делаем модуль с именем a.js :

      Тогда в другом файле мы могли бы сделать:

      Назначение module.exports должно быть выполнено немедленно. Это невозможно сделать ни в каких обратных вызовах. Это не работает:

      Переменная exports доступна на уровне файла модуля, и ей присваивается значение module.exports перед оценкой модуля.

      Это позволяет сократить путь, так что module.exports.f = . можно записать более кратко как exports.f = . . Однако имейте в виду, что, как и любой переменной, если для exports присваивается новое значение, оно больше не привязано к module.exports :

      Когда свойство module.exports полностью заменяется новым объектом, обычно также переназначаются экспорты:

      Чтобы проиллюстрировать поведение, представьте эту гипотетическую реализацию require() , которая очень похожа на то, что на самом деле делает require() :

      Полностью разрешенное имя файла модуля.

      Идентификатор модуля. Обычно это полностью разрешенное имя файла.

      Независимо от того, завершена ли загрузка модуля или находится в процессе загрузки.

      Модуль, который первым потребовал этот модуль, или null, если текущий модуль является точкой входа текущего процесса, или undefined, если модуль был загружен чем-то, что не является модулем CommonJS (например, REPL или import ).< /p>

      Имя каталога модуля. Обычно это то же самое, что и path.dirname() в module.id .

      Пути поиска модуля.

      Метод module.require() позволяет загрузить модуль, как если бы функция require() была вызвана из исходного модуля.

      Для этого необходимо получить ссылку на объект модуля. Поскольку require() возвращает module.exports , а модуль обычно только доступен в коде определенного модуля, для использования его необходимо явно экспортировать.

      Обновление: эта статья теперь является частью моей книги «Node.js Beyond The Basics».

      Node использует два основных модуля для управления зависимостями модулей:

      • Модуль require, который доступен в глобальном масштабе — нет необходимости require('require') .
      • Модуль модуля, который также доступен в глобальной области видимости — нет необходимости require('module') .

      Модуль require можно рассматривать как команду, а модуль module — как организатор всех необходимых модулей.

      Необходимость модуля в Node не так уж сложна.

      Основным объектом, экспортируемым модулем require, является функция (как в приведенном выше примере). Когда Node вызывает эту функцию require() с локальным путем к файлу в качестве единственного аргумента функции, Node выполняет следующую последовательность шагов:

      • Решение: найти абсолютный путь к файлу.
      • Загрузка: для определения типа содержимого файла.
      • Обертывание: чтобы дать файлу его частную область. Это то, что делает объекты require и module локальными для каждого требуемого файла.
      • Оценка. Это то, что в конечном итоге делает виртуальная машина с загруженным кодом.
      • Кэширование: чтобы, когда нам снова потребуется этот файл, мы не повторяли все шаги в другой раз.

      В этой статье я попытаюсь объяснить на примерах эти разные этапы и то, как они влияют на то, как мы пишем модули в Node.

      Позвольте мне сначала создать каталог для размещения всех примеров с помощью моего терминала:

      Все команды в оставшейся части этой статьи будут выполняться из ~/learn-node .

      Разрешение локального пути

      Позвольте представить вам объект модуля. Вы можете проверить это на простом сеансе REPL:

      Каждый объект модуля получает свойство id для его идентификации. Этот идентификатор обычно представляет собой полный путь к файлу, но в сеансе REPL это просто .

      Модули узла имеют прямое отношение к файлам в файловой системе. Нам нужен модуль, загружая содержимое файла в память.

      Однако, поскольку Node позволяет запрашивать файл многими способами (например, с относительным путем или предварительно настроенным путем), прежде чем мы сможем загрузить содержимое файла в память, нам нужно найти абсолютное местоположение файла. этот файл.

      Когда нам требуется модуль "найти меня", без указания пути:

      Node будет искать find-me.js по всем путям, указанным в module.paths, по порядку.

      Список путей в основном представляет собой список каталогов node_modules в каждом каталоге от текущего каталога до корневого каталога. Он также включает несколько устаревших каталогов, использование которых не рекомендуется.

      Если Node не сможет найти find-me.js ни по одному из этих путей, будет выдано сообщение «не удается найти модуль».

      Если сейчас вы создадите локальный каталог node_modules и поместите туда файл find-me.js, строка require('find-me') найдет его.

      Когда мы запрашиваем('find-me') из каталога Learn-Node, который имеет свои собственные node_modules/find-me.js , файл find-me.js в домашнем каталоге вообще не загружается. :

      Если мы удалим локальный каталог node_modules из ~/learn-node и попытаемся еще раз запросить find-me, будет использован файл в домашнем каталоге node_modules:

      Требуется папка

      Модули не обязательно должны быть файлами. Мы также можем создать папку find-me в node_modules и поместить туда файл index.js. Та же строка require('find-me') будет использовать файл index.js этой папки:

      Обратите внимание, как он снова проигнорировал путь node_modules к домашнему каталогу, поскольку теперь у нас есть локальный.

      Файл index.js будет использоваться по умолчанию, когда нам потребуется папка, но мы можем указать, с какого имени файла начинать папку, используя свойство main в package.json . Например, чтобы строка require('find-me') разрешалась в другой файл в папке find-me, все, что нам нужно сделать, это добавить туда файл package.json и указать, какой файл следует использовать для разрешения эта папка:

      require.resolve

      Если вы хотите только разрешить модуль, но не выполнять его, вы можете использовать функцию require.resolve. Она ведет себя точно так же, как основная функция require, но не загружает файл. Он по-прежнему будет выдавать ошибку, если файл не существует, и будет возвращать полный путь к файлу, когда он будет найден.

      Это можно использовать, например, чтобы проверить, установлен ли дополнительный пакет или нет, и использовать его только тогда, когда он доступен.

      Относительные и абсолютные пути

      Помимо разрешения модулей из каталогов node_modules, мы также можем разместить модуль в любом месте и потребовать его либо с относительными путями ( ./ и ../ ), либо с абсолютными путями, начинающимися с / .

      Если, например, файл find-me.js находится в папке lib, а не в папке node_modules, мы можем запросить его с помощью:

      Отношение родитель-потомок между файлами

      Создайте файл lib/util.js и добавьте туда строку console.log для его идентификации. Кроме того, console.log сам объект модуля:

      Проделайте то же самое с файлом index.js, который мы будем выполнять с помощью команды node. Сделайте так, чтобы этот файл index.js требовал lib/util.js :

      Теперь запустите файл index.js с узлом:

      Обратите внимание, что основной индексный модуль (идентификатор: '.') теперь указан как родительский для модуля lib/util. Однако модуль lib/util не был указан как дочерний по отношению к модулю index. Вместо этого у нас есть значение [Circular], потому что это циклическая ссылка. Если Node напечатает объект модуля lib/util, он войдет в бесконечный цикл. Вот почему он просто заменяет ссылку lib/util на [Circular].

      Что еще более важно, что произойдет, если модулю lib/util потребуется основной индексный модуль? Здесь мы подходим к так называемой круговой модульной зависимости, разрешенной в Node.

      Чтобы лучше понять это, давайте сначала разберемся с некоторыми другими понятиями объекта модуля.

      экспорт, module.exports и синхронная загрузка модулей

      В любом модуле экспорт является специальным объектом. Как вы заметили выше, каждый раз, когда мы печатали объект модуля, у него было свойство exports, которое до сих пор было пустым объектом. Мы можем добавить любой атрибут к этому специальному объекту экспорта. Например, давайте экспортируем атрибут id для index.js и lib/util.js:

      Когда мы теперь выполним index.js, мы увидим, что эти атрибуты управляются для каждого объекта модуля файла:

      Я удалил некоторые атрибуты из приведенного выше вывода, чтобы сделать его кратким, но обратите внимание, что объект экспорта теперь имеет атрибуты, которые мы определили в каждом модуле. Вы можете поместить столько атрибутов, сколько хотите, в этот объект экспорта, и вы можете фактически изменить весь объект, чтобы он был чем-то другим. Например, чтобы изменить объект экспорта на функцию, а не на объект, мы делаем следующее:

      Когда вы сейчас запустите index.js, вы увидите, что объект экспорта является функцией:

      Обратите внимание, что мы не сделали exports = function() <>, чтобы превратить объект экспорта в функцию. На самом деле мы не можем этого сделать, потому что переменная exports внутри каждого модуля — это просто ссылка на module.exports, который управляет экспортируемыми свойствами. Когда мы переназначаем переменную exports, эта ссылка теряется, и мы вводим новую переменную вместо изменения объекта module.exports.

      Объект module.exports в каждом модуле — это то, что возвращает функция require, когда нам требуется этот модуль. Например, измените строку require('./lib/util') в index.js на:

      Приведенный выше код зафиксирует свойства, экспортированные в lib/util, в константу UTIL. Когда мы сейчас запустим index.js, будет выведена самая последняя строка:

      Давайте также поговорим об атрибуте load для каждого модуля. До сих пор каждый раз, когда мы печатали объект модуля, мы видели загруженный атрибут этого объекта со значением false .

      Модуль модуля использует атрибут load для отслеживания того, какие модули были загружены (значение true) и какие модули все еще загружаются (значение false). Например, мы можем увидеть полностью загруженный модуль index.js, если напечатаем его объект модуля в следующем цикле цикла обработки событий с помощью вызова setImmediate:

      Вывод будет таким:

      Обратите внимание, что в этом отложенном выводе console.log и lib/util.js, и index.js полностью загружены.

      Объект экспорта становится завершенным, когда Node завершает загрузку модуля (и помечает его соответствующим образом). Весь процесс запроса/загрузки модуля является синхронным. Вот почему мы смогли увидеть модули полностью загруженными после одного цикла цикла обработки событий.

      Это также означает, что мы не можем изменять объект экспорта асинхронно. Мы не можем, например, сделать следующее ни в одном модуле:

      Круговая зависимость модуля

      Теперь попробуем ответить на важный вопрос о циклической зависимости в Node: что происходит, когда для модуля 1 требуется модуль 2, а для модуля 2 требуется модуль 1?

      Чтобы выяснить это, давайте создадим следующие два файла в lib/ , module1.js и module2.js и заставим их требовать друг друга:

      Когда мы запускаем module1.js, мы видим следующее:

      Нам требовался модуль 2 до того, как модуль 1 был полностью загружен, а поскольку модуль 2 требовал модуля 1, пока он не был полностью загружен, в этот момент мы получаем от объекта экспорта все свойства, экспортированные до циклической зависимости. Сообщалось только о свойстве a, так как и b, и c были экспортированы после того, как требуется модуль2 и напечатан модуль1 .

      Node делает это очень просто. Во время загрузки модуля он создает объект экспорта. Вы можете запросить модуль до того, как он загрузится, и вы просто получите объект частичного экспорта с тем, что было определено до сих пор.

      Дополнения JSON и C/C++

      Мы можем запросить файлы JSON и файлы дополнений C++ с помощью функции require. Для этого даже не нужно указывать расширение файла.

      Если расширение файла не указано, первое, что Node попытается разрешить, — это файл .js. Если он не может найти файл .js, он попробует файл .json и проанализирует файл .json, если он будет найден как текстовый файл JSON. После этого он попытается найти бинарный файл .node. Однако, чтобы устранить двусмысленность, вам, вероятно, следует указать расширение файла, когда требуются файлы, отличные от файлов .js.

      Требование файлов JSON полезно, если, например, все, что вам нужно для управления в этом файле, — это некоторые статические значения конфигурации или некоторые значения, которые вы периодически считываете из внешнего источника. Например, если бы у нас был следующий файл config.json:

      Мы можем запросить это прямо следующим образом:

      Выполнение приведенного выше кода приведет к следующему результату:

      Если Node не может найти файл .js или .json, он будет искать файл .node и интерпретировать его как скомпилированный дополнительный модуль.

      На сайте документации Node есть пример файла надстройки, написанного на C++. Это простой модуль, который предоставляет функцию hello(), а функция hello выводит слово «мир».

      Вы можете использовать пакет node-gyp для компиляции и преобразования файла .cc в файл .node. Вам просто нужно настроить файл binding.gyp, чтобы сообщить node-gyp, что делать.

      После того, как у вас есть файл addon.node (или любое другое имя, которое вы укажете в binding.gyp ), вы можете изначально потребовать его, как и любой другой модуль:

      Мы действительно можем увидеть поддержку трех расширений, взглянув на require.extensions .

      Глядя на функции каждого расширения, вы можете ясно увидеть, что Node будет делать с каждым из них. Он использует module._compile для файлов .js, JSON.parse для файлов .json и process.dlopen для файлов .node.

      Весь код, который вы пишете в Node, будет заключен в функции

      Оболочку модулей Node часто неправильно понимают. Чтобы понять это, напомню про отношение exports/module.exports.

      Мы можем использовать объект exports для экспорта свойств, но не можем напрямую заменить объект exports, потому что это просто ссылка на module.exports

      Как именно этот объект экспорта, который кажется глобальным для каждого модуля, определяется как ссылка на объект модуля?

      Позвольте мне задать еще один вопрос, прежде чем объяснять процесс упаковки Node.

      В браузере, когда мы объявляем переменную в скрипте следующим образом:

      Эта переменная ответа будет глобально доступна во всех скриптах после скрипта, в котором она определена.

      Это не относится к Node. Когда мы определяем переменную в одном модуле, другие модули программы не будут иметь доступа к этой переменной. Так как же получается, что переменные в Node волшебным образом ограничены областью действия?

      Ответ прост. Перед компиляцией модуля Node заключает код модуля в функцию, которую мы можем проверить с помощью свойства оболочки модуля модуля.

      Node не выполняет код, который вы пишете в файле напрямую. Он выполняет эту функцию-оболочку, в теле которой будет ваш код. Это то, что сохраняет переменные верхнего уровня, определенные в любом модуле, привязанными к этому модулю.

      Эта функция-оболочка имеет 5 аргументов: exports, require, module, __filename и __dirname. Именно поэтому они кажутся глобальными, хотя на самом деле они специфичны для каждого модуля.

      Все эти аргументы получают свои значения, когда Node выполняет функцию-оболочку. exports определяется как ссылка на module.exports до этого. require и module относятся к выполняемой функции, а переменные __filename / __dirname будут содержать абсолютное имя файла и путь к каталогу обернутого модуля.

      Вы можете увидеть эту оболочку в действии, если запустите скрипт с ошибкой в ​​первой строке:

      Обратите внимание, что первая строка скрипта, как указано выше, была функцией-оболочкой, а не плохой ссылкой.

      Более того, поскольку каждый модуль заключен в функцию, мы можем получить доступ к аргументам этой функции с помощью ключевого слова arguments:

      Первый аргумент — это объект экспорта, который начинается пустым. Затем у нас есть объекты require/module, оба из которых являются экземплярами, связанными с файлом index.js, который мы выполняем. Это не глобальные переменные. Последние 2 аргумента — это путь к файлу и путь к его каталогу.

      Функция упаковки возвращает значение module.exports . Внутри обернутой функции мы можем использовать объект exports для изменения свойств module.exports , но мы не можем переназначить сам экспорт, потому что это просто ссылка.

      Происходит примерно следующее:

      Если мы изменим весь объект экспорта, он больше не будет ссылкой на module.exports. Именно так ссылочные объекты JavaScript работают везде, а не только в этом контексте.

      Объект запроса

      В require нет ничего особенного. Это объект, который действует в основном как функция, которая принимает имя модуля или путь и возвращает объект module.exports. Мы можем просто переопределить объект require с помощью нашей собственной логики, если захотим.

      Например, возможно, в целях тестирования, мы хотим, чтобы каждый вызов require по умолчанию имитировался и просто возвращал поддельный объект вместо требуемого объекта экспорта модуля. Это простое переназначение require сделает свое дело:

      После выполнения описанного выше переназначения require каждый вызов require('something') в скрипте будет просто возвращать фиктивный объект.

      Объект require также имеет собственные свойства. Мы видели свойство разрешения, которое представляет собой функцию, выполняющую только этап разрешения требуемого процесса. Мы также видели require.extensions выше.

      Существует также require.main, который может быть полезен для определения того, требуется ли скрипт или выполняется напрямую.

      Скажем, например, что у нас есть эта простая функция printInFrame в print-in-frame.js:

      Функция принимает числовой размер аргумента и заголовок строкового аргумента и печатает этот заголовок в рамке из звездочек, контролируемых заданным нами размером.

      Мы хотим использовать этот файл двумя способами:

      Передача 8 и Hello в качестве аргументов командной строки для вывода «Hello» в кадре из 8 звезд.

      <р>2. С требованием. Предполагая, что требуемый модуль будет экспортировать функцию printInFrame, мы можем просто вызвать ее:

      Напечатать заголовок «Привет» в рамке из 5 звезд.

      Это два разных использования. Нам нужен способ определить, запускается ли файл как автономный скрипт или он требуется для других скриптов.

      Здесь мы можем использовать этот простой оператор if:

      Поэтому мы можем использовать это условие, чтобы удовлетворить приведенным выше требованиям к использованию, вызывая функцию printInFrame по-другому:

      Когда файл не требуется, мы просто вызываем функцию printInFrame с элементами process.argv. В противном случае мы просто изменим объект module.exports на саму функцию printInFrame.

      Все модули будут кэшированы

      Кэширование важно понимать. Позвольте мне использовать простой пример, чтобы продемонстрировать это.

      Скажем, у вас есть следующий файл ascii-art.js, который печатает классный заголовок:

      Мы хотим отображать этот заголовок каждый раз, когда нам требуется файл. Поэтому, когда нам требуется файл дважды, мы хотим, чтобы заголовок отображался дважды.

      Второй запрос не будет отображать заголовок из-за кэширования модулей. Node кэширует первый вызов и не загружает файл при втором вызове.

      Мы можем увидеть этот кэш, напечатав require.cache после первого запроса. Кэш-реестр — это просто объект, у которого есть свойство для каждого требуемого модуля. Эти значения свойств являются объектами модуля, используемыми для каждого модуля. Мы можем просто удалить свойство из этого объекта require.cache, чтобы сделать этот кеш недействительным. Если мы это сделаем, Node повторно загрузит модуль, чтобы повторно кэшировать его.

      Однако в данном случае это не самое эффективное решение. Простое решение — обернуть строку журнала в ascii-art.js функцией и экспортировать эту функцию. Таким образом, когда нам требуется файл ascii-art.js, мы получаем функцию, которую мы можем выполнять для вызова строки журнала каждый раз:

      В этом разделе описываются некоторые расширенные функции JavaScript, поддерживаемые Visual Studio Code. Используя языковую службу TypeScript, VS Code может предоставлять интеллектуальное завершение (IntelliSense), а также проверку типов для JavaScript.

      IntelliSense

      IntelliSense для JavaScript в Visual Studio Code обеспечивает интеллектуальное завершение кода, информацию о параметрах, поиск по ссылкам и многие другие расширенные языковые функции. Наш JavaScript IntelliSense основан на языковой службе JavaScript, разработанной командой TypeScript. Хотя IntelliSense должен работать для большинства проектов JavaScript без какой-либо настройки, вы можете сделать IntelliSense еще более полезным с помощью JSDoc или настроив проект jsconfig.json.

      Подробнее о том, как работает JavaScript IntelliSense, в том числе о том, как он основан на выводе типов, аннотациях JSDoc, объявлениях TypeScript и комбинировании проектов JavaScript и TypeScript, см. в документации по языковой службе JavaScript.

      Если вывод типа не дает желаемой информации, информация о типе может быть предоставлена ​​явно с помощью аннотаций JSDoc. В этом документе описаны поддерживаемые в настоящее время аннотации JSDoc.

      В дополнение к объектам, методам и свойствам окно JavaScript IntelliSense также обеспечивает базовое завершение слов для символов в вашем файле.

      Ввод и автоматическое получение типов

      Библиотеки и платформы IntelliSense для JavaScript основаны на файлах объявления типов (типизации) TypeScript. Файлы объявлений типов написаны на TypeScript, поэтому они могут выражать типы данных параметров и функций, что позволяет VS Code эффективно обеспечивать богатый опыт работы с IntelliSense.

      Многие популярные библиотеки поставляются с файлами типизации, поэтому IntelliSense для них устанавливается автоматически. Для библиотек, которые не включают типизацию, функция автоматического получения типов VS Code автоматически установит для вас файл типизации, поддерживаемый сообществом.

      Для автоматического получения типа требуется npmjs, диспетчер пакетов Node.js, который входит в состав среды выполнения Node.js. На этом изображении вы можете увидеть IntelliSense, включая сигнатуру метода, информацию о параметрах и документацию по методу для популярной библиотеки lodash.

      Файлы объявлений типов автоматически загружаются и управляются Visual Studio Code для пакетов, перечисленных в package.json вашего проекта или импортированных в файл JavaScript.

      В качестве альтернативы вы можете явно перечислить пакеты, для которых нужно получить файлы объявления типов, в jsconfig.json.

      Большинство распространенных библиотек JavaScript поставляются с файлами объявлений или имеют доступные файлы объявлений типов. Вы можете найти пакет файла объявления типа библиотеки, используя сайт TypeSearch.

      Исправлено предупреждение npm не установлено для автоматического получения типа

      Automatic Type Acquisition использует npm, диспетчер пакетов Node.js, для установки и управления файлами объявления типов (типизации). Чтобы убедиться, что автоматическое получение типов работает правильно, сначала убедитесь, что на вашем компьютере установлен npm.

      Запустите npm --version из терминала или командной строки, чтобы быстро проверить, установлен ли и доступен ли npm.

      Если у вас установлен npm, но по-прежнему отображается предупреждающее сообщение, вы можете явно указать VS Code, где установлен npm, с помощью параметра typescript.npm. Это должен быть полный путь к исполняемому файлу npm на вашем компьютере, и он не должен совпадать с версией npm, которую вы используете для управления пакетами в вашей рабочей области. typescript.npm требует TypeScript 2.3.4+.

      Например, в Windows вы должны добавить такой путь в файл settings.json:

      Проекты JavaScript (jsconfig.json)

      Присутствие файла jsconfig.json в каталоге указывает на то, что этот каталог является корнем проекта JavaScript. jsconfig.json указывает корневые файлы и параметры языковых функций, предоставляемых языковой службой JavaScript. Для обычных настроек файл jsconfig.json не требуется, однако бывают ситуации, когда вы захотите добавить файл jsconfig.json .

      • Не все файлы должны быть в вашем проекте JavaScript (например, вы хотите исключить некоторые файлы из показа IntelliSense). Такая ситуация характерна для внешнего и внутреннего кода.
      • Ваша рабочая область содержит более одного контекста проекта. В этом случае вам следует добавить файл jsconfig.json в корневую папку каждого проекта.
      • Вы используете компилятор TypeScript для компиляции исходного кода JavaScript нижнего уровня.

      Расположение jsconfig.json

      Чтобы определить наш код как проект JavaScript, создайте jsconfig.json в корне вашего кода JavaScript, как показано ниже. Проект JavaScript представляет собой исходные файлы проекта и не должен включать производные или упакованные файлы (например, каталог dist).

      В более сложных проектах в рабочей области может быть определено несколько файлов jsconfig.json. Это необходимо сделать, чтобы исходный код одного проекта не отображался в IntelliSense другого проекта.

      Ниже показан проект с папкой клиента и сервера, показывающий два отдельных проекта JavaScript:

      Написание файла jsconfig.json

      Ниже приведен простой шаблон для файла jsconfig.json, который определяет цель JavaScript как ES6, а атрибут exclude исключает папку node_modules. Вы можете скопировать и вставить этот код в свой файл jsconfig.json.

      Атрибут exclude сообщает языковой службе, какие файлы не являются частью вашего исходного кода. Если IntelliSense работает медленно, добавьте папки в список исключений (VS Code предложит вам сделать это, если обнаружит медленные завершения). Вы захотите исключить файлы, созданные в процессе сборки (например, каталог dist). Эти файлы будут вызывать двойное отображение предложений и замедлят работу IntelliSense.

      Вы можете явно указать файлы в своем проекте, используя атрибут include. Если атрибут включения отсутствует, то по умолчанию включаются все файлы в содержащем каталоге и подкаталогах. Если указан атрибут включения, включаются только эти файлы.

      Вот пример с явным включенным атрибутом:

      Наилучшая практика и наименее подверженный ошибкам путь — использовать атрибут include с одной папкой src. Обратите внимание, что пути к файлам в exclude и include относятся к расположению jsconfig.json .

      Для получения дополнительной информации см. полную документацию по jsconfig.json.

      Переход на TypeScript

      Возможны смешанные проекты TypeScript и JavaScript. Чтобы начать миграцию на TypeScript, переименуйте файл jsconfig.json в tsconfig.json и установите для свойства allowJs значение true . Дополнительную информацию см. в разделе Миграция с JavaScript.

      Примечание. jsconfig.json — это то же самое, что и файл tsconfig.json, только если для параметра allowJ установлено значение true. См. документацию для tsconfig.json здесь, чтобы увидеть другие доступные параметры.

      Проверка типов JavaScript

      VS Code позволяет использовать некоторые расширенные функции TypeScript для проверки типов и создания отчетов об ошибках в обычных файлах JavaScript. Это отличный способ выявить распространенные ошибки программирования. Эти проверки типов также позволяют использовать несколько замечательных быстрых исправлений для JavaScript, в том числе «Добавить отсутствующий импорт» и «Добавить отсутствующее свойство».

      TypeScript может выводить типы в файлах .js так же, как и в файлах .ts. Когда типы невозможно вывести, их можно указать с помощью комментариев JSDoc. Вы можете узнать больше о том, как TypeScript использует JSDoc для проверки типов JavaScript, в разделе Проверка типов файлов JavaScript.

      Проверка типов JavaScript является необязательной и необязательной. Существующие инструменты проверки JavaScript, такие как ESLint, можно использовать вместе с новой встроенной функцией проверки типов.

      Вы можете начать проверку типов несколькими способами, в зависимости от ваших потребностей.

      По файлу

      Самый простой способ включить проверку типов в файле JavaScript — добавить // @ts-check в начало файла.

      Использование // @ts-check — хороший подход, если вы просто хотите попробовать проверку типов в нескольких файлах, но еще не включили ее для всей кодовой базы.

      Использование настройки

      Чтобы включить проверку типов для всех файлов JavaScript без изменения кода, просто добавьте "js/ts.implicitProjectConfig.checkJs": true в рабочую область или настройки пользователя. Это включает проверку типов для любого файла JavaScript, который не является частью проекта jsconfig.json или tsconfig.json.

      Вы можете отключить проверку типов для отдельных файлов с помощью комментария // @ts-nocheck в верхней части файла:

      Вы также можете отключить отдельные ошибки в файле JavaScript с помощью комментария // @ts-ignore в строке перед ошибкой:

      Использование jsconfig или tsconfig

      Чтобы включить проверку типов для файлов JavaScript, которые являются частью jsconfig.json или tsconfig.json , добавьте "checkJs": true в параметры компилятора проекта:

      Это включает проверку типов для всех файлов JavaScript в проекте. Вы можете использовать // @ts-nocheck, чтобы отключить проверку типов для каждого файла.

      Для проверки типов JavaScript требуется TypeScript 2.3. Если вы не уверены, какая версия TypeScript в данный момент активна в вашей рабочей области, запустите команду TypeScript: выберите версию TypeScript для проверки. Для выполнения этой команды у вас должен быть открыт файл .js/.ts в редакторе. Если вы откроете файл TypeScript, версия появится в правом нижнем углу.

      Глобальные переменные и проверка типов

      Допустим, вы работаете с устаревшим кодом JavaScript, в котором используются глобальные переменные или нестандартные API DOM:

      Если вы попытаетесь использовать // @ts-check с приведенным выше кодом, вы увидите ряд ошибок, связанных с использованием глобальных переменных:

      1. Строка 2. Свойство "webkitNotifications" не существует для типа "Window".
      2. Строка 2. Не удается найти имя «CAN_NOTIFY».
      3. Строка 3. Свойство "webkitNotifications" не существует для типа "Window".

      Если вы хотите и дальше использовать // @ts-check, но уверены, что это не реальные проблемы с вашим приложением, вы должны сообщить TypeScript об этих глобальных переменных.

      Для начала создайте файл jsconfig.json в корне вашего проекта:

      Затем перезагрузите VS Code, чтобы убедиться, что изменения применены. Наличие jsconfig.json позволяет TypeScript узнать, что ваши файлы Javascript являются частью более крупного проекта.

      Теперь создайте файл globals.d.ts где-нибудь в рабочей области:

      Файлы d.ts являются объявлениями типов. В этом случае globals.d.ts позволяет TypeScript узнать, что существует глобальный CAN_NOTIFY и что свойство webkitNotifications существует в окне. Подробнее о написании d.ts можно прочитать в документации по TypeScript. d.ts не меняют способ оценки JavaScript, они используются только для улучшения поддержки языка JavaScript.

      Использование задач

      Использование компилятора TypeScript

      Одной из ключевых особенностей TypeScript является возможность использовать новейшие функции языка JavaScript и создавать код, который может выполняться в средах выполнения JavaScript, которые еще не понимают эти новые функции. Теперь, когда JavaScript использует тот же языковой сервис, он также может использовать эту функцию.

      Компилятор TypeScript tsc может понизить уровень компиляции файлов JavaScript из ES6 до уровня другого языка. Настройте jsconfig.json с нужными параметрами, а затем используйте аргумент –p, чтобы заставить tsc использовать ваш файл jsconfig.json, например, tsc -p jsconfig.json для компиляции более низкого уровня.

      Подробнее о параметрах компилятора для компиляции нижнего уровня читайте в документации по jsconfig.

      Запуск Вавилона

      Транспилятор Babel преобразует файлы ES6 в удобочитаемый JavaScript ES5 с помощью исходных карт. Вы можете легко интегрировать Babel в свой рабочий процесс, добавив приведенную ниже конфигурацию в файл tasks.json (расположенный в папке .vscode рабочей области). Параметр группы делает эту задачу жестом по умолчанию Задача: Запустить задачу сборки. isBackground указывает VS Code продолжать выполнение этой задачи в фоновом режиме. Чтобы узнать больше, перейдите в раздел "Задачи".

      После того, как вы добавили это, вы можете запустить Babel с помощью команды ⇧⌘B (Windows, Linux Ctrl+Shift+B ) (Запустить задачу сборки), и она скомпилирует все файлы из каталога src в каталог lib.< /p>

      Совет. Для получения справки по Babel CLI см. инструкции в разделе Использование Babel. В приведенном выше примере используется параметр CLI.

      Отключить поддержку JavaScript

      Если вы предпочитаете использовать функции языка JavaScript, поддерживаемые другими инструментами языка JavaScript, такими как Flow, вы можете отключить встроенную поддержку JavaScript в VS Code. Для этого отключите встроенное расширение языка TypeScript TypeScript и функции языка JavaScript (vscode.typescript-language-features), которое также обеспечивает поддержку языка JavaScript.

      Чтобы отключить поддержку JavaScript/TypeScript, перейдите в представление «Расширения» ( ⇧⌘X (Windows, Linux Ctrl+Shift+X )) и отфильтруйте встроенные расширения («Показать встроенные расширения» в раскрывающемся списке «Дополнительные действия»). , затем введите «машинопись». Выберите расширение «Возможности языка TypeScript и JavaScript» и нажмите кнопку «Отключить». Встроенные расширения VS Code нельзя удалить, их можно только отключить, и их можно снова включить в любое время.

      Частичный режим IntelliSense

      VS Code пытается предоставить IntelliSense для всего проекта для JavaScript и TypeScript, что делает возможными такие функции, как автоматический импорт и переход к определению. Однако в некоторых случаях VS Code может работать только с открытыми в данный момент файлами и не может загружать другие файлы, из которых состоит ваш проект JavaScript или TypeScript.

      Это может произойти в нескольких случаях:

      • Вы работаете с кодом JavaScript или TypeScript на vscode.dev или github.dev, а VS Code запущен в браузере.
      • Вы открываете файл из виртуальной файловой системы (например, при использовании расширения GitHub Repositories).
      • Проект загружается. После завершения загрузки вы начнете получать IntelliSense для всего проекта.

      В этих случаях IntelliSense VS Code будет работать в частичном режиме. Частичный режим делает все возможное, чтобы предоставить IntelliSense для любых открытых файлов JavaScript или TypeScript, но он ограничен и не может предлагать какие-либо функции IntelliSense для нескольких файлов.

      Какие функции затронуты?

      Вот неполный список функций, которые либо отключены, либо имеют более ограниченную функциональность в частичном режиме:

      • Все открытые файлы рассматриваются как часть одного проекта.
      • Параметры конфигурации из вашего jsconfig или tsconfig (например, target ) не учитываются.
      • Сообщается только о синтаксических ошибках. О семантических ошибках, таких как доступ к неизвестному свойству или передача функции неправильного типа, не сообщается.
      • Быстрые исправления семантических ошибок отключены.
      • Символы могут быть разрешены только в текущем файле. Любые символы, импортированные из других файлов, будут считаться символами любого типа.
      • Такие команды, как «Перейти к определению» и «Найти все ссылки», будут работать только для открытых файлов, а не для всего проекта. Это также означает, что символы из любых пакетов, которые вы устанавливаете в node_module, не будут разрешены.
      • Поиск символов в рабочей области будет включать символы только из открытых в данный момент файлов.
      • Автоматический импорт отключен.
      • Переименование отключено.
      • Многие рефакторинги отключены.

      Некоторые дополнительные функции отключены на vscode.dev и github.dev:

      Проверка, не находитесь ли вы в частичном режиме

      Чтобы проверить, использует ли текущий файл IntelliSense частичного режима вместо IntelliSense для всего проекта, наведите указатель мыши на элемент состояния языка JavaScript или TypeScript в строке состояния:

      Элемент состояния будет показывать Частичный режим, если текущий файл находится в частичном режиме.

      Читайте также: