diff --git a/packages/@vue/cli-ui/apollo-server/connectors/dependencies.js b/packages/@vue/cli-ui/apollo-server/connectors/dependencies.js index c31b35fde3..40b8b6126d 100644 --- a/packages/@vue/cli-ui/apollo-server/connectors/dependencies.js +++ b/packages/@vue/cli-ui/apollo-server/connectors/dependencies.js @@ -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`, diff --git a/packages/@vue/cli/lib/Creator.js b/packages/@vue/cli/lib/Creator.js index 4c7d199e55..6a2eca2947 100644 --- a/packages/@vue/cli/lib/Creator.js +++ b/packages/@vue/cli/lib/Creator.js @@ -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` - - 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 - } + // get latest CLI plugin version + const { latestMinor } = await getVersions() + // 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`) ) }) diff --git a/packages/@vue/cli/lib/Upgrader.js b/packages/@vue/cli/lib/Upgrader.js index d5985df596..154027d9c4 100644 --- a/packages/@vue/cli/lib/Upgrader.js +++ b/packages/@vue/cli/lib/Upgrader.js @@ -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) { diff --git a/packages/@vue/cli/lib/add.js b/packages/@vue/cli/lib/add.js index ca2a70a8f8..6001baf81e 100644 --- a/packages/@vue/cli/lib/add.js +++ b/packages/@vue/cli/lib/add.js @@ -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)}`) diff --git a/packages/@vue/cli/lib/util/ProjectPackageManager.js b/packages/@vue/cli/lib/util/ProjectPackageManager.js index 1a6a65d06b..afa7b25cb2 100644 --- a/packages/@vue/cli/lib/util/ProjectPackageManager.js +++ b/packages/@vue/cli/lib/util/ProjectPackageManager.js @@ -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]) } } diff --git a/packages/@vue/cli/lib/util/getVersions.js b/packages/@vue/cli/lib/util/getVersions.js index 4a765fae88..68a8e4085a 100644 --- a/packages/@vue/cli/lib/util/getVersions.js +++ b/packages/@vue/cli/lib/util/getVersions.js @@ -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 }) }