mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-04-26 14:58:30 -05:00
feat: support PNPM as a package manager (#1531)
Enables vue-cli to use PNPM (https://pnpm.js.org/) as package manager
This commit is contained in:
committed by
Haoqun Jiang
parent
a88203d3c2
commit
a02ef3988f
@@ -1,6 +1,7 @@
|
||||
const {
|
||||
info,
|
||||
hasProjectYarn,
|
||||
hasPnpm,
|
||||
openBrowser,
|
||||
IpcMessenger
|
||||
} = require('@vue/cli-shared-utils')
|
||||
@@ -234,7 +235,7 @@ module.exports = (api, options) => {
|
||||
isFirstCompile = false
|
||||
|
||||
if (!isProduction) {
|
||||
const buildCommand = hasProjectYarn(api.getCwd()) ? `yarn build` : `npm run build`
|
||||
const buildCommand = hasProjectYarn(api.getCwd()) ? `yarn build` : hasPnpm() ? `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 {
|
||||
|
||||
@@ -2,6 +2,7 @@ const { execSync } = require('child_process')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const LRU = require('lru-cache')
|
||||
const semver = require('semver')
|
||||
|
||||
let _hasYarn
|
||||
const _yarnProjects = new LRU({
|
||||
@@ -13,6 +14,7 @@ const _gitProjects = new LRU({
|
||||
max: 10,
|
||||
maxAge: 1000
|
||||
})
|
||||
let _hasPnpm
|
||||
|
||||
// env detection
|
||||
exports.hasYarn = () => {
|
||||
@@ -77,6 +79,25 @@ exports.hasProjectGit = (cwd) => {
|
||||
return result
|
||||
}
|
||||
|
||||
exports.hasPnpm = () => {
|
||||
if (process.env.VUE_CLI_TEST) {
|
||||
return true
|
||||
}
|
||||
if (_hasPnpm != null) {
|
||||
return _hasPnpm
|
||||
}
|
||||
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
|
||||
} catch (e) {
|
||||
return (_hasPnpm = false)
|
||||
}
|
||||
}
|
||||
|
||||
// OS
|
||||
exports.isWindows = process.platform === 'win32'
|
||||
exports.isMacintosh = process.platform === 'darwin'
|
||||
|
||||
@@ -8,6 +8,7 @@ scalar JSON
|
||||
enum PackageManager {
|
||||
npm
|
||||
yarn
|
||||
pnpm
|
||||
}
|
||||
|
||||
interface DescribedEntity {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
const {
|
||||
hasYarn,
|
||||
hasProjectYarn
|
||||
hasProjectYarn,
|
||||
hasPnpm
|
||||
} = require('@vue/cli-shared-utils')
|
||||
const { loadOptions } = require('@vue/cli/lib/options')
|
||||
|
||||
exports.getCommand = function (cwd = undefined) {
|
||||
if (!cwd) {
|
||||
return loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
|
||||
return loadOptions().packageManager || (hasYarn() ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm')
|
||||
}
|
||||
return hasProjectYarn(cwd) ? 'yarn' : 'npm'
|
||||
return hasProjectYarn(cwd) ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm'
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@
|
||||
value="yarn"
|
||||
label="yarn"
|
||||
/>
|
||||
<VueSelectButton
|
||||
value="pnpm"
|
||||
label="pnpm"
|
||||
/>
|
||||
</VueSelect>
|
||||
</VueFormField>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ test('default', async () => {
|
||||
},
|
||||
{
|
||||
message: 'package manager',
|
||||
choices: ['Yarn', 'NPM'],
|
||||
choices: ['Yarn', 'PNPM', 'NPM'],
|
||||
choose: 0
|
||||
}
|
||||
]
|
||||
|
||||
@@ -33,6 +33,7 @@ const {
|
||||
hasGit,
|
||||
hasProjectGit,
|
||||
hasYarn,
|
||||
hasPnpm,
|
||||
logWithSpinner,
|
||||
stopSpinner,
|
||||
exit,
|
||||
@@ -97,7 +98,8 @@ module.exports = class Creator extends EventEmitter {
|
||||
const packageManager = (
|
||||
cliOptions.packageManager ||
|
||||
loadOptions().packageManager ||
|
||||
(hasYarn() ? 'yarn' : 'npm')
|
||||
(hasYarn() ? 'yarn' : null) ||
|
||||
(hasPnpm() ? 'pnpm' : 'npm')
|
||||
)
|
||||
|
||||
await clearConsole()
|
||||
@@ -214,7 +216,7 @@ module.exports = class Creator extends EventEmitter {
|
||||
log(
|
||||
`👉 Get started with the following commands:\n\n` +
|
||||
(this.context === process.cwd() ? `` : chalk.cyan(` ${chalk.gray('$')} cd ${name}\n`)) +
|
||||
chalk.cyan(` ${chalk.gray('$')} ${packageManager === 'yarn' ? 'yarn serve' : 'npm run serve'}`)
|
||||
chalk.cyan(` ${chalk.gray('$')} ${packageManager === 'yarn' ? 'yarn serve' : packageManager === 'pnpm' ? 'pnpm run serve' : 'npm run serve'}`)
|
||||
)
|
||||
}
|
||||
log()
|
||||
@@ -410,23 +412,36 @@ module.exports = class Creator extends EventEmitter {
|
||||
|
||||
// ask for packageManager once
|
||||
const savedOptions = loadOptions()
|
||||
if (!savedOptions.packageManager && hasYarn()) {
|
||||
if (!savedOptions.packageManager && (hasYarn() || hasPnpm())) {
|
||||
const packageManagerChoices = []
|
||||
|
||||
if (hasYarn()) {
|
||||
packageManagerChoices.push({
|
||||
name: 'Use Yarn',
|
||||
value: 'yarn',
|
||||
short: 'Yarn'
|
||||
})
|
||||
}
|
||||
|
||||
if (hasPnpm()) {
|
||||
packageManagerChoices.push({
|
||||
name: 'Use PNPM',
|
||||
value: 'pnpm',
|
||||
short: 'PNPM'
|
||||
})
|
||||
}
|
||||
|
||||
packageManagerChoices.push({
|
||||
name: 'Use NPM',
|
||||
value: 'npm',
|
||||
short: 'NPM'
|
||||
})
|
||||
|
||||
outroPrompts.push({
|
||||
name: 'packageManager',
|
||||
type: 'list',
|
||||
message: 'Pick the package manager to use when installing dependencies:',
|
||||
choices: [
|
||||
{
|
||||
name: 'Use Yarn',
|
||||
value: 'yarn',
|
||||
short: 'Yarn'
|
||||
},
|
||||
{
|
||||
name: 'Use NPM',
|
||||
value: 'npm',
|
||||
short: 'NPM'
|
||||
}
|
||||
]
|
||||
choices: packageManagerChoices
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ const {
|
||||
log,
|
||||
error,
|
||||
hasProjectYarn,
|
||||
hasPnpm,
|
||||
resolvePluginId,
|
||||
resolveModule,
|
||||
loadModule
|
||||
@@ -26,7 +27,7 @@ async function add (pluginName, options = {}, context = process.cwd()) {
|
||||
log(`📦 Installing ${chalk.cyan(packageName)}...`)
|
||||
log()
|
||||
|
||||
const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : 'npm')
|
||||
const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm')
|
||||
await installPackage(context, packageManager, options.registry, packageName)
|
||||
|
||||
log(`${chalk.green('✔')} Successfully installed plugin: ${chalk.cyan(packageName)}`)
|
||||
|
||||
@@ -14,6 +14,7 @@ const {
|
||||
error,
|
||||
hasProjectYarn,
|
||||
hasProjectGit,
|
||||
hasPnpm,
|
||||
logWithSpinner,
|
||||
stopSpinner,
|
||||
resolvePluginId,
|
||||
@@ -138,7 +139,7 @@ async function runGenerator (context, plugin, pkg = getPkg(context)) {
|
||||
log(`📦 Installing additional dependencies...`)
|
||||
log()
|
||||
const packageManager =
|
||||
loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : 'npm')
|
||||
loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm')
|
||||
await installDeps(context, packageManager, plugin.options && plugin.options.registry)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ const presetSchema = createSchema(joi => joi.object().keys({
|
||||
const schema = createSchema(joi => joi.object().keys({
|
||||
latestVersion: joi.string().regex(/^\d+\.\d+\.\d+$/),
|
||||
lastChecked: joi.date().timestamp(),
|
||||
packageManager: joi.string().only(['yarn', 'npm']),
|
||||
packageManager: joi.string().only(['yarn', 'npm', 'pnpm']),
|
||||
useTaobaoRegistry: joi.boolean(),
|
||||
presets: joi.object().pattern(/^/, presetSchema)
|
||||
}))
|
||||
|
||||
@@ -9,7 +9,7 @@ const debug = require('debug')('vue-cli:install')
|
||||
|
||||
const taobaoDistURL = 'https://npm.taobao.org/dist'
|
||||
|
||||
const supportPackageManagerList = ['npm', 'yarn']
|
||||
const supportPackageManagerList = ['npm', 'yarn', 'pnpm']
|
||||
|
||||
class InstallProgress extends EventEmitter {
|
||||
constructor () {
|
||||
@@ -176,7 +176,7 @@ exports.installDeps = async function installDeps (targetDir, command, cliRegistr
|
||||
|
||||
const args = []
|
||||
|
||||
if (command === 'npm') {
|
||||
if (command === 'npm' || command === 'pnpm') {
|
||||
args.push('install', '--loglevel', 'error')
|
||||
} else if (command === 'yarn') {
|
||||
// do nothing
|
||||
@@ -195,7 +195,7 @@ exports.installPackage = async function (targetDir, command, cliRegistry, packag
|
||||
|
||||
const args = []
|
||||
|
||||
if (command === 'npm') {
|
||||
if (command === 'npm' || command === 'pnpm') {
|
||||
args.push('install', '--loglevel', 'error')
|
||||
} else if (command === 'yarn') {
|
||||
args.push('add')
|
||||
@@ -218,7 +218,7 @@ exports.uninstallPackage = async function (targetDir, command, cliRegistry, pack
|
||||
|
||||
const args = []
|
||||
|
||||
if (command === 'npm') {
|
||||
if (command === 'npm' || command === 'pnpm') {
|
||||
args.push('uninstall', '--loglevel', 'error')
|
||||
} else if (command === 'yarn') {
|
||||
args.push('remove')
|
||||
@@ -239,7 +239,7 @@ exports.updatePackage = async function (targetDir, command, cliRegistry, package
|
||||
|
||||
const args = []
|
||||
|
||||
if (command === 'npm') {
|
||||
if (command === 'npm' || command === 'pnpm') {
|
||||
args.push('update', '--loglevel', 'error')
|
||||
} else if (command === 'yarn') {
|
||||
args.push('upgrade')
|
||||
|
||||
@@ -11,8 +11,13 @@ module.exports = function loadCommand (commandName, moduleName) {
|
||||
} catch (err2) {
|
||||
if (isNotFoundError(err2)) {
|
||||
const chalk = require('chalk')
|
||||
const { hasYarn } = require('@vue/cli-shared-utils')
|
||||
const installCommand = hasYarn() ? `yarn global add` : `npm install -g`
|
||||
const { hasYarn, hasPnpm } = require('@vue/cli-shared-utils')
|
||||
let installCommand = `npm install -g`
|
||||
if (hasYarn()) {
|
||||
installCommand = `yarn global add`
|
||||
} else if (hasPnpm()) {
|
||||
installCommand = `pnpm install -g`
|
||||
}
|
||||
console.log()
|
||||
console.log(
|
||||
` Command ${chalk.cyan(`vue ${commandName}`)} requires a global addon to be installed.\n` +
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
const registries = {
|
||||
npm: 'https://registry.npmjs.org',
|
||||
yarn: 'https://registry.yarnpkg.com',
|
||||
taobao: 'https://registry.npm.taobao.org'
|
||||
taobao: 'https://registry.npm.taobao.org',
|
||||
pnpm: 'https://registry.npmjs.org'
|
||||
}
|
||||
|
||||
module.exports = registries
|
||||
|
||||
Reference in New Issue
Block a user