diff --git a/packages/@vue/cli-service/lib/commands/serve.js b/packages/@vue/cli-service/lib/commands/serve.js index d90e442250..26b2a3f37a 100644 --- a/packages/@vue/cli-service/lib/commands/serve.js +++ b/packages/@vue/cli-service/lib/commands/serve.js @@ -1,7 +1,7 @@ const { info, hasProjectYarn, - hasPnpm, + hasProjectPnpm, openBrowser, IpcMessenger } = require('@vue/cli-shared-utils') @@ -235,7 +235,7 @@ module.exports = (api, options) => { isFirstCompile = false if (!isProduction) { - const buildCommand = hasProjectYarn(api.getCwd()) ? `yarn build` : hasPnpm() ? `pnpm run build` : `npm run build` + const buildCommand = hasProjectYarn(api.getCwd()) ? `yarn build` : hasProjectPnpm(api.getCwd()) ? `pnpm run build` : `npm run build` console.log(` Note that the development build is not optimized.`) console.log(` To create a production build, run ${chalk.cyan(buildCommand)}.`) } else { diff --git a/packages/@vue/cli-shared-utils/lib/env.js b/packages/@vue/cli-shared-utils/lib/env.js index 84673f6567..64d51dd224 100644 --- a/packages/@vue/cli-shared-utils/lib/env.js +++ b/packages/@vue/cli-shared-utils/lib/env.js @@ -14,7 +14,6 @@ const _gitProjects = new LRU({ max: 10, maxAge: 1000 }) -let _hasPnpm // env detection exports.hasYarn = () => { @@ -79,25 +78,51 @@ exports.hasProjectGit = (cwd) => { return result } -exports.hasPnpm = () => { +let _hasPnpm +let _hasPnpm3orLater +const _pnpmProjects = new LRU({ + max: 10, + maxAge: 1000 +}) + +exports.hasPnpm3OrLater = () => { if (process.env.VUE_CLI_TEST) { return true } - if (_hasPnpm != null) { - return _hasPnpm + if (_hasPnpm3orLater != null) { + return _hasPnpm3orLater } try { const pnpmVersion = execSync('pnpm --version').toString() // there's a critical bug in pnpm 2 // https://github.com/pnpm/pnpm/issues/1678#issuecomment-469981972 // so we only support pnpm >= 3.0.0 - _hasPnpm = semver.gte(pnpmVersion, '3.0.0') - return _hasPnpm + _hasPnpm = true + _hasPnpm3orLater = semver.gte(pnpmVersion, '3.0.0') + return _hasPnpm3orLater } catch (e) { - return (_hasPnpm = false) + return (_hasPnpm3orLater = false) } } +exports.hasProjectPnpm = (cwd) => { + if (_pnpmProjects.has(cwd)) { + return checkPnpm(_pnpmProjects.get(cwd)) + } + + const lockFile = path.join(cwd, 'pnpm-lock.yaml') + const result = fs.existsSync(lockFile) + _pnpmProjects.set(cwd, result) + return checkPnpm(result) +} + +function checkPnpm (result) { + if (result && !exports.hasPnpm3OrLater()) { + throw new Error(`The project seems to require pnpm${_hasPnpm ? ' >= 3' : ''} but it's not installed.`) + } + return result +} + // OS exports.isWindows = process.platform === 'win32' exports.isMacintosh = process.platform === 'darwin' diff --git a/packages/@vue/cli-ui/apollo-server/util/command.js b/packages/@vue/cli-ui/apollo-server/util/command.js index 4cbc7507d3..aad7e14a11 100644 --- a/packages/@vue/cli-ui/apollo-server/util/command.js +++ b/packages/@vue/cli-ui/apollo-server/util/command.js @@ -1,13 +1,14 @@ const { hasYarn, hasProjectYarn, - hasPnpm + hasPnpm3OrLater, + hasProjectPnpm } = require('@vue/cli-shared-utils') const { loadOptions } = require('@vue/cli/lib/options') exports.getCommand = function (cwd = undefined) { if (!cwd) { - return loadOptions().packageManager || (hasYarn() ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm') + return loadOptions().packageManager || (hasYarn() ? 'yarn' : hasPnpm3OrLater() ? 'pnpm' : 'npm') } - return hasProjectYarn(cwd) ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm' + return hasProjectYarn(cwd) ? 'yarn' : hasProjectPnpm() ? 'pnpm' : 'npm' } diff --git a/packages/@vue/cli-ui/src/components/file-diff/FileDiffView.vue b/packages/@vue/cli-ui/src/components/file-diff/FileDiffView.vue index b33246030e..ba1436e347 100644 --- a/packages/@vue/cli-ui/src/components/file-diff/FileDiffView.vue +++ b/packages/@vue/cli-ui/src/components/file-diff/FileDiffView.vue @@ -133,6 +133,7 @@ import GIT_COMMIT from '@/graphql/git/gitCommit.gql' const defaultCollapsed = [ 'yarn.lock', + 'pnpm-lock.yaml', 'package-lock.json' ] diff --git a/packages/@vue/cli/lib/Creator.js b/packages/@vue/cli/lib/Creator.js index 1cd6014fa4..c32f58f4cc 100644 --- a/packages/@vue/cli/lib/Creator.js +++ b/packages/@vue/cli/lib/Creator.js @@ -33,7 +33,7 @@ const { hasGit, hasProjectGit, hasYarn, - hasPnpm, + hasPnpm3OrLater, logWithSpinner, stopSpinner, exit, @@ -99,7 +99,7 @@ module.exports = class Creator extends EventEmitter { cliOptions.packageManager || loadOptions().packageManager || (hasYarn() ? 'yarn' : null) || - (hasPnpm() ? 'pnpm' : 'npm') + (hasPnpm3OrLater() ? 'pnpm' : 'npm') ) await clearConsole() @@ -192,6 +192,13 @@ module.exports = class Creator extends EventEmitter { 'README.md': generateReadme(generator.pkg, packageManager) }) + // generate a .npmrc file for pnpm, to persist the `shamefully-flatten` flag + if (packageManager === 'pnpm') { + await writeFileTree(context, { + '.npmrc': 'shamefully-flatten=true\n' + }) + } + // commit initial state let gitCommitFailed = false if (shouldInitGit) { @@ -412,7 +419,7 @@ module.exports = class Creator extends EventEmitter { // ask for packageManager once const savedOptions = loadOptions() - if (!savedOptions.packageManager && (hasYarn() || hasPnpm())) { + if (!savedOptions.packageManager && (hasYarn() || hasPnpm3OrLater())) { const packageManagerChoices = [] if (hasYarn()) { @@ -423,7 +430,7 @@ module.exports = class Creator extends EventEmitter { }) } - if (hasPnpm()) { + if (hasPnpm3OrLater()) { packageManagerChoices.push({ name: 'Use PNPM', value: 'pnpm', diff --git a/packages/@vue/cli/lib/add.js b/packages/@vue/cli/lib/add.js index 2fa0a0febc..b4d3698f41 100644 --- a/packages/@vue/cli/lib/add.js +++ b/packages/@vue/cli/lib/add.js @@ -6,7 +6,7 @@ const { log, error, hasProjectYarn, - hasPnpm, + hasProjectPnpm, resolvePluginId, resolveModule, loadModule @@ -27,7 +27,7 @@ async function add (pluginName, options = {}, context = process.cwd()) { log(`📦 Installing ${chalk.cyan(packageName)}...`) log() - const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm') + const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : hasProjectPnpm() ? 'pnpm' : 'npm') await installPackage(context, packageManager, options.registry, packageName) log(`${chalk.green('✔')} Successfully installed plugin: ${chalk.cyan(packageName)}`) diff --git a/packages/@vue/cli/lib/invoke.js b/packages/@vue/cli/lib/invoke.js index 553de1f04f..b478c0db33 100644 --- a/packages/@vue/cli/lib/invoke.js +++ b/packages/@vue/cli/lib/invoke.js @@ -14,7 +14,7 @@ const { error, hasProjectYarn, hasProjectGit, - hasPnpm, + hasProjectPnpm, logWithSpinner, stopSpinner, resolvePluginId, @@ -145,7 +145,7 @@ async function runGenerator (context, plugin, pkg = getPkg(context)) { log(`📦 Installing additional dependencies...`) log() const packageManager = - loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm') + loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : hasProjectPnpm() ? 'pnpm' : 'npm') await installDeps(context, packageManager, plugin.options && plugin.options.registry) } diff --git a/packages/@vue/cli/lib/util/installDeps.js b/packages/@vue/cli/lib/util/installDeps.js index 03c443434e..8c5613453c 100644 --- a/packages/@vue/cli/lib/util/installDeps.js +++ b/packages/@vue/cli/lib/util/installDeps.js @@ -182,6 +182,10 @@ exports.installDeps = async function installDeps (targetDir, command, cliRegistr // do nothing } + if (command === 'pnpm') { + args.push('--shamefully-flatten') + } + await addRegistryToArgs(command, args, cliRegistry) debug(`command: `, command) diff --git a/packages/@vue/cli/lib/util/loadCommand.js b/packages/@vue/cli/lib/util/loadCommand.js index c5e764c9b8..1253bbcb69 100644 --- a/packages/@vue/cli/lib/util/loadCommand.js +++ b/packages/@vue/cli/lib/util/loadCommand.js @@ -11,11 +11,11 @@ module.exports = function loadCommand (commandName, moduleName) { } catch (err2) { if (isNotFoundError(err2)) { const chalk = require('chalk') - const { hasYarn, hasPnpm } = require('@vue/cli-shared-utils') + const { hasYarn, hasPnpm3OrLater } = require('@vue/cli-shared-utils') let installCommand = `npm install -g` if (hasYarn()) { installCommand = `yarn global add` - } else if (hasPnpm()) { + } else if (hasPnpm3OrLater()) { installCommand = `pnpm install -g` } console.log()