ImportJS 是一個在 JavaScript 專案中自動匯入相依性的工具。將其與我們針對 Atom、Emacs、Sublime、Vim 或 VS Code 的編輯器整合之一結合使用。
有適用於下列編輯器的 ImportJS 外掛程式:
有關如何安裝 ImportJS 的詳細說明可以在上面的編輯器連結中找到。
想要新增另一個編輯器到清單中嗎?了解如何做出貢獻。
ImportJS 使用 Babel 7 3.1.0 版本。 In most cases, Babel 7 is backwards-compatible with Babel 6, but if you run into issues (such as this one about decorators), consider installing a previous version of ImportJS (eg 3.0.0) or updating your project to be 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
尚未定義,因此我們需要導入它。如果您習慣於手動執行此操作,則需要確定定義Button
JavaScript 模組的路徑。使用 ImportJS,您可以將遊標放在單字「Button」上,然後點擊<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 17 中不再需要使用 React 導入來使用 JSX。
由於 ImportJS 非常擅長尋找 JS 模組,因此有一個開啟/轉到檔案而不是匯入檔案的選項是有意義的。這類似於 Vim 內建的「開啟遊標下的檔案」。透過將遊標放在變數上並點擊<leader>g
(Vim)、 (Mx) import-js-goto
(Emacs) 或選擇「ImportJS: goto module」(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
,使您的 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']
- 加入一堆 jasmine 全域變量['jest']
- 增加一堆笑話全域變量environments: [ 'meteor' , 'node' ] ;
excludes
定義與您不想包含在匯入中的檔案和目錄相符的全域模式清單。
excludes: [ './react-components/**/test/**' ] ;
globals
提供代碼中使用的全域標識符的清單。當嘗試匯入所有未定義的變數時,ImportJS 將忽略這些。
注意:如果正確使用environments
配置選項,則可能不需要指定 globals 。
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 解構賦值][解構賦值],例如
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 module to import for 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 具有破壞性(檔案已覆蓋),因此在新增-exec
部分之前仔細檢查find
命令是否返回正確的檔案是一件好事。
ImportJS 在最近的祖先目錄中尋找您正在編輯的文件的package.json
文件,以尋找要匯入的節點模組。但是,有時它可能會從鏈上更上游的目錄中提取依賴項。例如,您的目錄結構可能如下所示:
.
|-- package.json
|-- components
| |-- button.js
| |-- icon.js
|-- node_modules
| |-- react
|-- subpackage
| |-- package.json
| |-- components
| |-- bulletin.js
如果您要在導入 React 的subpackage/components/bulletin.js
上使用 ImportJS,ImportJS 將不知道react
是有效的依賴項。
要告訴 ImportJS 跳過某個目錄並繼續向上搜尋以尋找根包目錄,請在要忽略的目錄的package.json
中指定"importjs": { "isRoot": false }
。在這種情況下,你會想要這樣的東西:
{
"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 "
}
結果以 JSON 格式列印到stdout
。回應看起來與命令列工具產生的回應相同。如果發生錯誤,它也會以 JSON(帶有error
鍵的物件)的形式出現在stdout
中。
啟動時,守護程式將列印日誌檔案的路徑。如果您想了解幕後發生的事情,可以檢查此文件。如果您無法存取守護程式的控制台日誌,您將在os.tmpdir() + '/importjs.log
中找到日誌檔案(它將解析為類似var/folders/1l/_t6tm7195nd53936tsvh2pcr0000gn/T/importjs.log
)。
如果您有大型應用程序,則遍歷檔案系統來查找模組可能會很慢。這就是 ImportJS 與 Watchman 內建整合的原因,Watchman 是 Facebook 開發的快速且強大的檔案監視服務。要獲得效能提升,您所要做的就是在本機安裝 watchman,並確保使用最新的編輯器外掛程式(Watchman 僅在 ImportJS 作為守護程式運行時使用)。
有關如何在本機上運行、測試和開發 ImportJS 的提示,請參閱 CONTRIBUTING.md 文件。
快樂黑客!