Skip to content

Commit

Permalink
Merge pull request #287 from Galooshi/faster-find
Browse files Browse the repository at this point in the history
Faster find
  • Loading branch information
trotzig authored Jun 30, 2016
2 parents aa73e41 + a803e9c commit c9ddf7a
Show file tree
Hide file tree
Showing 20 changed files with 918 additions and 267 deletions.
5 changes: 5 additions & 0 deletions .importjs.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
"environments": ["node"],
"ignorePackagePrefixes": ["lodash."],
"logLevel": "debug",
"excludes": [
"./build/**",
"./lib/__mocks__/**"
Expand All @@ -10,5 +11,9 @@
{
"appliesTo": "lib/__tests__/**",
"importDevDependencies": true
},
{
"appliesTo": "lib/benchmark.js",
"importDevDependencies": true
}
]
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ Using Jest CLI v11.0.2, jasmine2, babel-jest
285 tests passed (285 total in 7 test suites, run time 29.123s)
```

## Testing the daemon

This is how you can test the `importjsd` daemon from the command line.

```sh
mkfifo IMPORTJS
importjsd < IMPORTJS
```

The `importjs` process will now listen to `stdin` from the named pipe
(`"IMPORTJS"`). You can print to it using echo:

```sh
echo '{"fileContent": "...", "pathToFile": "foo.js", "command": "fix"}' > IMPORTJS
```

## Publishing

First ensure that your master is up to date:
Expand Down
83 changes: 83 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ the cursor on a variable and hit `<leader>g` (Vim), `(M-x) import-js-goto`
- As part of resolving imports, all imports will be sorted and placed into
groups. *Grouping can be disabled, see the `groupImports` configuration
option.*
- You can speed up importing by installing
(Watchman)[https://facebook.github.io/watchman/]. See [Speeding it
up!](#speeding-it-up) for more information.

## Configuration

Expand All @@ -117,6 +120,7 @@ configure ImportJS. The following configuration options can be used.
- [`minimumVersion`](#minimumversion)
- [`maxLineLength`](#maxlinelength)
- [`tab`](#tab)
- [`logLevel`](#loglevel)

### `lookupPaths`

Expand Down Expand Up @@ -380,6 +384,19 @@ constructed when import statements are broken into multiple lines.
"tab": "\t"
```

### `logLevel`

One of `["debug", "info", "warn", "error"]`. This controls what ends up in the
logfile (mostly used when [ImportJS is run as a daemon
process](#running-as-a-daemon). The default is `info`.

```json
"logLevel": "debug"
```

*Tip:* Don't put `node_modules` here. ImportJS will find your Node dependencies
through your `package.json` file.

## Local configuration

You can dynamically apply configuration to different directory trees within your
Expand Down Expand Up @@ -477,6 +494,72 @@ Since the `--overwrite` flag makes ImportJS destructive (files are overwritten),
it's a good thing to double-check that the `find` command returns the right
files before adding the `-exec` part.

## Running as a daemon

*Note*: This section is intended mostly for developers of editor plugins. If
you are using one of the standard editor plugins, you are most likely using the
daemon under the hood already.

You can run ImportJS in a background process and communicate with it using
`stdin` and `stdout`. This will make importing faster because we're not
spinning up a node environment on every invocation.

The daemon is started by running running `importjsd`. It accepts commands sent
via `stdin`. Each command is a (oneline) JSON string ending with a newline. The
command structure is basically the same as for the command-line tool, but
wrapped in JSON instead of expressed on the command line. Here are a few
examples:

Run `fix imports`:
```json
{
"command": "fix",
"fileContent": "const foo = bar();\n",
"pathToFile": "foo.js",
}
```

Import a single word:
```json
{
"command": "word",
"commandArg": "bar",
"fileContent": "const foo = bar();\n",
"pathToFile": "foo.js",
}
```

Goto:
```json
{
"command": "goto",
"commandArg": "bar",
"fileContent": "const foo = bar();\n",
"pathToFile": "foo.js",
}
```

Results are printed to `stdout` in JSON format. The response will look the same
as what the command-line tool produces. If an error occurs, it will also end up
in `stdout` as JSON (an object with an `error` key).

On startup, the daemon will print a path to a logfile. If you want to find out
what's going on behind the scenes, you can inspect this file. If you don't have
access to the console log of the daemon, you'll find the logfile in
`os.tmpdir() + '/importjs.log` (which will resolve to something like
`var/folders/1l/_t6tm7195nd53936tsvh2pcr0000gn/T/importjs.log` on a Mac).

## Speeding it up!

If you have a large application, traversing the file system to find modules can
be slow. That's why ImportJS has built-in integration with
[Watchman](https://facebook.github.io/watchman/), a fast and robust file
watching service developed by Facebook. All you have to do to get a performance
boost is to [install watchman
locally](https://facebook.github.io/watchman/docs/install.html), and make sure
to use an up-to-date editor plugin (Watchman is only used when ImportJS is run
as a daemon).

## Contributing

See the [CONTRIBUTING.md](CONTRIBUTING.md) document for tips on how to run, test
Expand Down
21 changes: 2 additions & 19 deletions bin/importjs.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,4 @@
#!/usr/bin/env node

/* eslint-disable strict */

'use strict';

// This is hacky, but necessary to make eslint find plugins local to the files
// being linted. Without it, you'll get an error message of the following kind:
//
// Error: Cannot find module 'eslint-config-brigade'
//
// This is because eslint will look for modules relative to where it installed.
// The eslint we are using is local to import-js, so any plugin referenced for
// the file we are linting will have to be looked up relative to that file.
//
// Technique from http://stackoverflow.com/questions/11969175
const oldPath = process.env.NODE_PATH;
process.env.NODE_PATH = `${oldPath || ''}:${process.cwd()}/node_modules/`;
require('module').Module._initPaths(); // eslint-disable-line no-underscore-dangle

require('../build/importjs.js');
require('../build/fix-node-path');
require('../build/importjs.js')(process.argv);
4 changes: 4 additions & 0 deletions bin/importjsd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env node

require('../build/fix-node-path');
require('../build/daemon.js')();
18 changes: 5 additions & 13 deletions lib/Configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import path from 'path';

import escapeRegExp from 'lodash.escaperegexp';
import minimatch from 'minimatch';
import semver from 'semver';

import FileUtils from './FileUtils';
import JsModule from './JsModule';
import normalizePath from './normalizePath';
import requireResolve from './requireResolve';
import version from './version';

Expand All @@ -23,6 +23,7 @@ const DEFAULT_CONFIG = {
ignorePackagePrefixes: [],
importDevDependencies: false,
importFunction: 'require',
logLevel: 'info',
lookupPaths: ['.'],
maxLineLength: 80,
minimumVersion: '0.0.0',
Expand Down Expand Up @@ -105,6 +106,7 @@ const KNOWN_CONFIGURATION_OPTIONS = [
'ignorePackagePrefixes',
'importDevDependencies',
'importFunction',
'logLevel',
'lookupPaths',
'maxLineLength',
'minimumVersion',
Expand Down Expand Up @@ -146,17 +148,6 @@ function checkForUnknownConfiguration(config: Object): Array<string> {
return messages;
}

function normalizePath(rawPath: string): string {
if (!rawPath) {
return './';
}
const normalized = rawPath.replace(RegExp(`^${escapeRegExp(process.cwd())}`), '.');
if (normalized.startsWith('.')) {
return normalized;
}
return `./${normalized}`;
}

/**
* Checks that the current version is bigger than the `minimumVersion`
* defined in config.
Expand Down Expand Up @@ -248,7 +239,7 @@ export default class Configuration {
importPath = importPath.replace(/\{filename\}/,
path.basename(pathToCurrentFile, path.extname(pathToCurrentFile)));
}
return new JsModule({ importPath });
return new JsModule({ importPath, variableName });
}

resolveNamedExports(variableName: string): ?JsModule {
Expand All @@ -266,6 +257,7 @@ export default class Configuration {
const jsModule = new JsModule({
importPath,
hasNamedExports: true,
variableName,
});
if (this.get('useRelativePaths', { fromFile: relativeFilePath }) &&
!relativeFilePath.startsWith('node_modules')) {
Expand Down
Loading

0 comments on commit c9ddf7a

Please sign in to comment.