mirror of
https://github.com/vuejs/vue-cli.git
synced 2026-03-12 20:19:55 -05:00
feat: lock minor versions when creating projects / adding plugins (#5134)
* feat: lock minor versions when creating projects / adding plugins closes #5012 * refactor: also calculate latestMinor version * feat: support add packages with tilde version range * refactor: make the `runCommand` invocations more concise * refactor: use the `getVersions` utility function to get latestMinor * feat: when adding plugins, use tilde range by default * fix: allow empty args
This commit is contained in:
@@ -188,7 +188,10 @@ function install ({ id, type, range }, context) {
|
||||
}
|
||||
|
||||
const pm = new PackageManager({ context: cwd.get() })
|
||||
await pm.add(arg, type === 'devDependencies')
|
||||
await pm.add(arg, {
|
||||
tilde: !range && isPlugin(id),
|
||||
dev: type === 'devDependencies'
|
||||
})
|
||||
|
||||
logs.add({
|
||||
message: `Dependency ${id} installed`,
|
||||
|
||||
@@ -27,7 +27,6 @@ const {
|
||||
const {
|
||||
chalk,
|
||||
execa,
|
||||
semver,
|
||||
|
||||
log,
|
||||
warn,
|
||||
@@ -129,19 +128,9 @@ module.exports = class Creator extends EventEmitter {
|
||||
logWithSpinner(`✨`, `Creating project in ${chalk.yellow(context)}.`)
|
||||
this.emit('creation', { event: 'creating' })
|
||||
|
||||
// get latest CLI version
|
||||
const { current, latest } = await getVersions()
|
||||
let latestMinor = `${semver.major(latest)}.${semver.minor(latest)}.0`
|
||||
// get latest CLI plugin version
|
||||
const { latestMinor } = await getVersions()
|
||||
|
||||
if (
|
||||
// if the latest version contains breaking changes
|
||||
/major/.test(semver.diff(current, latest)) ||
|
||||
// or if using `next` branch of cli
|
||||
(semver.gte(current, latest) && semver.prerelease(current))
|
||||
) {
|
||||
// fallback to the current cli version number
|
||||
latestMinor = current
|
||||
}
|
||||
// generate package.json with plugin dependencies
|
||||
const pkg = {
|
||||
name,
|
||||
@@ -161,7 +150,7 @@ module.exports = class Creator extends EventEmitter {
|
||||
// Other `@vue/*` packages' version may not be in sync with the cli itself.
|
||||
pkg.devDependencies[dep] = (
|
||||
preset.plugins[dep].version ||
|
||||
((/^@vue/.test(dep)) ? `^${latestMinor}` : `latest`)
|
||||
((/^@vue/.test(dep)) ? `~${latestMinor}` : `latest`)
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ module.exports = class Upgrader {
|
||||
if (targetVersion === installed) {
|
||||
log(`Already installed ${packageName}@${targetVersion}`)
|
||||
|
||||
const newRange = tryGetNewerRange(`^${targetVersion}`, required)
|
||||
const newRange = tryGetNewerRange(`~${targetVersion}`, required)
|
||||
if (newRange !== required) {
|
||||
this.pkg[depEntry][packageName] = newRange
|
||||
fs.writeFileSync(path.resolve(this.context, 'package.json'), JSON.stringify(this.pkg, null, 2))
|
||||
@@ -103,10 +103,10 @@ module.exports = class Upgrader {
|
||||
}
|
||||
|
||||
log(`Upgrading ${packageName} from ${installed} to ${targetVersion}`)
|
||||
await this.pm.upgrade(`${packageName}@^${targetVersion}`)
|
||||
await this.pm.upgrade(`${packageName}@~${targetVersion}`)
|
||||
|
||||
// the cached `pkg` field won't automatically update after running `this.pm.upgrade`
|
||||
this.pkg[depEntry][packageName] = `^${targetVersion}`
|
||||
this.pkg[depEntry][packageName] = `~${targetVersion}`
|
||||
const pluginMigrator = loadModule(`${packageName}/migrator`, this.context)
|
||||
|
||||
if (pluginMigrator) {
|
||||
|
||||
@@ -7,6 +7,7 @@ const {
|
||||
loadModule
|
||||
} = require('@vue/cli-shared-utils')
|
||||
|
||||
const getVersions = require('./util/getVersions')
|
||||
const PackageManager = require('./util/ProjectPackageManager')
|
||||
const {
|
||||
log,
|
||||
@@ -40,12 +41,12 @@ async function add (pluginName, options = {}, context = process.cwd()) {
|
||||
log()
|
||||
|
||||
const pm = new PackageManager({ context })
|
||||
const { latestMinor } = await getVersions()
|
||||
|
||||
const cliVersion = require('../package.json').version
|
||||
if (isOfficialPlugin(packageName) && semver.prerelease(cliVersion)) {
|
||||
await pm.add(`${packageName}@^${cliVersion}`)
|
||||
if (isOfficialPlugin(packageName)) {
|
||||
await pm.add(`${packageName}@~${latestMinor}`)
|
||||
} else {
|
||||
await pm.add(packageName)
|
||||
await pm.add(packageName, { tilde: true })
|
||||
}
|
||||
|
||||
log(`${chalk.green('✔')} Successfully installed plugin: ${chalk.cyan(packageName)}`)
|
||||
|
||||
@@ -235,36 +235,48 @@ class PackageManager {
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
async runCommand (args) {
|
||||
async runCommand (command, args) {
|
||||
await this.setRegistryEnvs()
|
||||
await executeCommand(this.bin, args, this.context)
|
||||
return await executeCommand(
|
||||
this.bin,
|
||||
[
|
||||
...PACKAGE_MANAGER_CONFIG[this.bin][command],
|
||||
...(args || [])
|
||||
],
|
||||
this.context
|
||||
)
|
||||
}
|
||||
|
||||
async install () {
|
||||
if (process.env.VUE_CLI_TEST) {
|
||||
try {
|
||||
await this.runCommand([PACKAGE_MANAGER_CONFIG[this.bin].install, '--offline'])
|
||||
await this.runCommand('install', ['--offline'])
|
||||
} catch (e) {
|
||||
await this.runCommand([PACKAGE_MANAGER_CONFIG[this.bin].install])
|
||||
await this.runCommand('install')
|
||||
}
|
||||
}
|
||||
|
||||
return this.runCommand([PACKAGE_MANAGER_CONFIG[this.bin].install])
|
||||
return await this.runCommand('install')
|
||||
}
|
||||
|
||||
async add (packageName, isDev = true) {
|
||||
return this.runCommand([
|
||||
...PACKAGE_MANAGER_CONFIG[this.bin].add,
|
||||
packageName,
|
||||
...(isDev ? ['-D'] : [])
|
||||
])
|
||||
async add (packageName, {
|
||||
tilde = false,
|
||||
dev = true
|
||||
} = {}) {
|
||||
const args = dev ? ['-D'] : []
|
||||
if (tilde) {
|
||||
if (this.bin === 'yarn') {
|
||||
args.push('--tilde')
|
||||
} else {
|
||||
process.env.npm_config_save_prefix = '~'
|
||||
}
|
||||
}
|
||||
|
||||
return await this.runCommand('add', [packageName, ...args])
|
||||
}
|
||||
|
||||
async remove (packageName) {
|
||||
return this.runCommand([
|
||||
...PACKAGE_MANAGER_CONFIG[this.bin].remove,
|
||||
packageName
|
||||
])
|
||||
return await this.runCommand('remove', [packageName])
|
||||
}
|
||||
|
||||
async upgrade (packageName) {
|
||||
@@ -281,10 +293,7 @@ class PackageManager {
|
||||
return
|
||||
}
|
||||
|
||||
return this.runCommand([
|
||||
...PACKAGE_MANAGER_CONFIG[this.bin].add,
|
||||
packageName
|
||||
])
|
||||
return await this.runCommand('add', [packageName])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ module.exports = async function getVersions () {
|
||||
if (process.env.VUE_CLI_TEST || process.env.VUE_CLI_DEBUG) {
|
||||
return (sessionCached = {
|
||||
current: local,
|
||||
latest: local
|
||||
latest: local,
|
||||
latestMinor: local
|
||||
})
|
||||
}
|
||||
|
||||
@@ -44,9 +45,21 @@ module.exports = async function getVersions () {
|
||||
latest = cached
|
||||
}
|
||||
|
||||
let latestMinor = `${semver.major(latest)}.${semver.minor(latest)}.0`
|
||||
if (
|
||||
// if the latest version contains breaking changes
|
||||
/major/.test(semver.diff(local, latest)) ||
|
||||
// or if using `next` branch of cli
|
||||
(semver.gte(local, latest) && semver.prerelease(local))
|
||||
) {
|
||||
// fallback to the local cli version number
|
||||
latestMinor = local
|
||||
}
|
||||
|
||||
return (sessionCached = {
|
||||
current: local,
|
||||
latest,
|
||||
latestMinor,
|
||||
error
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user