mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-02-12 18:08:35 -06:00
122 lines
3.2 KiB
JavaScript
122 lines
3.2 KiB
JavaScript
const { URL } = require('url')
|
|
const https = require('https')
|
|
const chalk = require('chalk')
|
|
const inquirer = require('inquirer')
|
|
const { promisify } = require('util')
|
|
const { spawn, exec } = require('child_process')
|
|
const { savePartialOptions } = require('../options')
|
|
const { stopSpinner, logWithSpinner } = require('@vue/cli-shared-utils')
|
|
|
|
const SLOW_THRESHOLD = 1000
|
|
const taobaoRegistry = 'https://registry.npm.taobao.org'
|
|
const taobaoDistURL = 'https://npm.taobao.org/dist'
|
|
const defaultRegistry = {
|
|
npm: 'https://registry.npmjs.org',
|
|
yarn: 'https://registry.yarnpkg.com'
|
|
}
|
|
|
|
const ping = promisify((host, cb) => {
|
|
const start = Date.now()
|
|
const req = https.request({
|
|
hostname: new URL(host).hostname
|
|
}, () => {
|
|
cb(null, Date.now() - start)
|
|
})
|
|
req.on('error', cb)
|
|
req.end()
|
|
})
|
|
|
|
const checkRegistrySwitch = async (command) => {
|
|
const { stdout } = await promisify(exec)(`${command} config get registry`)
|
|
const currentRegistry = stdout.toString().trim()
|
|
// if user has set custom registry, ignore
|
|
if (currentRegistry.replace(/\/$/, '') !== defaultRegistry[command]) {
|
|
return false
|
|
}
|
|
const latency = await ping(currentRegistry)
|
|
if (latency > SLOW_THRESHOLD) {
|
|
const tbLatency = await ping(taobaoRegistry)
|
|
if (tbLatency < latency) {
|
|
stopSpinner(false)
|
|
console.log()
|
|
const { use } = await inquirer.prompt([{
|
|
name: 'use',
|
|
type: 'confirm',
|
|
message: chalk.yellow(
|
|
` Your connection to the default ${command} registry is quite slow (${chalk.red(`${latency}ms`)}).\n` +
|
|
` Use the Taobao mirror (${chalk.green(`${tbLatency}ms`)}) for faster installation?`
|
|
)
|
|
}])
|
|
console.log()
|
|
|
|
savePartialOptions({
|
|
useTaobaoRegistry: use
|
|
})
|
|
|
|
logWithSpinner('⚙', `Installing CLI plugins. This might take a while...`)
|
|
return use
|
|
}
|
|
}
|
|
}
|
|
|
|
let isFirstCall = false
|
|
let shouldUseTaobao
|
|
module.exports = async function installDeps (targetDir, options, deps) {
|
|
const command = options.packageManager
|
|
|
|
if (!isFirstCall) {
|
|
isFirstCall = true
|
|
shouldUseTaobao = typeof options.useTaobaoRegistry === 'boolean'
|
|
? options.useTaobaoRegistry
|
|
: await checkRegistrySwitch(command)
|
|
}
|
|
|
|
await new Promise((resolve, reject) => {
|
|
const args = []
|
|
if (command === 'npm') {
|
|
args.push('install', '--loglevel', 'error')
|
|
if (deps) {
|
|
args.push('--save-dev')
|
|
}
|
|
} else if (command === 'yarn') {
|
|
if (deps) {
|
|
args.push('add', '--dev')
|
|
}
|
|
} else {
|
|
throw new Error(`unknown package manager: ${command}`)
|
|
}
|
|
|
|
if (shouldUseTaobao) {
|
|
args.push(`--registry=${taobaoRegistry}`)
|
|
if (command === 'npm') {
|
|
args.push(`--disturl=${taobaoDistURL}`)
|
|
}
|
|
}
|
|
|
|
if (deps) {
|
|
args.push.apply(args, deps)
|
|
}
|
|
|
|
const child = spawn(command, args, {
|
|
cwd: targetDir,
|
|
stdio: 'pipe'
|
|
})
|
|
|
|
let stderr = ''
|
|
child.stderr.on('data', buf => {
|
|
stderr += buf.toString()
|
|
})
|
|
|
|
child.on('close', code => {
|
|
if (code !== 0) {
|
|
reject(
|
|
`command failed: ${command} ${args.join(' ')}\n` +
|
|
stderr
|
|
)
|
|
return
|
|
}
|
|
resolve()
|
|
})
|
|
})
|
|
}
|