Skip to content

Commit 142fc52

Browse files
committed
feat: add support for PNPM as a package manager
Enables vue-cli to use PNPM (https://pnpm.js.org/) as package manager
1 parent 60de7c4 commit 142fc52

File tree

13 files changed

+67
-29
lines changed

13 files changed

+67
-29
lines changed

packages/@vue/cli-service/lib/commands/serve.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const {
22
info,
33
hasYarn,
4+
hasPnpm,
45
openBrowser,
56
IpcMessenger
67
} = require('@vue/cli-shared-utils')
@@ -191,7 +192,7 @@ module.exports = (api, options) => {
191192
isFirstCompile = false
192193

193194
if (!isProduction) {
194-
const buildCommand = hasYarn() ? `yarn build` : `npm run build`
195+
const buildCommand = hasYarn() ? `yarn build` : hasPnpm() ? `pnpm run build` : `npm run build`
195196
console.log(` Note that the development build is not optimized.`)
196197
console.log(` To create a production build, run ${chalk.cyan(buildCommand)}.`)
197198
} else {

packages/@vue/cli-shared-utils/lib/env.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const { execSync } = require('child_process')
22

33
let _hasYarn
44
let _hasGit
5+
let _hasPnpm
56

67
// env detection
78
exports.hasYarn = () => {
@@ -33,3 +34,18 @@ exports.hasGit = () => {
3334
return (_hasGit = false)
3435
}
3536
}
37+
38+
exports.hasPnpm = () => {
39+
if (process.env.VUE_CLI_TEST) {
40+
return false
41+
}
42+
if (_hasPnpm != null) {
43+
return _hasPnpm
44+
}
45+
try {
46+
execSync('pnpm --version', { stdio: 'ignore' })
47+
return (_hasPnpm = true)
48+
} catch (e) {
49+
return (_hasPnpm = false)
50+
}
51+
}

packages/@vue/cli-ui/src/graphql-api/type-defs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ scalar JSON
88
enum PackageManager {
99
npm
1010
yarn
11+
pnpm
1112
}
1213
1314
interface DescribedEntity {
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
const {
2-
hasYarn
2+
hasYarn,
3+
hasPnpm
34
} = require('@vue/cli-shared-utils')
45
const { loadOptions } = require('@vue/cli/lib/options')
56

67
exports.getCommand = function () {
7-
return loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
8+
return loadOptions().packageManager || (hasYarn() ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm')
89
}

packages/@vue/cli-ui/src/views/ProjectCreate.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
value="yarn"
7171
label="yarn"
7272
/>
73+
<VueSelectButton
74+
value="pnpm"
75+
label="pnpm"
76+
/>
7377
</VueSelect>
7478
</VueFormField>
7579

packages/@vue/cli/__tests__/Creator.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ test('default', async () => {
1616
},
1717
{
1818
message: 'package manager',
19-
choices: ['Yarn', 'NPM'],
19+
choices: ['Yarn', 'NPM', 'PNPM'],
2020
choose: 0
2121
}
2222
]

packages/@vue/cli/lib/Creator.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const {
3030
error,
3131
hasGit,
3232
hasYarn,
33+
hasPnpm,
3334
logWithSpinner,
3435
stopSpinner,
3536
exit
@@ -91,7 +92,7 @@ module.exports = class Creator extends EventEmitter {
9192
const packageManager = (
9293
cliOptions.packageManager ||
9394
loadOptions().packageManager ||
94-
(hasYarn() ? 'yarn' : 'npm')
95+
(hasYarn() ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm')
9596
)
9697

9798
await clearConsole()
@@ -191,7 +192,7 @@ module.exports = class Creator extends EventEmitter {
191192
log(
192193
`👉 Get started with the following commands:\n\n` +
193194
(this.context === process.cwd() ? `` : chalk.cyan(` ${chalk.gray('$')} cd ${name}\n`)) +
194-
chalk.cyan(` ${chalk.gray('$')} ${packageManager === 'yarn' ? 'yarn serve' : 'npm run serve'}`)
195+
chalk.cyan(` ${chalk.gray('$')} ${packageManager === 'yarn' ? 'yarn serve' : packageManager === 'pnpm' ? 'pnpm run serve' : 'npm run serve'}`)
195196
)
196197
log()
197198
this.emit('creation', { event: 'done' })
@@ -388,23 +389,34 @@ module.exports = class Creator extends EventEmitter {
388389

389390
// ask for packageManager once
390391
const savedOptions = loadOptions()
391-
if (!savedOptions.packageManager && hasYarn()) {
392+
if (!savedOptions.packageManager && (hasYarn() || hasPnpm())) {
393+
const packageManagerChoices = [{
394+
name: 'Use NPM',
395+
value: 'npm',
396+
short: 'NPM'
397+
}]
398+
399+
if (hasYarn()) {
400+
packageManagerChoices.push({
401+
name: 'Use Yarn',
402+
value: 'yarn',
403+
short: 'Yarn'
404+
})
405+
}
406+
407+
if (hasPnpm()) {
408+
packageManagerChoices.push({
409+
name: 'Use PNPM',
410+
value: 'pnpm',
411+
short: 'PNPM'
412+
})
413+
}
414+
392415
outroPrompts.push({
393416
name: 'packageManager',
394417
type: 'list',
395418
message: 'Pick the package manager to use when installing dependencies:',
396-
choices: [
397-
{
398-
name: 'Use Yarn',
399-
value: 'yarn',
400-
short: 'Yarn'
401-
},
402-
{
403-
name: 'Use NPM',
404-
value: 'npm',
405-
short: 'NPM'
406-
}
407-
]
419+
choices: packageManagerChoices
408420
})
409421
}
410422

packages/@vue/cli/lib/add.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const {
77
log,
88
error,
99
hasYarn,
10+
hasPnpm,
1011
stopSpinner,
1112
resolvePluginId
1213
} = require('@vue/cli-shared-utils')
@@ -26,7 +27,7 @@ async function add (pluginName, options = {}, context = process.cwd()) {
2627
log(`📦 Installing ${chalk.cyan(packageName)}...`)
2728
log()
2829

29-
const packageManager = loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
30+
const packageManager = loadOptions().packageManager || (hasYarn() ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm')
3031
await installPackage(context, packageManager, null, packageName)
3132

3233
stopSpinner()

packages/@vue/cli/lib/invoke.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const {
1414
log,
1515
error,
1616
hasYarn,
17+
hasPnpm,
1718
hasGit,
1819
logWithSpinner,
1920
stopSpinner,
@@ -121,7 +122,7 @@ async function runGenerator (context, plugin, pkg = getPkg(context)) {
121122
if (!isTestOrDebug && depsChanged) {
122123
log(`📦 Installing additional dependencies...`)
123124
const packageManager =
124-
loadOptions().packageManager || (hasYarn() ? 'yarn' : 'npm')
125+
loadOptions().packageManager || (hasYarn() ? 'yarn' : hasPnpm() ? 'pnpm' : 'npm')
125126
await installDeps(context, packageManager)
126127
}
127128

packages/@vue/cli/lib/options.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const presetSchema = createSchema(joi => joi.object().keys({
3535
}))
3636

3737
const schema = createSchema(joi => joi.object().keys({
38-
packageManager: joi.string().only(['yarn', 'npm']),
38+
packageManager: joi.string().only(['yarn', 'npm', 'pnpm']),
3939
useTaobaoRegistry: joi.boolean(),
4040
presets: joi.object().pattern(/^/, presetSchema)
4141
}))

packages/@vue/cli/lib/util/installDeps.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ function executeCommand (command, args, targetDir) {
172172

173173
exports.installDeps = async function installDeps (targetDir, command, cliRegistry) {
174174
const args = []
175-
if (command === 'npm') {
175+
if (command === 'npm' || command === 'pnpm') {
176176
args.push('install', '--loglevel', 'error')
177177
} else if (command === 'yarn') {
178178
// do nothing
@@ -190,7 +190,7 @@ exports.installDeps = async function installDeps (targetDir, command, cliRegistr
190190

191191
exports.installPackage = async function (targetDir, command, cliRegistry, packageName, dev = true) {
192192
const args = []
193-
if (command === 'npm') {
193+
if (command === 'npm' || command === 'pnpm') {
194194
args.push('install', '--loglevel', 'error')
195195
} else if (command === 'yarn') {
196196
args.push('add')
@@ -212,7 +212,7 @@ exports.installPackage = async function (targetDir, command, cliRegistry, packag
212212

213213
exports.uninstallPackage = async function (targetDir, command, cliRegistry, packageName) {
214214
const args = []
215-
if (command === 'npm') {
215+
if (command === 'npm' || command === 'pnpm') {
216216
args.push('uninstall', '--loglevel', 'error')
217217
} else if (command === 'yarn') {
218218
args.push('remove')
@@ -232,7 +232,7 @@ exports.uninstallPackage = async function (targetDir, command, cliRegistry, pack
232232

233233
exports.updatePackage = async function (targetDir, command, cliRegistry, packageName) {
234234
const args = []
235-
if (command === 'npm') {
235+
if (command === 'npm' || command === 'pnpm') {
236236
args.push('update', '--loglevel', 'error')
237237
} else if (command === 'yarn') {
238238
args.push('upgrade')

packages/@vue/cli/lib/util/loadCommand.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ module.exports = function loadCommand (commandName, moduleName) {
1111
} catch (err2) {
1212
if (isNotFoundError(err2)) {
1313
const chalk = require('chalk')
14-
const { hasYarn } = require('@vue/cli-shared-utils')
15-
const installCommand = hasYarn() ? `yarn global add` : `npm install -g`
14+
const { hasYarn, hasPnpm } = require('@vue/cli-shared-utils')
15+
const installCommand = hasYarn() ? `yarn global add` : hasPnpm() ? `pnpm install -g` : `npm install -g`
1616
console.log()
1717
console.log(
1818
` Command ${chalk.cyan(`vue ${commandName}`)} requires a global addon to be installed.\n` +
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
const registries = {
22
npm: 'https://registry.npmjs.org',
33
yarn: 'https://registry.yarnpkg.com',
4-
taobao: 'https://registry.npm.taobao.org'
4+
taobao: 'https://registry.npm.taobao.org',
5+
pnpm: 'https://registry.npmjs.org'
56
}
67

78
module.exports = registries

0 commit comments

Comments
 (0)