nuxt / rfcs

RFCs for changes to Nuxt.js
99 stars 2 forks source link

Custom CLI Commands #11

Closed pi0 closed 5 years ago

pi0 commented 6 years ago

Related to #10.

Related PR: nuxt/nuxt.js#4314

Original idea: @galvez

TLDR

A limitation of current module spec is that it doesn't allow adding new commands. We can't add helpers to the module function body because commands are executed before of nuxt instance initialization.

Different ways

1. Universal approach

The @nuxt/cli package exports useful functions to create a good CLI command interface and also benefits of nuxt built-in utilities like config loading and fancy CLI. This pattern allows module package authors to easily create their own bin/ commands with help of a nuxt core module that is also semi-compatible with nuxt projects lower than 2.3.0.

#!/bin/env node -r esm

import { NuxtCommand, run } from '@nuxt/cli'

const cmd = NuxtCommand.from({
    name: 'custom',
    description: 'A custom nuxt command',
    usage: 'nuxt custom',
    async run(cmd) {
      const argv = cmd.getArgv()
      // ...
    }
})

run(cmd)

Positive points:

Negative points:

Appendix:

For sub-commands support, nuxt CLI can simply map nuxt foo into nuxt-foo and nuxt foo bar into nuxt-foo-bar command and execute it. Preferring convention over platform/PM complexities.

2. js files that @nuxt/cli execute them

The process of adding a command to modules is like creating node_modules/my-module/bin/custom.js that exports a command object like nuxt internal commands. Then by invoking npx nuxt my-command custom nuxt will search for custom command, wraps it into NuxtCommand and runs it.

Positive points:

Negative points:

3. Via module commands export

Module authors can attach module exported commands to the exported function commands object like this:

function myModule(options) {
 // ...
}

myCommand.commands = {
  custom: {
    name: 'custom',
    description: 'A custom nuxt command',
    usage: 'nuxt custom',
    async run(cmd) {
      const argv = cmd.getArgv()
      // ...
    }
  }
}

Positive points:

Negative points:

galvez commented 5 years ago

Thanks for the write-up @pi0 -- It's pretty clear to me that Option 1 is the way to go. Thanks for laying out all pros and cons so thoroughly. Unless anyone wants to voice more concerns, I'm gonna start making the necessary changes in https://github.com/nuxt/nuxt.js/pull/4314 towards that direction.

manniL commented 5 years ago

:+1: for Option 1 :relaxed:

atinux commented 5 years ago

Let's go for Option 1, awesome write up @pi0, really impressed by it and the time you put into it.

pi0 commented 5 years ago

Implemented