ImportJS é uma ferramenta para importar automaticamente dependências em seu projeto JavaScript. Use-o junto com uma de nossas integrações de editor para Atom, Emacs, Sublime, Vim ou VS Code.
Existem plug-ins ImportJS para os seguintes editores:
Instruções detalhadas sobre como instalar o ImportJS podem ser encontradas nos links do editor acima.
Quer adicionar outro editor à lista? Veja como contribuir.
ImportJS usa Babel 7 da versão 3.1.0. Na maioria dos casos, o Babel 7 é compatível com versões anteriores do Babel 6, mas se você tiver problemas (como este sobre decoradores), considere instalar uma versão anterior do ImportJS (por exemplo, 3.0.0) ou atualizar seu projeto para o Babel 7. compatível.
Digamos que você tenha um projeto JavaScript com a seguinte estrutura:
.
|-- index.html
|-- components
| |-- button.js
| |-- icon.js
|-- vendor
| |--
|-- pages
| |-- index.js
Agora, imagine que você está editando pages/index.js
que contém:
document . createElement ( new Button ( { text : 'Save' } ) . toDOMElement ( ) ) ;
Neste ponto, Button
está indefinido, então precisamos importá-lo. Se você está acostumado a fazer isso manualmente, isso envolve descobrir o caminho para o módulo JavaScript que define Button
. Com ImportJS, você coloca o cursor na palavra "Botão" e pressiona <leader>j
(Vim), (Mx) import-js-import
(Emacs) ou escolhe "ImportJS: import word under cursor" (Sublime). O buffer do arquivo agora mudará para o seguinte:
import Button from '../components/button' ;
document . createElement ( new Button ( { text : 'Save' } ) . toDOMElement ( ) ) ;
É basicamente isso. ImportJS irá ajudá-lo a encontrar módulos e adicionar automaticamente instruções import
. Mas continue lendo para obter recursos mais interessantes.
ImportJS pode ser usado para corrigir automaticamente todas as importações no arquivo atual. Ao clicar em <leader>i
(Vim), (Mx) import-js-fix
(Emacs) ou escolher ImportJS: fix all imports
(Sublime), todas as suas variáveis indefinidas serão resolvidas e todas as suas importações não utilizadas serão removidas.
Se você estiver usando JSX, o ImportJS não importará mais React
automaticamente para você. Se isso for algo que você precisa, considere usar ImportJS versão 5.1.0 ou anterior. A necessidade de importações do React para usar JSX foi removida no React 17. Leia mais aqui
Como ImportJS é muito bom em encontrar módulos JS, faz sentido que haja uma opção para abrir/ir para um arquivo em vez de importá-lo. Isso é semelhante ao "Abrir arquivo sob o cursor" integrado do Vim. Use-o colocando o cursor em uma variável e pressione <leader>g
(Vim), (Mx) import-js-goto
(Emacs), ou escolha "ImportJS: goto module" (Sublime).
.js*
e .ts*
são considerados na importaçãogroupImports
e sortImports
. Comentários e espaços em branco serão preservados se ambos estiverem desativados. ImportJS é configurado através de um arquivo JavaScript ( .importjs.js
).
O arquivo precisa exportar um único objeto contendo suas configurações, como no exemplo abaixo.
module . exports = {
excludes : [ './react-components/**/test/**' ] ,
// continue with the rest of your settings...
} ;
Salve este arquivo na pasta raiz do seu projeto (por exemplo, onde o arquivo package.json se encontra). Você também pode salvá-lo no diretório inicial do usuário se quiser compartilhar uma configuração global entre diferentes projetos.
As seguintes opções de configuração são suportadas.
aliases
danglingCommas
declarationKeyword
emptyLineBetweenGroups
environments
excludes
globals
groupImports
ignorePackagePrefixes
importDevDependencies
importFunction
importStatementFormatter
logLevel
maxLineLength
mergableOptions
minimumVersion
moduleNameFormatter
namedExports
parserPlugins
sortImports
stripFileExtensions
tab
useRelativePaths
aliases
Alguns nomes de variáveis podem não ser facilmente mapeados para um arquivo no sistema de arquivos. Para esses, você pode adicioná-los à configuração aliases
.
aliases: {
$ : 'third-party-libs/jquery' ,
_ : 'third-party-libs/underscore' ,
}
danglingCommas
Por padrão, ImportJS adicionará vírgulas finais ao construir instruções de importação com múltiplas importações nomeadas.
Você pode desativar esse comportamento definindo danglingCommas
como false
.
danglingCommas: false ;
declarationKeyword
O valor padrão para esta propriedade é import
, fazendo com que suas instruções de importação usem a sintaxe dos módulos ES2015:
import Foo from 'foo' ;
Os aliases podem ser tornados dinâmicos usando a string {filename}
. Esta parte do alias será substituída pelo nome do arquivo que você está editando no momento.
por exemplo
aliases: {
styles : './{filename}.scss' ,
}
irá para um arquivo foo/bar.js
resultar em
import styles from './bar.scss' ;
emptyLineBetweenGroups
Por padrão, ImportJS irá inserir uma linha vazia entre os grupos de importação.
Você pode desativar esse comportamento definindo emptyLineBetweenGroups
como false
.
emptyLineBetweenGroups: false ;
environments
Esta lista de ambientes controla quais módulos principais estão disponíveis durante a importação e quais variáveis são consideradas globais por padrão. Os valores suportados no momento são
['meteor']
- disponibiliza os módulos principais do Meteor e adiciona vários meteoros globais['node']
- disponibiliza todos os módulos principais do Node e adiciona vários nós globais['browser']
- adicione vários navegadores globais['jasmine']
- adicione um monte de jasmim globais['jest']
- adicione um monte de piadas globaisenvironments: [ 'meteor' , 'node' ] ;
excludes
Defina uma lista de padrões glob que correspondam a arquivos e diretórios que você não deseja incluir para importação.
excludes: [ './react-components/**/test/**' ] ;
globals
Forneça uma lista de identificadores globais usados no código. ImportJS irá ignorá-los ao tentar importar todas as variáveis indefinidas.
Nota: Se você usar a opção de configuração environments
corretamente, talvez não seja necessário especificar globals .
groupImports
Por padrão, ImportJS colocará as importações em grupos:
Você pode desativar esse comportamento definindo groupImports
como false
. Quando desabilitada, as importações são listadas em ordem alfabética em uma lista.
groupImports: false ;
ignorePackagePrefixes
Se você tiver dependências de pacote especificadas em package.json
que são prefixadas, por exemplo, com o nome de uma organização, mas deseja poder importá-las sem o prefixo do pacote, você pode definir a opção de configuração ignorePackagePrefixes
.
ignorePackagePrefixes: [ 'my-company-' ] ;
Quando as dependências do pacote forem correspondidas, esses prefixos serão ignorados. Por exemplo, uma variável chamada validator
corresponderia a um pacote chamado my-company-validator
.
importDevDependencies
ImportJS procurará dependências de pacote listadas em package.json
durante a importação. Por padrão, apenas os módulos listados em dependencies
e peerDependencies
serão usados. Ao definir importDevDependencies
como true
, devDependencies
também será levado em consideração.
importDevDependencies: true ;
importFunction
Nota: isso se aplica apenas se você estiver usando var
ou const
como declarationKeyword
.
O valor padrão para esta opção de configuração é "require"
, que é o nome da função CommonJS padrão usado para importação.
importFunction: 'myCustomRequireFunction' ;
importStatementFormatter
Use uma função aqui para controlar a aparência da instrução de importação resultante. Isso é útil se você, por exemplo, deseja remover os pontos e vírgulas finais (que o ImportJS adiciona por padrão).
Nota: este método só deve ser usado em casos raros. Há uma chance de que o ImportJS não consiga reconhecer a instrução de importação resultante na próxima vez que estiver prestes a importar algo.
importStatementFormatter ( { importStatement } ) {
return importStatement . replace ( / ;$ / , '' ) ;
} ,
logLevel
Um de ["debug", "info", "warn", "error"]
. Isso controla o que termina no arquivo de log. O padrão é info
.
logLevel: 'debug' ;
O arquivo de log é gravado em "importjs.log" no diretório padrão do seu sistema operacional para arquivos temporários. Você pode obter o caminho para o arquivo de log executando importjs logpath
.
maxLineLength
O padrão é 80
. Essa configuração controla quando as instruções de importação são divididas em diversas linhas.
maxLineLength: 70 ;
mergableOptions
Um dicionário de opções que pode ser mesclado com padrões e valores fornecidos por um environment
. Isso pode ser usado para substituir opções fornecidas pelos ambientes. O padrão é:
mergableOptions: {
aliases : true ,
coreModules : true ,
namedExports : true ,
globals : true ,
}
Nota: a opção mergableOptions
sempre será mesclada e será ignorada se incluída na configuração do usuário.
Para desabilitar a mesclagem de uma opção específica ou conjunto de opções, defina a chave como false
:
mergableOptions: {
globals: false ;
}
Por exemplo, se você estiver usando o ambiente meteor
, mas quiser importar explicitamente módulos fornecidos como globais, poderá usar esta configuração para substituir os globais do ambiente.
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
Definir minimumVersion
avisará as pessoas que estão executando uma versão do ImportJS mais antiga do que o exigido pelo arquivo de configuração .importjs.js
. Se a versão do seu plugin for anterior a esse valor, você receberá um aviso que o incentiva a atualizar o seu plugin.
minimumVersion: '1.0.0' ;
moduleNameFormatter
Use uma função aqui para controlar a aparência da string de nome do módulo resultante. É útil se você, por exemplo, quiser adicionar um prefixo personalizado a determinadas importações. Além dos valores padrão pathToCurrentFile
e pathToImportedModule
passados para todas as funções de configuração, esse método também recebe um valor moduleName
, que em geral é o que você deseja manipular.
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
*Nota: Desde a versão 2.1.0, o ImportJS encontra suas exportações nomeadas automaticamente. Provavelmente você não precisa dessa opção. Se você tiver que usar essa configuração de qualquer maneira, pode haver um bug nas partes de localização de exportações do ImportJS. Registre um problema e conte-nos sobre ele!
Se você tiver um módulo ES6/ES2015 que exporta várias coisas (denominadas exportações) ou um módulo CommonJS que exporta um objeto com propriedades que deseja desestruturar ao importar, você pode adicioná-las a uma opção de configuração namedExports
.
namedExports: {
underscore : [
'omit' ,
'debounce' ,
'memoize'
] ,
'lib/utils' : [
'escape' ,
'hasKey' ,
] ,
}
As importações que usam a palavra-chave de declaração import
usam a sintaxe de importações nomeadas. por exemplo
import { memoize } from 'underscore' ;
memoize ( ( ) => {
foo ( ) ;
} ) ;
e importações que usam const
ou var
usam [ES2015 Destructuring Assigment][destruindo atribuição], por exemplo
const { memoize } = require ( 'underscore' ) ;
memoize ( ( ) => {
foo ( ) ;
} ) ;
A chave usada para descrever as exportações nomeadas deve ser um caminho de importação válido. Pode ser, por exemplo, o nome de um pacote encontrado em node_modules
, um caminho para um módulo que você mesmo criou ou um caminho de importação relativo.
Considere o exemplo como um caso de uso válido para a namedExports
. Digamos que temos um arquivo:
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' ) ,
) ;
E vamos importar BrowserRouter
, mas em vez do resultado desejado, obtemos o módulo No JS para importar para a mensagem BrowserRouter
. Para corrigir o problema, namedExports
em seu arquivo de configuração da seguinte forma:
namedExports: {
'react-router-dom' : [ 'BrowserRouter' , 'Route' , 'Redirect' ]
}
Depois disso, podemos importar BrowserRouter
corretamente. A instrução de importação resultante ficará assim:
import { BrowserRouter } from 'react-router-dom'
Se você ainda não está pronto para o ES2015, você tem a opção de usar var
ou const
.
declarationKeyword: 'const' ;
Nesse caso, suas instruções de importação serão mais ou menos assim:
var Foo = require ( 'foo' ) ; // "declarationKeyword": "var"
const Foo = require ( 'foo' ) ; // "declarationKeyword": "const"
parserPlugins
O padrão do ImportJS é um compromisso razoável para qual sintaxe suportar, mas pode ser substituído (substituído) na configuração. Os padrões mais recentes podem ser encontrados aqui
Os plug-ins disponíveis estão em Babel: Lista de plug-ins
parserPlugins: [ ]
hack
) Quando parserPlugins
é especificado, você precisa adicionar novamente os padrões.
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
Por padrão, ImportJS classificará as importações pelo nome ou caminho do módulo importado.
Você pode desativar esse comportamento definindo sortImports
como false
. Quando desativado, as importações existentes não são reorganizadas e as novas importações são sempre adicionadas acima das importações existentes.
sortImports: false ;
stripFileExtensions
Uma matriz que controla quais extensões de arquivo são removidas da instrução de importação resultante. A configuração padrão remove [".js", ".jsx", ".ts", ".tsx"]
. Defina como uma matriz vazia []
para evitar a remoção de extensões.
stripFileExtensions: [ '.web.js' , '.js' ] ;
tab
O padrão é dois espaços ( " "
). Essa configuração controla como o recuo é construído quando as instruções de importação são divididas em diversas linhas.
tab: 't' ;
useRelativePaths
Esta opção está habilitada por padrão. Quando ativado, as importações serão resolvidas em relação ao arquivo atual que está sendo editado.
import Foo from './foo' ;
import Bar from '../baz/bar' ;
Você pode desativar isso definindo-o como falso:
useRelativePaths: false ;
As dependências do pacote (localizadas em node_modules
) não serão importadas relativamente.
Diferentes seções do seu aplicativo podem ter necessidades especiais de importação. Por exemplo, seus testes podem precisar da palavra-chave de declaração 'const'
, mas o restante do seu aplicativo pode usar 'import'
. Para poder direcionar esses casos especiais, você pode transformar sua opção de configuração em uma função. Quando ImportJS resolve uma opção de configuração, ele verifica se uma função é usada. Nesse caso, a função é invocada com os seguintes argumentos:
pathToCurrentFile
: (sempre disponível) Um caminho para o arquivo que você está editando.pathToImportedModule
(não disponível para algumas opções) Um caminho para o arquivo/módulo que você está importando. Aqui está um exemplo de como controlar dinamicamente a opção de configuração declarationKeyword
com base no arquivo que você está importando:
// .importjs.js
function isTestFile ( path ) {
return path . endsWith ( '-test.js' ) ;
}
module . exports = {
declarationKeyword ( { pathToImportedModule } ) {
if ( isTestFile ( pathToImportedModule ) ) {
return 'const' ;
}
return 'import' ;
} ,
} ;
Aqui está um exemplo mais elaborado levando em consideração pathToImportedModule
e pathToCurrentFile
:
module . exports = {
useRelativePaths ( { pathToImportedModule , pathToCurrentFile } ) {
if ( pathToCurrentFile . endsWith ( '-mock.js' ) ) {
return false ;
}
if ( pathToImportedModule . endsWith ( '-test.js' ) ) {
return false ;
}
return true ;
} ,
} ;
Para usar funções, você precisa usar o arquivo de configuração JavaScript ( .importjs.js
).
ImportJS vem com uma ferramenta útil de linha de comando que pode ajudá-lo a realizar importações fora de um editor. Nos bastidores, é isso que a maioria das integrações do editor usa.
⨠ 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
Se quiser alterar a forma como as importações são construídas em um projeto existente, você pode usar a ferramenta de linha de comando em combinação com find
para atualizar em lote um conjunto de arquivos. Por exemplo
find ./app -name " **.js* " -exec importjs rewrite --overwrite {} ;
Como o sinalizador --overwrite
torna o ImportJS destrutivo (os arquivos são sobrescritos), é bom verificar novamente se o comando find
retorna os arquivos corretos antes de adicionar a parte -exec
.
ImportJS procura o arquivo package.json
no diretório ancestral mais próximo do arquivo que você está editando para encontrar módulos de nó para importar. No entanto, às vezes pode extrair dependências de um diretório mais acima na cadeia. Por exemplo, sua estrutura de diretórios pode ser assim:
.
|-- package.json
|-- components
| |-- button.js
| |-- icon.js
|-- node_modules
| |-- react
|-- subpackage
| |-- package.json
| |-- components
| |-- bulletin.js
Se você usasse ImportJS em subpackage/components/bulletin.js
que importa React, ImportJS não saberia que react
é uma dependência válida.
Para dizer ao ImportJS para pular um diretório e continuar pesquisando para encontrar o diretório raiz do pacote, especifique "importjs": { "isRoot": false }
no package.json
do diretório a ser ignorado. Nesse caso, você gostaria de algo assim:
{
"name" : " subpackage " ,
...
"importjs" : {
"isRoot" : false
}
}
Nota : Esta seção é destinada principalmente a desenvolvedores de plug-ins de editor. Se você estiver usando um dos plug-ins de editor padrão, provavelmente já está usando o daemon interno.
Você pode executar ImportJS em um processo em segundo plano e comunicar-se com ele usando stdin
e stdout
. Isso tornará a importação mais rápida porque não criaremos um ambiente de nó a cada chamada.
O daemon é iniciado executando importjs
. Aceita comandos enviados via stdin
. Cada comando é uma string JSON (oneline) terminando com uma nova linha. A estrutura de comando é basicamente a mesma da ferramenta de linha de comando, mas agrupada em JSON em vez de expressa na linha de comando. Aqui estão alguns exemplos:
Execute fix imports
:
{
"command" : " fix " ,
"fileContent" : " const foo = bar(); n " ,
"pathToFile" : " foo.js "
}
Importe uma única palavra:
{
"command" : " word " ,
"commandArg" : " bar " ,
"fileContent" : " const foo = bar(); n " ,
"pathToFile" : " foo.js "
}
Vá para:
{
"command" : " goto " ,
"commandArg" : " bar " ,
"fileContent" : " const foo = bar(); n " ,
"pathToFile" : " foo.js "
}
Os resultados são impressos em stdout
no formato JSON. A resposta será igual à produzida pela ferramenta de linha de comando. Se ocorrer um erro, ele também terminará em stdout
como JSON (um objeto com uma chave error
).
Na inicialização, o daemon imprimirá um caminho para um arquivo de log. Se quiser descobrir o que está acontecendo nos bastidores, você pode inspecionar este arquivo. Se você não tiver acesso ao log do console do daemon, você encontrará o arquivo de log em os.tmpdir() + '/importjs.log
(que resolverá algo como var/folders/1l/_t6tm7195nd53936tsvh2pcr0000gn/T/importjs.log
em um Mac).
Se você tiver um aplicativo grande, percorrer o sistema de arquivos para localizar módulos pode ser lento. É por isso que o ImportJS possui integração integrada com o Watchman, um serviço rápido e robusto de observação de arquivos desenvolvido pelo Facebook. Tudo o que você precisa fazer para obter um aumento de desempenho é instalar o watchman localmente e certificar-se de usar um plugin de editor atualizado (o Watchman é usado apenas quando o ImportJS é executado como um daemon).
Consulte o documento CONTRIBUTING.md para dicas sobre como executar, testar e desenvolver ImportJS localmente.
Feliz hacking!