ImportJS — это инструмент для автоматического импорта зависимостей в ваш проект JavaScript. Используйте его вместе с одной из наших интеграций редакторов для Atom, Emacs, Sublime, Vim или VS Code.
Существуют плагины ImportJS для следующих редакторов:
Подробные инструкции по установке ImportJS можно найти по ссылкам на редактор выше.
Хотите добавить в список еще один редактор? Посмотрите, как внести свой вклад.
ImportJS использует Babel 7 версии 3.1.0. В большинстве случаев Babel 7 обратно совместим с Babel 6, но если у вас возникнут проблемы (например, с декораторами), рассмотрите возможность установки предыдущей версии ImportJS (например, 3.0.0) или обновления вашего проекта до Babel 7. совместимый.
Допустим, у вас есть проект JavaScript со следующей структурой:
.
|-- index.html
|-- components
| |-- button.js
| |-- icon.js
|-- vendor
| |--
|-- pages
| |-- index.js
Теперь представьте, что вы редактируете pages/index.js
, который содержит:
document . createElement ( new Button ( { text : 'Save' } ) . toDOMElement ( ) ) ;
На данный момент Button
не определен, поэтому нам нужно его импортировать. Если вы привыкли делать это вручную, вам потребуется выяснить путь к модулю JavaScript, который определяет Button
. Вместо этого с помощью ImportJS вы помещаете курсор на слово «Кнопка», затем нажимаете <leader>j
(Vim), (Mx) import-js-import
(Emacs) или выбираете «ImportJS: импортировать слово под курсором» (Sublime). Буфер файла теперь изменится на следующее:
import Button from '../components/button' ;
document . createElement ( new Button ( { text : 'Save' } ) . toDOMElement ( ) ) ;
Вот и все. ImportJS поможет вам найти модули и автоматически добавить операторы import
. Но продолжайте читать, чтобы узнать о более интересных функциях.
ImportJS можно использовать для автоматического исправления всего импорта в текущем файле. Нажав <leader>i
(Vim), (Mx) import-js-fix
(Emacs) или выбрав ImportJS: fix all imports
(Sublime), все ваши неопределенные переменные будут разрешены, а все неиспользуемые импорты будут удалены.
Если вы используете JSX, ImportJS больше не будет автоматически импортировать React
за вас. Если это то, что вам нужно, рассмотрите возможность использования ImportJS версии 5.1.0 или более ранней. Необходимость импорта React для использования JSX была удалена в React 17. Подробнее здесь.
Поскольку ImportJS довольно хорошо находит модули JS, имеет смысл, что есть возможность открыть файл или перейти к нему, а не импортировать его. Это похоже на встроенную в Vim функцию «Открыть файл под курсором». Используйте его, поместив курсор на переменную и нажав <leader>g
(Vim), (Mx) import-js-goto
(Emacs) или выберите «ImportJS: goto modul» (Sublime).
.js*
и .ts*
groupImports
и sortImports
. Комментарии и пробелы будут сохранены, если они оба отключены. ImportJS настраивается через файл JavaScript ( .importjs.js
).
В файле необходимо экспортировать один объект, содержащий настройки конфигурации, как показано в примере ниже.
module . exports = {
excludes : [ './react-components/**/test/**' ] ,
// continue with the rest of your settings...
} ;
Сохраните этот файл в корневой папке вашего проекта (например, там, где находится файл package.json). Вы также можете сохранить его в домашнем каталоге пользователя, если хотите поделиться глобальной конфигурацией между разными проектами.
Поддерживаются следующие параметры конфигурации.
aliases
danglingCommas
declarationKeyword
emptyLineBetweenGroups
environments
excludes
globals
groupImports
ignorePackagePrefixes
importDevDependencies
importFunction
importStatementFormatter
logLevel
maxLineLength
mergableOptions
minimumVersion
moduleNameFormatter
namedExports
parserPlugins
sortImports
stripFileExtensions
tab
useRelativePaths
aliases
Некоторые имена переменных могут быть нелегко сопоставить с файлом в файловой системе. Для них вы можете добавить их в конфигурацию aliases
.
aliases: {
$ : 'third-party-libs/jquery' ,
_ : 'third-party-libs/underscore' ,
}
danglingCommas
По умолчанию ImportJS добавляет конечные запятые при создании операторов импорта с несколькими именованными импортами.
Вы можете отключить это поведение, установив для danglingCommas
значение false
.
danglingCommas: false ;
declarationKeyword
Значением по умолчанию для этого свойства является import
, благодаря чему ваши операторы импорта используют синтаксис модулей ES2015:
import Foo from 'foo' ;
Псевдонимы можно сделать динамическими, используя строку {filename}
. Эта часть псевдонима будет заменена именем файла, который вы сейчас редактируете.
например
aliases: {
styles : './{filename}.scss' ,
}
для файла foo/bar.js
результат будет
import styles from './bar.scss' ;
emptyLineBetweenGroups
По умолчанию ImportJS вставит пустую строку между группами импорта.
Вы можете отключить это поведение, установив для emptyLineBetweenGroups
значение false
.
emptyLineBetweenGroups: false ;
environments
Этот список сред определяет, какие основные модули доступны при импорте и какие переменные считаются глобальными по умолчанию. Поддерживаемые значения на данный момент:
['meteor']
- сделать доступными основные модули для Meteor и добавить несколько глобальных метеоров.['node']
— сделать доступными все основные модули Node и добавить несколько глобальных узлов узла.['browser']
— добавить несколько глобальных переменных браузера.['jasmine']
— добавить несколько глобальных элементов жасмина['jest']
- добавить кучу шутливых глобальных переменныхenvironments: [ 'meteor' , 'node' ] ;
excludes
Определите список шаблонов glob, соответствующих файлам и каталогам, которые вы не хотите включать в импорт.
excludes: [ './react-components/**/test/**' ] ;
globals
Предоставьте список глобальных идентификаторов, используемых в коде. ImportJS будет игнорировать их при попытке импортировать все неопределенные переменные.
Примечание. Если вы правильно используете параметр конфигурации environments
, вам, возможно, не потребуется указывать глобальные переменные .
groupImports
По умолчанию ImportJS распределяет импорт по группам:
Вы можете отключить это поведение, установив для параметра groupImports
значение false
. Если этот параметр отключен, импорт отображается в одном списке в алфавитном порядке.
groupImports: false ;
ignorePackagePrefixes
Если у вас есть зависимости пакета, указанные в package.json
, с префиксом, например, именем организации, но вы хотите иметь возможность импортировать их без префикса пакета, вы можете установить параметр конфигурации ignorePackagePrefixes
.
ignorePackagePrefixes: [ 'my-company-' ] ;
Если зависимости пакетов совпадают, эти префиксы будут игнорироваться. Например, переменная с именем validator
будет соответствовать пакету с именем my-company-validator
.
importDevDependencies
ImportJS при импорте будет искать зависимости пакета, перечисленные в package.json
. По умолчанию будут использоваться только модули, перечисленные в dependencies
и peerDependencies
. Если для importDevDependencies
установлено значение true
, devDependencies
также будут приняты во внимание.
importDevDependencies: true ;
importFunction
Примечание. Это применимо только в том случае, если вы используете var
или const
в качестве declarationKeyword
.
Значением по умолчанию для этого параметра конфигурации является "require"
— стандартное имя функции CommonJS, используемое для импорта.
importFunction: 'myCustomRequireFunction' ;
importStatementFormatter
Используйте здесь функцию, чтобы контролировать, как будет выглядеть результирующий оператор импорта. Это полезно, если вы, например, хотите удалить конечные точки с запятой (которые ImportJS добавляет по умолчанию).
Примечание: этот метод следует использовать только в редких случаях. Существует вероятность того, что ImportJS не сможет распознать полученный оператор импорта в следующий раз, когда он собирается что-то импортировать.
importStatementFormatter ( { importStatement } ) {
return importStatement . replace ( / ;$ / , '' ) ;
} ,
logLevel
Один из ["debug", "info", "warn", "error"]
. Это контролирует то, что попадает в файл журнала. По умолчанию используется info
.
logLevel: 'debug' ;
Файл журнала записывается в «importjs.log» в каталоге вашей операционной системы по умолчанию для временных файлов. Вы можете получить путь к файлу журнала, запустив importjs logpath
.
maxLineLength
По умолчанию 80
. Этот параметр контролирует, когда операторы импорта разбиваются на несколько строк.
maxLineLength: 70 ;
mergableOptions
Словарь параметров, которые можно объединить со значениями по умолчанию и значениями, предоставленными environment
. Это можно использовать для перезаписи параметров, предоставляемых средой. По умолчанию:
mergableOptions: {
aliases : true ,
coreModules : true ,
namedExports : true ,
globals : true ,
}
Примечание. Параметр mergableOptions
всегда будет объединен и будет игнорироваться, если он включен в конфигурацию пользователя.
Чтобы отключить объединение определенной опции или набора опций, установите для ключа значение false
:
mergableOptions: {
globals: false ;
}
Например, если вы используете среду meteor
, но хотите явно импортировать модули, которые предоставляются как глобальные переменные, вы можете использовать этот параметр для перезаписи глобальных переменных среды.
const globals = require ( 'globals' ) ;
module . exports = {
environments : [ 'meteor' , 'node' ] ,
mergableOptions : {
globals : false , // Overwrite globals
} ,
globals : [
// Add the globals you want back in
... Object . keys ( globals . builtin ) , // include javascript builtins
... Object . keys ( globals . node ) , // include node globals
'Package' ,
'Npm' , // Include meteor globals for `package.js` files
] ,
} ;
minimumVersion
Установка minimumVersion
будет предупреждать людей, которые используют версию ImportJS, более старую, чем требуется для вашего файла конфигурации .importjs.js
. Если версия вашего плагина старше этого значения, вам будет показано предупреждение, предлагающее обновить плагин.
minimumVersion: '1.0.0' ;
moduleNameFormatter
Используйте здесь функцию, чтобы контролировать, как будет выглядеть результирующая строка имени модуля. Это полезно, если вы, например, хотите добавить собственный префикс к определенному импорту. Помимо стандартных значений pathToCurrentFile
и pathToImportedModule
передаваемых во все функции конфигурации, этому методу также передается значение moduleName
, которым обычно и нужно манипулировать.
moduleNameFormatter ( { moduleName , pathToCurrentFile } ) {
if ( / -test / . test ( pathToCurrentFile ) ) {
// Import a mocked version in test files
return `mocks/ ${ moduleName } ` ;
}
if ( moduleName . startsWith ( 'foo' ) ) {
// Add a leading slash to foo imports
return `/ ${ moduleName } ` ;
}
// Fall back to the original specifier. It's important that this function
// always returns a string.
return moduleName ;
} ,
namedExports
*Примечание. Начиная с версии 2.1.0, ImportJS автоматически находит именованный экспорт. Скорее всего вам эта опция не нужна. Если вам все равно придется использовать эту конфигурацию, возможно, в частях ImportJS, занимающихся поиском экспорта, может быть ошибка. Напишите о проблеме и расскажите нам о ней!
Если у вас есть модуль ES6/ES2015, который экспортирует несколько объектов (именованный экспорт), или модуль CommonJS, который экспортирует объект со свойствами, которые вы хотите деструктурировать при импорте, вы можете добавить их в параметр конфигурации namedExports
.
namedExports: {
underscore : [
'omit' ,
'debounce' ,
'memoize'
] ,
'lib/utils' : [
'escape' ,
'hasKey' ,
] ,
}
Импорты, использующие ключевое слово объявления import
, затем используют синтаксис именованных импортов. например
import { memoize } from 'underscore' ;
memoize ( ( ) => {
foo ( ) ;
} ) ;
и импорт, который использует const
или var
использует [ES2015 Destructuring Assignment] [destructuring Assignment], например
const { memoize } = require ( 'underscore' ) ;
memoize ( ( ) => {
foo ( ) ;
} ) ;
Ключ, используемый для описания именованного экспорта, должен быть допустимым путем импорта. Это может быть, например, имя пакета, найденное в node_modules
, путь к модулю, который вы создали самостоятельно, или относительный путь импорта.
Рассматривайте этот пример как допустимый вариант использования namedExports
. Допустим, у нас есть файл:
import { Provider } from 'react-redux' ;
import React from 'react' ;
import store from './redux/redux-store' ;
import ReactDOM from 'react-dom' ;
import App from './App' ;
ReactDOM . render (
< BrowserRouter >
< Provider store = { store } >
< App / >
< / Provider >
< / BrowserRouter > ,
document . getElementById ( 'root' ) ,
) ;
И мы собираемся импортировать BrowserRouter
, но вместо желаемого результата мы получаем модуль No JS для импорта для сообщения BrowserRouter
. Чтобы решить проблему, заполните namedExports
в файле конфигурации следующим образом:
namedExports: {
'react-router-dom' : [ 'BrowserRouter' , 'Route' , 'Redirect' ]
}
После этого мы сможем правильно импортировать BrowserRouter
. Результирующий оператор импорта будет выглядеть следующим образом:
import { BrowserRouter } from 'react-router-dom'
Если вы еще не готовы к ES2015, у вас есть возможность использовать вместо этого var
или const
.
declarationKeyword: 'const' ;
В таком случае ваши операторы импорта будут выглядеть примерно так:
var Foo = require ( 'foo' ) ; // "declarationKeyword": "var"
const Foo = require ( 'foo' ) ; // "declarationKeyword": "const"
parserPlugins
ImportJS по умолчанию использует разумный компромисс в отношении поддерживаемого синтаксиса, но его можно переопределить (заменить) в конфигурации. Последние настройки по умолчанию можно найти здесь
Доступные плагины можно найти на сайте Babel: Список плагинов.
parserPlugins: [ ]
hack
) Если указан parserPlugins
вам необходимо повторно добавить значения по умолчанию.
parserPlugins: [
'jsx' ,
'doExpressions' ,
'objectRestSpread' ,
'decorators-legacy' ,
'classProperties' ,
'classPrivateProperties' ,
'classPrivateMethods' ,
'exportExtensions' ,
'asyncGenerators' ,
'functionBind' ,
'functionSent' ,
'dynamicImport' ,
'numericSeparator' ,
'optionalChaining' ,
'importMeta' ,
'bigInt' ,
'optionalCatchBinding' ,
'throwExpressions' ,
'nullishCoalescingOperator' ,
'exportNamespaceFrom' ,
'exportDefaultFrom' ,
[
'pipelineOperator' ,
{
proposal : 'hack' ,
} ,
] ,
] ;
sortImports
По умолчанию ImportJS сортирует импорт по имени или пути к импортируемому модулю.
Вы можете отключить это поведение, установив для sortImports
значение false
. Если этот параметр отключен, существующий импорт не переупорядочивается, а новый импорт всегда добавляется поверх существующего импорта.
sortImports: false ;
stripFileExtensions
Массив, который контролирует, какие расширения файлов удаляются из результирующего оператора импорта. Конфигурация по умолчанию удаляет [".js", ".jsx", ".ts", ".tsx"]
. Установите пустой массив []
чтобы избежать удаления расширений.
stripFileExtensions: [ '.web.js' , '.js' ] ;
tab
По умолчанию два пробела ( " "
). Этот параметр управляет тем, как создаются отступы, когда операторы импорта разбиваются на несколько строк.
tab: 't' ;
useRelativePaths
Эта опция включена по умолчанию. Если этот параметр включен, импорт будет выполняться относительно текущего редактируемого файла.
import Foo from './foo' ;
import Bar from '../baz/bar' ;
Вы можете отключить это, установив для него значение false:
useRelativePaths: false ;
Зависимости пакета (расположенные в node_modules
) не будут импортированы относительно.
Различные разделы вашего приложения могут иметь особые потребности в импорте. Например, вашим тестам может потребоваться ключевое слово объявления 'const'
, но остальная часть вашего приложения может использовать 'import'
. Чтобы иметь возможность работать с этими особыми случаями, вы можете превратить параметр конфигурации в функцию. Когда ImportJS разрешает параметр конфигурации, он проверяет, используется ли функция. В таком случае функция вызывается со следующими аргументами:
pathToCurrentFile
: (всегда доступен) Путь к файлу, который вы редактируете.pathToImportedModule
(недоступно для некоторых параметров) Путь к файлу/модулю, который вы импортируете. Вот пример того, как динамически управлять параметром declarationKeyword
на основе импортируемого файла:
// .importjs.js
function isTestFile ( path ) {
return path . endsWith ( '-test.js' ) ;
}
module . exports = {
declarationKeyword ( { pathToImportedModule } ) {
if ( isTestFile ( pathToImportedModule ) ) {
return 'const' ;
}
return 'import' ;
} ,
} ;
Вот более подробный пример, учитывающий как pathToImportedModule
, так и pathToCurrentFile
:
module . exports = {
useRelativePaths ( { pathToImportedModule , pathToCurrentFile } ) {
if ( pathToCurrentFile . endsWith ( '-mock.js' ) ) {
return false ;
}
if ( pathToImportedModule . endsWith ( '-test.js' ) ) {
return false ;
}
return true ;
} ,
} ;
Чтобы использовать функции, вам необходимо использовать файл конфигурации JavaScript ( .importjs.js
).
ImportJS поставляется с удобным инструментом командной строки, который поможет вам выполнить импорт вне редактора. Под капотом это то, что использует большинство интеграций редактора.
⨠ importjs --help
Usage: importjs [options] [command]
Commands:
word [options] < word > < pathToFile >
search [options] < word > < pathToFile >
fix [options] < pathToFile >
rewrite [options] < pathToFile >
add [options] < imports > < pathToFile >
goto < word > < pathToFile >
start [options] start a daemon
cachepath show path to cache file
logpath show path to log file
Options:
-h, --help output usage information
-V, --version output the version number
Examples:
$ importjs word someModule path/to/file.js
$ importjs search someModule * path/to/file.js
$ importjs fix path/to/file.js
$ importjs rewrite --overwrite path/to/file.js
$ importjs add ' { "foo": "path/to/foo", "bar": "path/to/bar" } ' path/to/file.js
$ importjs goto someModule path/to/file.js
$ importjs cachepath
$ importjs logpath
$ importjs start --parent-pid=12345
Если вы хотите изменить способ импорта в существующем проекте, вы можете использовать инструмент командной строки в сочетании с find
для пакетного обновления набора файлов. Например
find ./app -name " **.js* " -exec importjs rewrite --overwrite {} ;
Поскольку флаг --overwrite
делает ImportJS деструктивным (файлы перезаписываются), полезно дважды проверить, что команда find
возвращает правильные файлы, прежде чем добавлять часть -exec
.
ImportJS ищет файл package.json
в ближайшем родительском каталоге для файла, который вы редактируете, чтобы найти модули узла для импорта. Однако иногда он может извлечь зависимости из каталога, расположенного дальше по цепочке. Например, ваша структура каталогов может выглядеть так:
.
|-- package.json
|-- components
| |-- button.js
| |-- icon.js
|-- node_modules
| |-- react
|-- subpackage
| |-- package.json
| |-- components
| |-- bulletin.js
Если бы вы использовали ImportJS для subpackage/components/bulletin.js
, который импортирует React, ImportJS не знал бы, что react
является допустимой зависимостью.
Чтобы указать ImportJS пропустить каталог и продолжить поиск вверх, чтобы найти корневой каталог пакета, укажите "importjs": { "isRoot": false }
в package.json
каталога, который нужно игнорировать. В этом случае вам нужно что-то вроде этого:
{
"name" : " subpackage " ,
...
"importjs" : {
"isRoot" : false
}
}
Примечание . Этот раздел предназначен в основном для разработчиков плагинов-редакторов. Если вы используете один из стандартных плагинов редактора, скорее всего, вы уже используете демон «под капотом».
Вы можете запустить ImportJS в фоновом процессе и взаимодействовать с ним, используя stdin
и stdout
. Это ускорит импорт, поскольку мы не запускаем среду узла при каждом вызове.
Демон запускается путем запуска importjs
. Он принимает команды, отправленные через stdin
. Каждая команда представляет собой (одну строку) строку JSON, заканчивающуюся новой строкой. Структура команды в основном такая же, как и для инструмента командной строки, но она заключена в JSON, а не выражается в командной строке. Вот несколько примеров:
Запустите fix imports
:
{
"command" : " fix " ,
"fileContent" : " const foo = bar(); n " ,
"pathToFile" : " foo.js "
}
Импортируйте одно слово:
{
"command" : " word " ,
"commandArg" : " bar " ,
"fileContent" : " const foo = bar(); n " ,
"pathToFile" : " foo.js "
}
Перейти:
{
"command" : " goto " ,
"commandArg" : " bar " ,
"fileContent" : " const foo = bar(); n " ,
"pathToFile" : " foo.js "
}
Результаты выводятся на stdout
в формате JSON. Ответ будет выглядеть так же, как и результат, полученный с помощью инструмента командной строки. Если возникает ошибка, она также попадает в stdout
в виде JSON (объект с ключом error
).
При запуске демон напечатает путь к файлу журнала. Если вы хотите узнать, что происходит за кулисами, вы можете просмотреть этот файл. Если у вас нет доступа к журналу консоли демона, вы найдете файл журнала в os.tmpdir() + '/importjs.log
(который преобразуется в что-то вроде var/folders/1l/_t6tm7195nd53936tsvh2pcr0000gn/T/importjs.log
на Mac).
Если у вас большое приложение, просмотр файловой системы в поисках модулей может быть медленным. Вот почему ImportJS имеет встроенную интеграцию с Watchman, быстрым и надежным сервисом просмотра файлов, разработанным Facebook. Все, что вам нужно сделать, чтобы получить прирост производительности, — это установить Watchman локально и обязательно использовать обновленный плагин редактора (Watchman используется только тогда, когда ImportJS запускается как демон).
См. документ CONTRIBUTING.md, где приведены советы о том, как запускать, тестировать и разрабатывать ImportJS локально.
Удачного взлома!