From 4c0905763eb001a621994016aa33cab571adb54a Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Sun, 29 Nov 2020 01:58:52 +0800 Subject: [PATCH 1/9] feat: replace eslint-loader by eslint-webpack-plugin --- .../__tests__/eslintPlugin.spec.js | 30 +++++++++ packages/@vue/cli-plugin-eslint/index.js | 67 ++++++------------- packages/@vue/cli-plugin-eslint/package.json | 2 +- .../__tests__/globalService.spec.js | 9 ++- .../lib/globalConfigPlugin.js | 57 +++++++++------- yarn.lock | 44 +++++++----- 6 files changed, 116 insertions(+), 93 deletions(-) diff --git a/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js b/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js index a4aa46fe69..0c00050597 100644 --- a/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js +++ b/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js @@ -195,3 +195,33 @@ test('should save report results to file with --output-file option', async () => // results file should show "Missing semicolon" errors expect(resultsFileContents).toEqual(expect.stringContaining('Missing semicolon')) }) + +test('should persist cache', async () => { + const project = await create('eslint-cache', { + plugins: { + '@vue/cli-plugin-eslint': { + config: 'airbnb', + lintOn: 'save' + } + } + }) + + let done + const donePromise = new Promise(resolve => { + done = resolve + }) + const { has, run } = project + const server = run('vue-cli-service serve') + + server.stdout.on('data', data => { + data = data.toString() + if (data.match(/Compiled successfully/)) { + done() + } + }) + + await donePromise + server.kill('SIGTERM') + + expect(has('node_modules/.cache/.eslintcache')).toBe(true) +}) diff --git a/packages/@vue/cli-plugin-eslint/index.js b/packages/@vue/cli-plugin-eslint/index.js index c514daafca..3d2a51b7ac 100644 --- a/packages/@vue/cli-plugin-eslint/index.js +++ b/packages/@vue/cli-plugin-eslint/index.js @@ -1,63 +1,38 @@ const path = require('path') +const eslintWebpackPlugin = require('eslint-webpack-plugin') +/** @type {import('@vue/cli-service').ServicePlugin} */ module.exports = (api, options) => { if (options.lintOnSave) { const extensions = require('./eslintOptions').extensions(api) // Use loadModule to allow users to customize their ESLint dependency version. const { resolveModule, loadModule } = require('@vue/cli-shared-utils') const cwd = api.getCwd() - const eslintPkg = - loadModule('eslint/package.json', cwd, true) || - loadModule('eslint/package.json', __dirname, true) - - // eslint-loader doesn't bust cache when eslint config changes - // so we have to manually generate a cache identifier that takes the config - // into account. - const { cacheIdentifier } = api.genCacheConfig( - 'eslint-loader', - { - 'eslint-loader': require('eslint-loader/package.json').version, - eslint: eslintPkg.version - }, - [ - '.eslintrc.js', - '.eslintrc.yaml', - '.eslintrc.yml', - '.eslintrc.json', - '.eslintrc', - '.eslintignore', - 'package.json' - ] - ) api.chainWebpack(webpackConfig => { const { lintOnSave } = options const allWarnings = lintOnSave === true || lintOnSave === 'warning' const allErrors = lintOnSave === 'error' - webpackConfig.module - .rule('eslint') - .pre() - .exclude - .add(/node_modules/) - .add(path.dirname(require.resolve('@vue/cli-service'))) - .end() - .test(/\.(vue|(j|t)sx?)$/) - .use('eslint-loader') - .loader(require.resolve('eslint-loader')) - .options({ - extensions, - cache: true, - cacheIdentifier, - emitWarning: allWarnings, - // only emit errors in production mode. - emitError: allErrors, - eslintPath: path.dirname( - resolveModule('eslint/package.json', cwd) || - resolveModule('eslint/package.json', __dirname) - ), - formatter: loadModule('eslint/lib/formatters/codeframe', cwd, true) - }) + /** @type {import('eslint-webpack-plugin').Options & import('eslint').ESLint.Options} */ + const eslintWebpackPluginOptions = { + // common to both plugin and ESlint + extensions, + // ESlint options + cwd, + cache: true, + cacheLocation: api.resolve('node_modules/.cache/.eslintcache'), + // plugin options + context: cwd, + emitWarning: allWarnings, + emitError: allErrors, + eslintPath: path.dirname( + resolveModule('eslint/package.json', cwd) || + resolveModule('eslint/package.json', __dirname) + ), + formatter: loadModule('eslint/lib/formatters/codeframe', cwd, true) + } + webpackConfig.plugin('eslint').use(eslintWebpackPlugin, [eslintWebpackPluginOptions]) }) } diff --git a/packages/@vue/cli-plugin-eslint/package.json b/packages/@vue/cli-plugin-eslint/package.json index 3cca31a289..e03cc999f1 100644 --- a/packages/@vue/cli-plugin-eslint/package.json +++ b/packages/@vue/cli-plugin-eslint/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@vue/cli-shared-utils": "^4.5.8", - "eslint-loader": "^4.0.2", + "eslint-webpack-plugin": "^2.4.0", "globby": "^9.2.0", "inquirer": "^7.1.0", "webpack": "^4.0.0", diff --git a/packages/@vue/cli-service-global/__tests__/globalService.spec.js b/packages/@vue/cli-service-global/__tests__/globalService.spec.js index 310a94e7a8..8163d19148 100644 --- a/packages/@vue/cli-service-global/__tests__/globalService.spec.js +++ b/packages/@vue/cli-service-global/__tests__/globalService.spec.js @@ -11,6 +11,7 @@ const launchPuppeteer = require('@vue/cli-test-utils/launchPuppeteer') const cwd = path.resolve(__dirname, 'temp') const binPath = require.resolve('@vue/cli/bin/vue') const write = (file, content) => fs.writeFile(path.join(cwd, file), content) +const remove = (file) => fs.remove(path.join(cwd, file)) const entryVue = fs.readFileSync(path.resolve(__dirname, 'entry.vue'), 'utf-8') @@ -26,6 +27,7 @@ beforeEach(async () => { await write('App.vue', entryVue) await write('Other.vue', entryVue) await write('foo.js', entryJs) + await remove('node_modules/.cache') }) test('global serve', async () => { @@ -55,9 +57,12 @@ test('global serve', async () => { test('global serve with eslint', async () => { try { + const cachePath = path.join(cwd, 'node_modules/.cache/.eslintcache') + expect(fs.existsSync(cachePath)).toBe(false) await serve( () => execa(binPath, ['serve', 'foo.js'], { cwd }), - async ({ page, nextUpdate, helpers }) => { + async ({ nextUpdate, helpers }) => { + expect(fs.existsSync(cachePath)).toBe(true) expect(await helpers.getText('h1')).toMatch('hi') write('foo.js', entryJs.replace(`$mount('#app')`, `$mount('#app');`)) @@ -72,7 +77,7 @@ test('global serve with eslint', async () => { // Failed because of no-extra-semi expect(err).toMatch('Failed to compile with 1 errors') } - expect.assertions(3) + expect.assertions(5) }) let server, browser, page diff --git a/packages/@vue/cli-service-global/lib/globalConfigPlugin.js b/packages/@vue/cli-service-global/lib/globalConfigPlugin.js index 730abadb85..94948f6791 100644 --- a/packages/@vue/cli-service-global/lib/globalConfigPlugin.js +++ b/packages/@vue/cli-service-global/lib/globalConfigPlugin.js @@ -6,6 +6,7 @@ const { loadPartialConfigSync } = require('@babel/core') module.exports = function createConfigPlugin (context, entry, asLib) { return { id: '@vue/cli-service-global-config', + /** @type {import('@vue/cli-service').ServicePlugin} */ apply: (api, options) => { const _entry = path.resolve(context, entry) api.chainWebpack(config => { @@ -85,6 +86,7 @@ module.exports = function createConfigPlugin (context, entry, asLib) { // messed up when the project is inside another project. const ESLintConfigFile = findExisting(context, [ '.eslintrc.js', + '.eslintrc.cjs', '.eslintrc.yaml', '.eslintrc.yml', '.eslintrc.json', @@ -99,33 +101,36 @@ module.exports = function createConfigPlugin (context, entry, asLib) { const hasBabelConfig = !!babelConfig && babelConfig.hasFilesystemConfig() // set inline eslint options - config.module - .rule('eslint') - .include - .clear() - .end() - .exclude - .add(/node_modules/) - .end() - .use('eslint-loader') - .tap(loaderOptions => Object.assign({}, loaderOptions, { - useEslintrc: hasESLintConfig, - baseConfig: { - extends: [ - 'plugin:vue/essential', - 'eslint:recommended' - ], - parserOptions: { - parser: '@babel/eslint-parser', - requireConfigFile: hasBabelConfig, - babelOptions - }, - rules: { - 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', - 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' - } + config + .plugin('eslint') + .tap(args => { + /** @type {import('eslint-webpack-plugin').Options & import('eslint').ESLint.Options} */ + const eslintWebpackPluginOptions = { + // eslint@7 load config and plugin related to baseConfig.extends from cwd, + // By default, cwd is the current working directory of `vue serve`, + // should load baseConfig.extends config(dependencies of @vue/cli-service-global) from `__dirname` + cwd: __dirname, + useEslintrc: hasESLintConfig, + baseConfig: { + extends: [ + 'plugin:vue/essential', + 'eslint:recommended' + ], + parserOptions: { + parser: '@babel/eslint-parser', + requireConfigFile: hasBabelConfig, + babelOptions + }, + rules: { + 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', + 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' } - })) + } + } + Object.assign(args[0], eslintWebpackPluginOptions) + + return args + }) if (!asLib) { // set html plugin template diff --git a/yarn.lock b/yarn.lock index 80848860b8..152c171a6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2708,6 +2708,19 @@ resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== +"@types/eslint@^7.2.4": + version "7.2.5" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.5.tgz#92172ecf490c2fce4b076739693d75f30376d610" + integrity sha512-Dc6ar9x16BdaR3NSxSF7T4IjL9gxxViJq8RmFd+2UAyA+K6ck2W+gUwfgpG/y9TPyUuBL35109bbULpEynvltA== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.45" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" + integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== + "@types/execa@^0.9.0": version "0.9.0" resolved "https://registry.yarnpkg.com/@types/execa/-/execa-0.9.0.tgz#9b025d2755f17e80beaf9368c3f4f319d8b0fb93" @@ -2867,7 +2880,7 @@ ast-types "0.12.1" recast "0.17.2" -"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": +"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== @@ -8774,17 +8787,6 @@ eslint-import-resolver-webpack@^0.12.1, eslint-import-resolver-webpack@^0.12.2: resolve "^1.13.1" semver "^5.7.1" -eslint-loader@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/eslint-loader/-/eslint-loader-4.0.2.tgz#386a1e21bcb613b3cf2d252a3b708023ccfb41ec" - integrity sha512-EDpXor6lsjtTzZpLUn7KmXs02+nIjGcgees9BYjNkWra3jVq5vVa8IoCKgzT2M7dNNeoMBtaSG83Bd40N3poLw== - dependencies: - find-cache-dir "^3.3.1" - fs-extra "^8.1.0" - loader-utils "^2.0.0" - object-hash "^2.0.3" - schema-utils "^2.6.5" - eslint-module-utils@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" @@ -8934,6 +8936,17 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== +eslint-webpack-plugin@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.4.0.tgz#dcfd2653d0e15e52251f34dd3690ce60718d5589" + integrity sha512-j0lAJj3RnStAFdIH2P0+nsEImiBijwogZhL1go4bI6DE+9OhQuOmJ/xtmxkLtNr1w0cf5SRNkDlmIe8t/pHgww== + dependencies: + "@types/eslint" "^7.2.4" + arrify "^2.0.1" + jest-worker "^26.6.2" + micromatch "^4.0.2" + schema-utils "^3.0.0" + eslint@^7.13.0: version "7.13.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.13.0.tgz#7f180126c0dcdef327bfb54b211d7802decc08da" @@ -12575,7 +12588,7 @@ jest-worker@^24.6.0, jest-worker@^24.9.0: merge-stream "^2.0.0" supports-color "^6.1.0" -jest-worker@^26.5.0: +jest-worker@^26.5.0, jest-worker@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== @@ -15278,11 +15291,6 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-hash@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.0.3.tgz#d12db044e03cd2ca3d77c0570d87225b02e1e6ea" - integrity sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg== - object-inspect@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" From cfc69c3a145496bff8db056389d66394b2636a7f Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Sun, 29 Nov 2020 17:36:56 +0800 Subject: [PATCH 2/9] ci: disable cli-ui lintOnSave in circleci --- packages/@vue/cli-ui/vue.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/@vue/cli-ui/vue.config.js b/packages/@vue/cli-ui/vue.config.js index 14b25f5655..be9dbc40b1 100644 --- a/packages/@vue/cli-ui/vue.config.js +++ b/packages/@vue/cli-ui/vue.config.js @@ -1,7 +1,11 @@ const merge = require('deepmerge') const path = require('path') +/** @type {import('@vue/cli-service').ProjectOptions} */ module.exports = { + lintOnSave: process.env.CIRCLECI + ? false + : 'default', pluginOptions: { apollo: { enableMocks: false, From 934353fed2976ec881be5f1faa0d51eb154a6a68 Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Sun, 29 Nov 2020 18:03:06 +0800 Subject: [PATCH 3/9] Revert "ci: disable cli-ui lintOnSave in circleci" This reverts commit cfc69c3a145496bff8db056389d66394b2636a7f. --- packages/@vue/cli-ui/vue.config.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/@vue/cli-ui/vue.config.js b/packages/@vue/cli-ui/vue.config.js index be9dbc40b1..14b25f5655 100644 --- a/packages/@vue/cli-ui/vue.config.js +++ b/packages/@vue/cli-ui/vue.config.js @@ -1,11 +1,7 @@ const merge = require('deepmerge') const path = require('path') -/** @type {import('@vue/cli-service').ProjectOptions} */ module.exports = { - lintOnSave: process.env.CIRCLECI - ? false - : 'default', pluginOptions: { apollo: { enableMocks: false, From d9351efddb4e1a27a649864cc15e1e1e2ab28528 Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Sun, 29 Nov 2020 18:04:45 +0800 Subject: [PATCH 4/9] fix: set 'threads' of eslint-webpack-plugin by 'options.parallel' --- packages/@vue/cli-plugin-eslint/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/@vue/cli-plugin-eslint/index.js b/packages/@vue/cli-plugin-eslint/index.js index 3d2a51b7ac..5ca43af83a 100644 --- a/packages/@vue/cli-plugin-eslint/index.js +++ b/packages/@vue/cli-plugin-eslint/index.js @@ -24,6 +24,9 @@ module.exports = (api, options) => { cacheLocation: api.resolve('node_modules/.cache/.eslintcache'), // plugin options context: cwd, + threads: process.env.NODE_ENV === 'production' + ? options.parallel + : false, emitWarning: allWarnings, emitError: allErrors, eslintPath: path.dirname( From f67bc93b21c777ec34c0a6b75fd28efb5b156000 Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Mon, 30 Nov 2020 11:59:25 +0800 Subject: [PATCH 5/9] test: fix some tests --- .../__tests__/nightwatchPlugin.spec.js | 36 ++++++++++--------- .../__tests__/eslintPlugin.spec.js | 2 +- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/@vue/cli-plugin-e2e-nightwatch/__tests__/nightwatchPlugin.spec.js b/packages/@vue/cli-plugin-e2e-nightwatch/__tests__/nightwatchPlugin.spec.js index 0eab736cff..a27daf6ac4 100644 --- a/packages/@vue/cli-plugin-e2e-nightwatch/__tests__/nightwatchPlugin.spec.js +++ b/packages/@vue/cli-plugin-e2e-nightwatch/__tests__/nightwatchPlugin.spec.js @@ -42,23 +42,27 @@ describe('nightwatch e2e plugin', () => { }) test('should accept the --url cli option', async () => { - await project.run(`vue-cli-service build`) - const server = createServer({ root: path.join(project.dir, 'dist') }) - await new Promise((resolve, reject) => { - server.listen(8080, err => { - if (err) return reject(err) - resolve() + let server + try { + await project.run(`vue-cli-service build`) + server = createServer({ root: path.join(project.dir, 'dist') }) + await new Promise((resolve, reject) => { + server.listen(8080, err => { + if (err) return reject(err) + resolve() + }) }) - }) - await project.run(`vue-cli-service test:e2e --headless --url http://127.0.0.1:8080/`) - server.close() - - let results = await project.read('test_results.json') - results = JSON.parse(results) - expect(Object.keys(results.modules)).toEqual([ - 'test-with-pageobjects', - 'test' - ]) + await project.run(`vue-cli-service test:e2e --headless --url http://127.0.0.1:8080/`) + + let results = await project.read('test_results.json') + results = JSON.parse(results) + expect(Object.keys(results.modules)).toEqual([ + 'test-with-pageobjects', + 'test' + ]) + } finally { + server && server.close() + } }) test('should run single test with custom nightwatch.json', async () => { diff --git a/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js b/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js index 0c00050597..8ff1d84c00 100644 --- a/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js +++ b/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js @@ -216,12 +216,12 @@ test('should persist cache', async () => { server.stdout.on('data', data => { data = data.toString() if (data.match(/Compiled successfully/)) { + server.stdin.write('close') done() } }) await donePromise - server.kill('SIGTERM') expect(has('node_modules/.cache/.eslintcache')).toBe(true) }) From 99f2fd5c2a264c4bbed2fe97cb6123739e2098f3 Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Tue, 1 Dec 2020 23:52:33 +0800 Subject: [PATCH 6/9] chore: bump version of eslint-webpack-plugin --- packages/@vue/cli-plugin-eslint/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/@vue/cli-plugin-eslint/package.json b/packages/@vue/cli-plugin-eslint/package.json index e03cc999f1..4ffef8e0bf 100644 --- a/packages/@vue/cli-plugin-eslint/package.json +++ b/packages/@vue/cli-plugin-eslint/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@vue/cli-shared-utils": "^4.5.8", - "eslint-webpack-plugin": "^2.4.0", + "eslint-webpack-plugin": "^2.4.1", "globby": "^9.2.0", "inquirer": "^7.1.0", "webpack": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 152c171a6a..de2b4111cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8936,10 +8936,10 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint-webpack-plugin@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.4.0.tgz#dcfd2653d0e15e52251f34dd3690ce60718d5589" - integrity sha512-j0lAJj3RnStAFdIH2P0+nsEImiBijwogZhL1go4bI6DE+9OhQuOmJ/xtmxkLtNr1w0cf5SRNkDlmIe8t/pHgww== +eslint-webpack-plugin@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-2.4.1.tgz#9353ec46a31d29558734a38a05eb14c5760a7144" + integrity sha512-cj8iPWZKuAiVD8MMgTSunyMCAvxQxp5mxoPHZl1UMGkApFXaXJHdCFcCR+oZEJbBNhReNa5SjESIn34uqUbBtg== dependencies: "@types/eslint" "^7.2.4" arrify "^2.0.1" From 9c772a439f7de41ca6b7eb1ac2f3828edaa02bc4 Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Thu, 3 Dec 2020 02:04:31 +0800 Subject: [PATCH 7/9] fix: disable 'threads' Although eslint-webpack-plugin disable 'threads' by default, it's better set it explicitly --- packages/@vue/cli-plugin-eslint/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/@vue/cli-plugin-eslint/index.js b/packages/@vue/cli-plugin-eslint/index.js index 5ca43af83a..bb8361e57c 100644 --- a/packages/@vue/cli-plugin-eslint/index.js +++ b/packages/@vue/cli-plugin-eslint/index.js @@ -24,9 +24,8 @@ module.exports = (api, options) => { cacheLocation: api.resolve('node_modules/.cache/.eslintcache'), // plugin options context: cwd, - threads: process.env.NODE_ENV === 'production' - ? options.parallel - : false, + // https://github.com/webpack-contrib/eslint-webpack-plugin/issues/56 + threads: false, emitWarning: allWarnings, emitError: allErrors, eslintPath: path.dirname( From 9e395f3c48e5456e9438784666396fadd7720255 Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Fri, 4 Dec 2020 04:14:12 +0800 Subject: [PATCH 8/9] feat: add cacheIdentifier --- .../__tests__/eslintPlugin.spec.js | 2 +- packages/@vue/cli-plugin-eslint/index.js | 21 ++++++++++++++++++- .../__tests__/globalService.spec.js | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js b/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js index 8ff1d84c00..71b1134a89 100644 --- a/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js +++ b/packages/@vue/cli-plugin-eslint/__tests__/eslintPlugin.spec.js @@ -223,5 +223,5 @@ test('should persist cache', async () => { await donePromise - expect(has('node_modules/.cache/.eslintcache')).toBe(true) + expect(has('node_modules/.cache/eslint/cache.json')).toBe(true) }) diff --git a/packages/@vue/cli-plugin-eslint/index.js b/packages/@vue/cli-plugin-eslint/index.js index bb8361e57c..df302c7d14 100644 --- a/packages/@vue/cli-plugin-eslint/index.js +++ b/packages/@vue/cli-plugin-eslint/index.js @@ -9,6 +9,19 @@ module.exports = (api, options) => { const { resolveModule, loadModule } = require('@vue/cli-shared-utils') const cwd = api.getCwd() + const eslintPkg = + loadModule('eslint/package.json', cwd, true) || + loadModule('eslint/package.json', __dirname, true) + + // ESLint doesn't clear the cache when you upgrade ESLint plugins (ESlint do consider config changes) + // so we have to manually generate a cache identifier that takes lock file into account. + const { cacheIdentifier, cacheDirectory } = api.genCacheConfig( + 'eslint', + { + eslint: eslintPkg.version + } + ) + api.chainWebpack(webpackConfig => { const { lintOnSave } = options const allWarnings = lintOnSave === true || lintOnSave === 'warning' @@ -21,7 +34,13 @@ module.exports = (api, options) => { // ESlint options cwd, cache: true, - cacheLocation: api.resolve('node_modules/.cache/.eslintcache'), + cacheLocation: path.format({ + dir: cacheDirectory, + name: process.env.VUE_CLI_TEST + ? 'cache' + : cacheIdentifier, + ext: '.json' + }), // plugin options context: cwd, // https://github.com/webpack-contrib/eslint-webpack-plugin/issues/56 diff --git a/packages/@vue/cli-service-global/__tests__/globalService.spec.js b/packages/@vue/cli-service-global/__tests__/globalService.spec.js index 8163d19148..3559bafa8d 100644 --- a/packages/@vue/cli-service-global/__tests__/globalService.spec.js +++ b/packages/@vue/cli-service-global/__tests__/globalService.spec.js @@ -57,7 +57,7 @@ test('global serve', async () => { test('global serve with eslint', async () => { try { - const cachePath = path.join(cwd, 'node_modules/.cache/.eslintcache') + const cachePath = path.join(cwd, 'node_modules/.cache/eslint/cache.json') expect(fs.existsSync(cachePath)).toBe(false) await serve( () => execa(binPath, ['serve', 'foo.js'], { cwd }), From 2d6134086fac357cd42139f99f7844c6e8cfb99e Mon Sep 17 00:00:00 2001 From: fangbinwei Date: Fri, 4 Dec 2020 04:31:12 +0800 Subject: [PATCH 9/9] fix: take package.json into account --- packages/@vue/cli-plugin-eslint/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/@vue/cli-plugin-eslint/index.js b/packages/@vue/cli-plugin-eslint/index.js index df302c7d14..246736746f 100644 --- a/packages/@vue/cli-plugin-eslint/index.js +++ b/packages/@vue/cli-plugin-eslint/index.js @@ -19,7 +19,8 @@ module.exports = (api, options) => { 'eslint', { eslint: eslintPkg.version - } + }, + ['package.json'] ) api.chainWebpack(webpackConfig => {