From 2eb37c8b9ade943904313a5a206c93ccadff2b43 Mon Sep 17 00:00:00 2001 From: simon3000 Date: Thu, 19 Mar 2020 19:32:26 +0100 Subject: [PATCH 1/6] chore: Update yarn.lock --- yarn.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/yarn.lock b/yarn.lock index 86cbbe74ef..d343e4f6be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5107,7 +5107,7 @@ cheerio@^1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" -"chokidar@>=2.0.0 <4.0.0": +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.3.0: version "3.3.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== @@ -5122,7 +5122,7 @@ cheerio@^1.0.0-rc.2: optionalDependencies: fsevents "~2.1.2" -chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4, chokidar@^2.1.8: +chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -8352,14 +8352,14 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-ts-checker-webpack-plugin@^1.5.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.6.0.tgz#a81fd1c6bf5258fa5318cf3e9a7e9bac006f7917" - integrity sha512-vqOY5gakcoon2s12V7MMe01OPwfgqulUWFzm+geQaPPOBKjW1I7aqqoBVlU0ECn97liMB0ECs16pRdIGe9qdRw== +fork-ts-checker-webpack-plugin@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-3.1.1.tgz#a1642c0d3e65f50c2cc1742e9c0a80f441f86b19" + integrity sha512-DuVkPNrM12jR41KM2e+N+styka0EgLkTnXmNcXdgOM37vtGeY+oCBK/Jx0hzSeEU6memFCtWb4htrHPMDfwwUQ== dependencies: babel-code-frame "^6.22.0" chalk "^2.4.1" - chokidar "^2.0.4" + chokidar "^3.3.0" micromatch "^3.1.10" minimatch "^3.0.4" semver "^5.6.0" From ffff91a27074d9df91e4748eacb63bbbb8cc45d5 Mon Sep 17 00:00:00 2001 From: simon3000 Date: Thu, 19 Mar 2020 21:57:28 +0100 Subject: [PATCH 2/6] feat: support vue.config.cjs --- packages/@vue/cli-service/__tests__/Service.spec.js | 12 ++++++++++-- packages/@vue/cli-service/lib/Service.js | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/@vue/cli-service/__tests__/Service.spec.js b/packages/@vue/cli-service/__tests__/Service.spec.js index 7212c0d014..166c6b0a02 100644 --- a/packages/@vue/cli-service/__tests__/Service.spec.js +++ b/packages/@vue/cli-service/__tests__/Service.spec.js @@ -1,5 +1,6 @@ jest.mock('fs') jest.mock('/vue.config.js', () => ({ lintOnSave: false }), { virtual: true }) +jest.mock('/vue.config.cjs', () => ({ lintOnSave: true }), { virtual: true }) jest.mock('vue-cli-plugin-foo', () => () => {}, { virtual: true }) const fs = require('fs') @@ -61,7 +62,7 @@ test('env loading for custom mode', () => { test('loading plugins from package.json', () => { mockPkg({ devDependencies: { - 'bar': '^1.0.0', + bar: '^1.0.0', '@vue/cli-plugin-babel': '^4.2.0', 'vue-cli-plugin-foo': '^1.0.0' } @@ -139,6 +140,13 @@ test('load project options from vue.config.js', () => { expect(service.projectOptions.lintOnSave).toBe(false) }) +test('load project options from vue.config.cjs', () => { + fs.writeFileSync('/vue.config.cjs', '') + const service = createMockService() + fs.unlinkSync('/vue.config.cjs') + expect(service.projectOptions.lintOnSave).toBe(true) +}) + test('load project options from vue.config.js', () => { process.env.VUE_CLI_SERVICE_CONFIG_PATH = `/vue.config.js` fs.writeFileSync('/vue.config.js', '') // only to ensure fs.existsSync returns true @@ -191,7 +199,7 @@ test('api: --skip-plugins', () => { id: 'test-command', apply: api => { api.registerCommand('foo', _args => { - return + }) } }, diff --git a/packages/@vue/cli-service/lib/Service.js b/packages/@vue/cli-service/lib/Service.js index 43e01096a7..32337f99ca 100644 --- a/packages/@vue/cli-service/lib/Service.js +++ b/packages/@vue/cli-service/lib/Service.js @@ -300,10 +300,13 @@ module.exports = class Service { loadUserOptions () { // vue.config.js + // vue.config.cjs let fileConfig, pkgConfig, resolved, resolvedFrom + const jsConfigPath = path.resolve(this.context, 'vue.config.js') + const cjsConfigPath = path.resolve(this.context, 'vue.config.cjs') const configPath = ( process.env.VUE_CLI_SERVICE_CONFIG_PATH || - path.resolve(this.context, 'vue.config.js') + (fs.existsSync(cjsConfigPath) ? cjsConfigPath : jsConfigPath) ) if (fs.existsSync(configPath)) { try { From 0e5fc4a0bb6a6250fb9f12faa264b96c2a3d4fa1 Mon Sep 17 00:00:00 2001 From: simon3000 Date: Mon, 23 Mar 2020 03:47:42 +0100 Subject: [PATCH 3/6] feat(cli-service): import(vue.config.js) with deasync --- packages/@vue/cli-service/lib/Service.js | 26 +++++++++++++++++++- packages/@vue/cli-service/package.json | 1 + yarn.lock | 31 +++++++++++++++++------- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/packages/@vue/cli-service/lib/Service.js b/packages/@vue/cli-service/lib/Service.js index 43e01096a7..a2c4bb039e 100644 --- a/packages/@vue/cli-service/lib/Service.js +++ b/packages/@vue/cli-service/lib/Service.js @@ -7,6 +7,7 @@ const PluginAPI = require('./PluginAPI') const dotenv = require('dotenv') const dotenvExpand = require('dotenv-expand') const defaultsDeep = require('lodash.defaultsdeep') +const deasync = require('deasync') const { chalk, warn, error, isPlugin, resolvePluginId, loadModule, resolvePkg } = require('@vue/cli-shared-utils') const { defaults, validate } = require('./options') @@ -307,7 +308,7 @@ module.exports = class Service { ) if (fs.existsSync(configPath)) { try { - fileConfig = require(configPath) + fileConfig = importConfig(configPath) if (typeof fileConfig === 'function') { fileConfig = fileConfig() @@ -415,3 +416,26 @@ function cloneRuleNames (to, from) { } }) } + +function importConfig (configPath) { + let done = false + let data + let reject = false + import(configPath) + .then(result => { + data = result + done = true + }) + .catch(reason => { + data = reason + done = true + reject = true + }) + deasync.loopWhile(() => { + return !done + }) + if (reject) { + throw new Error(data) + } + return data.default +} diff --git a/packages/@vue/cli-service/package.json b/packages/@vue/cli-service/package.json index 4c656313ec..50aedfd35f 100644 --- a/packages/@vue/cli-service/package.json +++ b/packages/@vue/cli-service/package.json @@ -46,6 +46,7 @@ "css-loader": "^3.4.2", "cssnano": "^4.1.10", "current-script-polyfill": "^1.0.0", + "deasync": "^0.1.19", "debug": "^4.1.1", "default-gateway": "^5.0.5", "dotenv": "^8.2.0", diff --git a/yarn.lock b/yarn.lock index 86cbbe74ef..66c6f4f7ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5107,7 +5107,7 @@ cheerio@^1.0.0-rc.2: lodash "^4.15.0" parse5 "^3.0.1" -"chokidar@>=2.0.0 <4.0.0": +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.3.0: version "3.3.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== @@ -5122,7 +5122,7 @@ cheerio@^1.0.0-rc.2: optionalDependencies: fsevents "~2.1.2" -chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4, chokidar@^2.1.8: +chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -6416,6 +6416,14 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= +deasync@^0.1.19: + version "0.1.19" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.19.tgz#e7ea89fcc9ad483367e8a48fe78f508ca86286e8" + integrity sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg== + dependencies: + bindings "^1.5.0" + node-addon-api "^1.7.1" + debug@*, debug@4, debug@4.1.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -8352,14 +8360,14 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= -fork-ts-checker-webpack-plugin@^1.5.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.6.0.tgz#a81fd1c6bf5258fa5318cf3e9a7e9bac006f7917" - integrity sha512-vqOY5gakcoon2s12V7MMe01OPwfgqulUWFzm+geQaPPOBKjW1I7aqqoBVlU0ECn97liMB0ECs16pRdIGe9qdRw== +fork-ts-checker-webpack-plugin@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-3.1.1.tgz#a1642c0d3e65f50c2cc1742e9c0a80f441f86b19" + integrity sha512-DuVkPNrM12jR41KM2e+N+styka0EgLkTnXmNcXdgOM37vtGeY+oCBK/Jx0hzSeEU6memFCtWb4htrHPMDfwwUQ== dependencies: babel-code-frame "^6.22.0" chalk "^2.4.1" - chokidar "^2.0.4" + chokidar "^3.3.0" micromatch "^3.1.10" minimatch "^3.0.4" semver "^5.6.0" @@ -12714,6 +12722,11 @@ no-case@^2.2.0, no-case@^2.3.2: dependencies: lower-case "^1.1.1" +node-addon-api@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492" + integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ== + node-cache@^4.1.1: version "4.2.1" resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.1.tgz#efd8474dee4edec4138cdded580f5516500f7334" @@ -14613,7 +14626,7 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -puppeteer@1.11.0, puppeteer@^1.11.0: +puppeteer@^1.11.0: version "1.11.0" resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-1.11.0.tgz#63cdbe12b07275cd6e0b94bce41f3fcb20305770" integrity sha512-iG4iMOHixc2EpzqRV+pv7o3GgmU2dNYEMkvKwSaQO/vMZURakwSOn/EYJ6OIRFYOque1qorzIBvrytPIQB3YzQ== @@ -17851,7 +17864,7 @@ vue-router@^3.1.3, vue-router@^3.1.5: resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.1.5.tgz#ff29b8a1e1306c526b52d4dc0532109f16c41231" integrity sha512-BszkPvhl7I9h334GjckCh7sVFyjTPMMJFJ4Bsrem/Ik+B/9gt5tgrk8k4gGLO4ZpdvciVdg7O41gW4DisQWurg== -vue-server-renderer@^2.6.10, vue-server-renderer@^2.6.11: +vue-server-renderer@^2.6.10: version "2.6.11" resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.11.tgz#be8c9abc6aacc309828a755c021a05fc474b4bc3" integrity sha512-V3faFJHr2KYfdSIalL+JjinZSHYUhlrvJ9pzCIjjwSh77+pkrsXpK4PucdPcng57+N77pd1LrKqwbqjQdktU1A== From a7fe5833bd4edb01d022e56c32c292e04c8daf8a Mon Sep 17 00:00:00 2001 From: simon3000 Date: Mon, 23 Mar 2020 03:51:01 +0100 Subject: [PATCH 4/6] fix: vue.config.js prior than cjs --- packages/@vue/cli-service/lib/Service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@vue/cli-service/lib/Service.js b/packages/@vue/cli-service/lib/Service.js index 32337f99ca..01df35d779 100644 --- a/packages/@vue/cli-service/lib/Service.js +++ b/packages/@vue/cli-service/lib/Service.js @@ -306,7 +306,7 @@ module.exports = class Service { const cjsConfigPath = path.resolve(this.context, 'vue.config.cjs') const configPath = ( process.env.VUE_CLI_SERVICE_CONFIG_PATH || - (fs.existsSync(cjsConfigPath) ? cjsConfigPath : jsConfigPath) + (fs.existsSync(jsConfigPath) ? jsConfigPath : cjsConfigPath) ) if (fs.existsSync(configPath)) { try { From fabc2e0b057a98b8611317d96e15f7b0964a4f4c Mon Sep 17 00:00:00 2001 From: simon3000 Date: Tue, 24 Mar 2020 12:08:54 +0100 Subject: [PATCH 5/6] chore: merge upstream --- .../cli-service/__tests__/Service.spec.js | 9 ---- .../cli-service/__tests__/ServiceESM.spec.js | 33 ++++++++++++ .../__tests__/mockESM/package.json | 6 +++ packages/@vue/cli-service/lib/Service.js | 51 ++++++++++++++----- 4 files changed, 77 insertions(+), 22 deletions(-) create mode 100644 packages/@vue/cli-service/__tests__/ServiceESM.spec.js create mode 100644 packages/@vue/cli-service/__tests__/mockESM/package.json diff --git a/packages/@vue/cli-service/__tests__/Service.spec.js b/packages/@vue/cli-service/__tests__/Service.spec.js index 3f15b7fc9a..cf01610159 100644 --- a/packages/@vue/cli-service/__tests__/Service.spec.js +++ b/packages/@vue/cli-service/__tests__/Service.spec.js @@ -135,15 +135,6 @@ test('load project options from vue.config.js', () => { expect(service.projectOptions.lintOnSave).toBe(false) }) - -test('load project options from vue.config.cjs', () => { - fs.writeFileSync('/vue.config.cjs', '') - const service = createMockService() - fs.unlinkSync('/vue.config.cjs') - expect(service.projectOptions.lintOnSave).toBe(true) -}) - - test('load project options from vue.config.js as a function', () => { jest.mock('/vue.config.js', () => function () { return { lintOnSave: false } }, { virtual: true }) mockPkg({ diff --git a/packages/@vue/cli-service/__tests__/ServiceESM.spec.js b/packages/@vue/cli-service/__tests__/ServiceESM.spec.js new file mode 100644 index 0000000000..88957c63c4 --- /dev/null +++ b/packages/@vue/cli-service/__tests__/ServiceESM.spec.js @@ -0,0 +1,33 @@ +const { join } = require('path') +const Service = require('../lib/Service') + +const mockDir = join(__dirname, 'mockESM') +const configPath = join(mockDir, 'vue.config.cjs') + +const createService = () => { + const service = new Service(mockDir, { + plugins: [], + useBuiltIn: false + }) + service.init() + return service +} + +// vue.config.cjs has higher priority + +test('load project options from package.json', async () => { + const service = createService() + expect(service.projectOptions.lintOnSave).toBe('default') +}) + +test('load project options from vue.config.cjs', async () => { + jest.mock(configPath, () => ({ lintOnSave: true }), { virtual: true }) + const service = createService() + expect(service.projectOptions.lintOnSave).toBe(true) +}) + +test('load project options from vue.config.cjs as a function', async () => { + jest.mock(configPath, () => function () { return { lintOnSave: true } }, { virtual: true }) + const service = createService() + expect(service.projectOptions.lintOnSave).toBe(true) +}) diff --git a/packages/@vue/cli-service/__tests__/mockESM/package.json b/packages/@vue/cli-service/__tests__/mockESM/package.json new file mode 100644 index 0000000000..bdd0885ceb --- /dev/null +++ b/packages/@vue/cli-service/__tests__/mockESM/package.json @@ -0,0 +1,6 @@ +{ + "type": "module", + "vue": { + "lintOnSave": "default" + } +} diff --git a/packages/@vue/cli-service/lib/Service.js b/packages/@vue/cli-service/lib/Service.js index a2db329b7a..21db7ffaee 100644 --- a/packages/@vue/cli-service/lib/Service.js +++ b/packages/@vue/cli-service/lib/Service.js @@ -10,6 +10,22 @@ const { chalk, warn, error, isPlugin, resolvePluginId, loadModule, resolvePkg } const { defaults, validate } = require('./options') +const loadConfig = configPath => { + let fileConfig = require(configPath) + + if (typeof fileConfig === 'function') { + fileConfig = fileConfig() + } + + if (!fileConfig || typeof fileConfig !== 'object') { + error( + `Error loading ${chalk.bold('vue.config.js')}: should export an object or a function that returns object.` + ) + fileConfig = null + } + return fileConfig +} + module.exports = class Service { constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) { process.VUE_CLI_SERVICE = this @@ -301,32 +317,41 @@ module.exports = class Service { // vue.config.js // vue.config.cjs let fileConfig, pkgConfig, resolved, resolvedFrom + const esm = this.pkg.type && this.pkg.type === 'module' const jsConfigPath = path.resolve(this.context, 'vue.config.js') const cjsConfigPath = path.resolve(this.context, 'vue.config.cjs') const configPath = ( process.env.VUE_CLI_SERVICE_CONFIG_PATH || - (fs.existsSync(jsConfigPath) ? jsConfigPath : cjsConfigPath) + jsConfigPath ) - try { - fileConfig = require(configPath) - - if (typeof fileConfig === 'function') { - fileConfig = fileConfig() - } - if (!fileConfig || typeof fileConfig !== 'object') { - error( - `Error loading ${chalk.bold('vue.config.js')}: should export an object or a function that returns object.` - ) - fileConfig = null - } + try { + fileConfig = loadConfig(configPath) } catch (e) { if (e.code !== 'MODULE_NOT_FOUND') { + if (e.code === 'ERR_REQUIRE_ESM') { + warn(`Rename ${chalk.bold('vue.config.js')} to ${chalk.bold('vue.config.cjs')} when ECMAScript modules is enabled`) + } error(`Error loading ${chalk.bold('vue.config.js')}:`) throw e } } + // vue.config.js not found, esm enabled, no env set + if (!fileConfig && esm && !process.env.VUE_CLI_SERVICE_CONFIG_PATH) { + try { + fileConfig = loadConfig(cjsConfigPath) + } catch (e) { + if (e.code !== 'MODULE_NOT_FOUND') { + error(`Error loading ${chalk.bold('vue.config.cjs')}:`) + throw e + } + } + if (fileConfig) { + warn(`ECMAScript modules is detected, config loaded from ${chalk.bold('vue.config.cjs')}`) + } + } + // package.vue pkgConfig = this.pkg.vue if (pkgConfig && typeof pkgConfig !== 'object') { From bedebfe0b270c86a338772923e57f13d60eb5055 Mon Sep 17 00:00:00 2001 From: simon3000 Date: Tue, 24 Mar 2020 13:10:26 +0100 Subject: [PATCH 6/6] feat: use import(vue.config.js) --- .../cli-service/__tests__/ServiceESM.spec.js | 33 -------------- .../__tests__/e2eServiceESM.spec.js | 43 +++++++++++++++++++ .../__tests__/mockESM/readConfig.cjs | 9 ++++ packages/@vue/cli-service/lib/Service.js | 43 +++++++------------ 4 files changed, 67 insertions(+), 61 deletions(-) delete mode 100644 packages/@vue/cli-service/__tests__/ServiceESM.spec.js create mode 100644 packages/@vue/cli-service/__tests__/e2eServiceESM.spec.js create mode 100644 packages/@vue/cli-service/__tests__/mockESM/readConfig.cjs diff --git a/packages/@vue/cli-service/__tests__/ServiceESM.spec.js b/packages/@vue/cli-service/__tests__/ServiceESM.spec.js deleted file mode 100644 index 88957c63c4..0000000000 --- a/packages/@vue/cli-service/__tests__/ServiceESM.spec.js +++ /dev/null @@ -1,33 +0,0 @@ -const { join } = require('path') -const Service = require('../lib/Service') - -const mockDir = join(__dirname, 'mockESM') -const configPath = join(mockDir, 'vue.config.cjs') - -const createService = () => { - const service = new Service(mockDir, { - plugins: [], - useBuiltIn: false - }) - service.init() - return service -} - -// vue.config.cjs has higher priority - -test('load project options from package.json', async () => { - const service = createService() - expect(service.projectOptions.lintOnSave).toBe('default') -}) - -test('load project options from vue.config.cjs', async () => { - jest.mock(configPath, () => ({ lintOnSave: true }), { virtual: true }) - const service = createService() - expect(service.projectOptions.lintOnSave).toBe(true) -}) - -test('load project options from vue.config.cjs as a function', async () => { - jest.mock(configPath, () => function () { return { lintOnSave: true } }, { virtual: true }) - const service = createService() - expect(service.projectOptions.lintOnSave).toBe(true) -}) diff --git a/packages/@vue/cli-service/__tests__/e2eServiceESM.spec.js b/packages/@vue/cli-service/__tests__/e2eServiceESM.spec.js new file mode 100644 index 0000000000..75013fb161 --- /dev/null +++ b/packages/@vue/cli-service/__tests__/e2eServiceESM.spec.js @@ -0,0 +1,43 @@ +// Native support for ES Modules is not complete with jest +// https://github.com/facebook/jest/issues/9430 + +const { writeFile, unlink } = require('fs').promises +const { join } = require('path') +const { fork } = require('child_process') + +const mockDir = join(__dirname, 'mockESM') +const configPath = join(mockDir, 'vue.config.js') +const e2ePath = join(mockDir, 'readConfig.cjs') + +const configData = 'export default { lintOnSave: true }' +const functionConfigData = 'export default () => ({ lintOnSave: true })' + +const e2e = () => new Promise(resolve => { + const subprocess = fork(e2ePath, { stdio: 'pipe' }) + let output = '' + subprocess.stdout.on('data', data => { + output += data + }) + subprocess.stdout.on('end', () => resolve(JSON.parse(output))) +}) + +// vue.config.cjs has higher priority + +test('load project options from package.json', async () => { + const output = await e2e() + expect(output).toBe('default') +}) + +test('load project options with import(vue.config.js)', async () => { + await writeFile(configPath, configData) + const output = await e2e() + await unlink(configPath) + expect(output).toBe(true) +}) + +test('load project options with import(vue.config.js) as a function', async () => { + await writeFile(configPath, functionConfigData) + const output = await e2e() + await unlink(configPath) + expect(output).toBe(true) +}) diff --git a/packages/@vue/cli-service/__tests__/mockESM/readConfig.cjs b/packages/@vue/cli-service/__tests__/mockESM/readConfig.cjs new file mode 100644 index 0000000000..9ebb648f09 --- /dev/null +++ b/packages/@vue/cli-service/__tests__/mockESM/readConfig.cjs @@ -0,0 +1,9 @@ +const Service = require('../../lib/Service') + +const service = new Service(__dirname, { + plugins: [], + useBuiltIn: false +}) +service.init() + +process.stdout.write(JSON.stringify(service.projectOptions.lintOnSave)) diff --git a/packages/@vue/cli-service/lib/Service.js b/packages/@vue/cli-service/lib/Service.js index c18a3ee410..e4d07bcb10 100644 --- a/packages/@vue/cli-service/lib/Service.js +++ b/packages/@vue/cli-service/lib/Service.js @@ -6,13 +6,15 @@ const PluginAPI = require('./PluginAPI') const dotenv = require('dotenv') const dotenvExpand = require('dotenv-expand') const defaultsDeep = require('lodash.defaultsdeep') -const deasync = require('deasync') const { chalk, warn, error, isPlugin, resolvePluginId, loadModule, resolvePkg } = require('@vue/cli-shared-utils') const { defaults, validate } = require('./options') -const loadConfig = configPath => { - let fileConfig = require(configPath) +const loadConfig = (configPath, esm) => { + if (esm) { + warn(`ECMAScript modules is enabled, config will be loaded with ${chalk.bold('import()')}`) + } + let fileConfig = esm ? importConfig(configPath) : require(configPath) if (typeof fileConfig === 'function') { fileConfig = fileConfig() @@ -316,43 +318,23 @@ module.exports = class Service { loadUserOptions () { // vue.config.js - // vue.config.cjs let fileConfig, pkgConfig, resolved, resolvedFrom const esm = this.pkg.type && this.pkg.type === 'module' const jsConfigPath = path.resolve(this.context, 'vue.config.js') - const cjsConfigPath = path.resolve(this.context, 'vue.config.cjs') const configPath = ( process.env.VUE_CLI_SERVICE_CONFIG_PATH || jsConfigPath ) try { - fileConfig = loadConfig(configPath) + fileConfig = loadConfig(configPath, esm) } catch (e) { - if (e.code !== 'MODULE_NOT_FOUND') { - if (e.code === 'ERR_REQUIRE_ESM') { - warn(`Rename ${chalk.bold('vue.config.js')} to ${chalk.bold('vue.config.cjs')} when ECMAScript modules is enabled`) - } + if (e.code !== 'MODULE_NOT_FOUND' && e.code !== 'ERR_MODULE_NOT_FOUND') { error(`Error loading ${chalk.bold('vue.config.js')}:`) throw e } } - // vue.config.js not found, esm enabled, no env set - if (!fileConfig && esm && !process.env.VUE_CLI_SERVICE_CONFIG_PATH) { - try { - fileConfig = loadConfig(cjsConfigPath) - } catch (e) { - if (e.code !== 'MODULE_NOT_FOUND') { - error(`Error loading ${chalk.bold('vue.config.cjs')}:`) - throw e - } - } - if (fileConfig) { - warn(`ECMAScript modules is detected, config loaded from ${chalk.bold('vue.config.cjs')}`) - } - } - // package.vue pkgConfig = this.pkg.vue if (pkgConfig && typeof pkgConfig !== 'object') { @@ -445,12 +427,13 @@ function cloneRuleNames (to, from) { } function importConfig (configPath) { + const deasync = require('deasync') let done = false let data let reject = false import(configPath) .then(result => { - data = result + data = result && result.default done = true }) .catch(reason => { @@ -462,7 +445,11 @@ function importConfig (configPath) { return !done }) if (reject) { - throw new Error(data) + if (data instanceof Error) { + throw data + } else { + throw data + } } - return data.default + return data } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy