Skip to content

Commit

Permalink
fix: recompile speedups (#55)
Browse files Browse the repository at this point in the history
* fix: don't use threads after intial build

* fix: flip threads default

* docs: move `threads` option

Co-authored-by: Ricardo Gobbo de Souza <ricardogobbosouza@yahoo.com.br>
  • Loading branch information
jsg2021 and ricardogobbosouza authored Nov 30, 2020
1 parent bdb5210 commit d862d92
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 8 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ Accepts a function that will have one argument: an array of eslint messages (obj

Lint only changed files, skip lint on start.

#### `threads`

- Type: `Boolean | Number`
- Default: `false`

Will run lint tasks across a thread pool. The pool size is automatic unless you specify a number.

### Errors and Warning

**By default the plugin will auto adjust error reporting depending on eslint errors/warnings counts.**
Expand Down
1 change: 1 addition & 0 deletions declarations/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export function parseFoldersToGlobs(
patterns: string | string[],
extensions?: string | string[]
): string[];
export function jsonStringifyReplacerSortKeys(_: string, value: any): any;
40 changes: 34 additions & 6 deletions src/getESLint.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import os from 'os';
import JestWorker from 'jest-worker';

import { getESLintOptions } from './options';
import { jsonStringifyReplacerSortKeys } from './utils';

/** @type {{[key: string]: any}} */
const cache = {};

/** @typedef {import('eslint').ESLint} ESLint */
/** @typedef {import('eslint').ESLint.LintResult} LintResult */
Expand Down Expand Up @@ -47,6 +51,7 @@ export function loadESLint(options) {
* @returns {Linter}
*/
export function loadESLintThreaded(poolSize, options) {
const key = getCacheKey(options);
const { eslintPath = 'eslint' } = options;
const source = require.resolve('./worker');
const workerOptions = {
Expand All @@ -57,18 +62,28 @@ export function loadESLintThreaded(poolSize, options) {

const local = loadESLint(options);

/** @type {Worker} */
/** @type {Worker?} */
// prettier-ignore
const worker = (/** @type {Worker} */ new JestWorker(source, workerOptions));
let worker = (/** @type {Worker} */ new JestWorker(source, workerOptions));

return {
/** @type {Linter} */
const context = {
...local,
threads: poolSize,
lintFiles: (files) => worker.lintFiles(files),
lintFiles: async (files) =>
(worker && (await worker.lintFiles(files))) ||
/* istanbul ignore next */ [],
cleanup: async () => {
worker.end();
cache[key] = local;
context.lintFiles = (files) => local.lintFiles(files);
if (worker) {
worker.end();
worker = null;
}
},
};

return context;
}

/**
Expand All @@ -84,5 +99,18 @@ export default function getESLint({ threads, ...options }) {
: /* istanbul ignore next */
threads;

return max > 1 ? loadESLintThreaded(max, options) : loadESLint(options);
const key = getCacheKey({ threads, ...options });
if (!cache[key]) {
cache[key] =
max > 1 ? loadESLintThreaded(max, options) : loadESLint(options);
}
return cache[key];
}

/**
* @param {Options} options
* @returns {string}
*/
function getCacheKey(options) {
return JSON.stringify(options, jsonStringifyReplacerSortKeys);
}
1 change: 0 additions & 1 deletion src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import schema from './options.json';
export function getOptions(pluginOptions) {
const options = {
extensions: 'js',
threads: true,
...pluginOptions,
};

Expand Down
2 changes: 1 addition & 1 deletion src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
]
},
"threads": {
"description": "Set to true to auto-selected based on number of cpus. Set to a number greater than 1 to set an explicit maximum. Set to false, 1 or less to disable and only run in main process.",
"description": "Default is false. Set to true for an auto-selected pool size based on number of cpus. Set to a number greater than 1 to set an explicit pool size. Set to false, 1, or less to disable and only run in main process.",
"anyOf": [{ "type": "number" }, { "type": "boolean" }]
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,24 @@ export function parseFoldersToGlobs(patterns, extensions = []) {
return pattern;
});
}

/**
*
* @param {string} _ key, but unused
* @param {any} value
*/
export const jsonStringifyReplacerSortKeys = (_, value) => {
/**
* @param {{ [x: string]: any; }} sorted
* @param {string | number} key
*/
const insert = (sorted, key) => {
// eslint-disable-next-line no-param-reassign
sorted[key] = value[key];
return sorted;
};

return value instanceof Object && !(value instanceof Array)
? Object.keys(value).sort().reduce(insert, {})
: value;
};
2 changes: 2 additions & 0 deletions test/utils/conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export default (entry, pluginConf = {}, webpackConf = {}) => {
// folder to skip it on the global linting, but here we want the opposite
// (we only use .eslintignore on the test that checks this)
ignore: false,
// TODO: update tests to run both states: test.each([[{threads: false}], [{threads: true}]])('it should...', async ({threads}) => {...})
threads: true,
...pluginConf,
}),
],
Expand Down

0 comments on commit d862d92

Please sign in to comment.