Vue CLI

Creating a Vue project...

Previously

vue init

The good old'

Lots of templates

Scaffolding only

Eject only

Difficult upgrades

Enter the next best thing...

Vue CLI 3.0

yarn global add @vue/cli
yarn global remove vue-cli

Install it now!

How is it different?

A complete rewrite from scratch

An entirely new architecture based on plugins

A powerful and extensive API

The Ultimate Objective...

The standard build toolchain for Vue

Vue CLI 3.0

Feature-rich

vue create

Built-in

zero-config

fully-featured

Webpack 4

Babel 7

PostCSS

SASS

Stylus

LESS

Auto-generated HTML

Modern mode

Multi-page support

Library target

Web component target

All of this...

Out-of-the-box!

No Template

PLUGINS

Pick

the additional features

you want...

Typescript

ESLint/TSLint/Prettier

Vue Router

Vuex

PWA

Want to write

tests?

Cypress

Jest

Mocha

Nightwatch

Add new features after project creation

Plugins can be upgraded thus upgrading the app

vue create

is not the end of the story...

vue-cli-service <command>

@vue/cli-service

@vue/cli-plugin-typescript

@vue/cli-plugin-eslint

@vue/cli-plugin-pwa

Your project

Creation

Development

Production build

Deployment

...

Something is still missing?

Community plugins

240+ plugins already available

Create your own!

One more thing...

Vue CLI

UI

But CLI is "Command Line Interface"?!?

Vue CLI 3.0 is more complex

More choices

More commands

More options

But we still shoot for

Ease of Access

with simple-to-use tools

So let's

Interfacize

(thanks, @Compulves)

Everything

More context

Detailed explanations

Discoverability

Better prompts UI

Localization

I started with a UI framework

yarn add @vue/ui

Homogeneous look-and-feel for Vue org apps

And after a few months of work...

vue ui

Graphical User Interface (web app)

Node.js GraphQL Server

No

electron

needed

That's not all...

UI Plugin API

Install Prompts

// prompts.js
module.exports = [
  {
    type: 'confirm',
    name: 'addExamples',
    message: 'Add example code',
    description: 'This will generate a component, graphql files and an example schema (if server is added).',
    default: false,
  },
  {
    type: 'confirm',
    name: 'addServer',
    message: 'Add a GraphQL API Server?',
    description: 'Generate GraphQL server files in a `apollo-server` folder.',
    group: 'GraphQL Server',
    default: false,
  },
  {
    type: 'confirm',
    name: 'addMocking',
    message: 'Enable automatic mocking?',
    description: 'Missing resolvers will be automatically mocked.',
    group: 'GraphQL Server',
    default: false,
    when: answers => answers.addServer,
  },
  {
    type: 'confirm',
    name: 'addApolloEngine',
    message: 'Add Apollo Engine?',
    link: 'http://engine.apollographql.com/',
    group: 'GraphQL Server',
    default: false,
    when: answers => answers.addServer,
  },
  {
    type: 'input',
    name: 'apolloEngineKey',
    message: 'API Key (create one at https://engine.apollographql.com):',
    group: 'GraphQL Server',
    validate: input => !!input,
    when: answers => answers.addApolloEngine,
  },
]

Configuration Screen

// ui.js
module.exports = api => {
  // Config file
  api.describeConfig({
    id: CONFIG,
    name: 'Apollo Server',
    description: 'Integrated GraphQL server',
    link: 'https://github.com/Akryum/vue-cli-plugin-apollo#configuration',
    files: {
      vue: {
        js: ['vue.config.js'],
      },
      graphql: {
        yaml: ['.graphqlconfig.yml'],
      },
    },
    onRead: ({ data, cwd }) => {
      return {
        prompts: [
          {
            name: 'enableMocks',
            message: 'Mocking',
            description: 'Enable auto-mocking for quick prototyping',
            link: 'https://github.com/Akryum/vue-cli-plugin-apollo#mocks',
            type: 'confirm',
            file: 'vue',
            default: false,
            value: getConfigData(data).enableMocks,
          },
        ],
      }
    },
    onWrite: async ({ api, prompts, cwd }) => {
      const result = {}
      for (const prompt of prompts.filter(p => p.raw.file === 'vue')) {
        result[`pluginOptions.apollo.${prompt.id}`] = await api.getAnswer(prompt.id)
      }
      api.setData('vue', result)

      // Update app manifest

      const serverFolder = result['pluginOptions.apollo.serverFolder'] || prompts.find(p => p.id === 'serverFolder').raw.default
      api.setData('graphql', {
        'projects.app.schemaPath': path.join(serverFolder, 'schema.graphql'),
      })
    },
  })
}

Augmented Task

// ui.js
module.exports = api => {
  api.describeTask({
    match: /vue-cli-service apollo:watch/,
    description: 'Run and watch the GraphQL server',
    link: 'https://github.com/Akryum/vue-cli-plugin-apollo#injected-commands',
    prompts: [
      {
        name: 'open',
        type: 'confirm',
        default: false,
        description: 'org.akryum.apollo.tasks.watch.open'
      },
    ],
    views: [
      {
        id: 'org.akryum.vue-apollo.views.playground',
        label: 'Playground',
        icon: 'gamepad',
        component: 'org.akryum.vue-apollo.components.playground',
      },
    ],
    defaultView: 'org.akryum.vue-apollo.views.playground',
    onRun: () => {
      api.ipcOn(onGraphqlServerMessage)
      setSharedData('running', true)
    },
    onExit: () => {
      api.ipcOff(onGraphqlServerMessage)
      resetData()
    },
  })
}

Custom components

// ui.js
module.exports = api => {
  api.addClientAddon({
    id: 'org.akryum.vue-apollo.client-addon',
    path: path.resolve(__dirname, './client-addon-dist'),
  })
}
// During plugin dev
module.exports = api => {
  api.addClientAddon({
    id: 'org.akryum.vue-apollo.client-addon',
    url: 'http://localhost:8043/index.js'
  })
}
// vue.config.js
const { clientAddonConfig } = require('@vue/cli-ui')

module.exports = {
  ...clientAddonConfig({
    id: 'vue-apollo',
    port: 8043,
  }),
  outputDir: '../client-addon-dist',
}

In client addon:

Custom components

// src/main.js

import Welcome from './components/Welcome.vue'
import KillPort from './components/KillPort.vue'
import PluginUpdates from './components/PluginUpdates.vue'
import DependencyUpdates from './components/DependencyUpdates.vue'
import Vulnerability from './components/Vulnerability.vue'
import VulnerabilityDetails from './components/VulnerabilityDetails.vue'
import RunTask from './components/RunTask.vue'
import News from './components/News.vue'

ClientAddonApi.component('org.vue.widgets.components.welcome', Welcome)
ClientAddonApi.component('org.vue.widgets.components.kill-port', KillPort)
ClientAddonApi.component('org.vue.widgets.components.plugin-updates', PluginUpdates)
ClientAddonApi.component('org.vue.widgets.components.dependency-updates', DependencyUpdates)
ClientAddonApi.component('org.vue.widgets.components.vulnerability', Vulnerability)
ClientAddonApi.component('org.vue.widgets.components.vulnerability-details', VulnerabilityDetails)
ClientAddonApi.component('org.vue.widgets.components.run-task', RunTask)
ClientAddonApi.component('org.vue.widgets.components.news', News)

In client addon:

Widget

// ui.js
module.exports = api => {
  api.registerWidget({
    id: 'org.vue.widgets.news',
    title: 'org.vue.widgets.news.title',
    description: 'org.vue.widgets.news.description',
    icon: 'rss_feed',
    component: 'org.vue.widgets.components.news',
    detailsComponent: 'org.vue.widgets.components.news',
    minWidth: 2,
    minHeight: 1,
    maxWidth: 6,
    maxHeight: 6,
    defaultWidth: 2,
    defaultHeight: 3,
    openDetailsButton: true,
    defaultConfig: () => ({
      url: 'https://vuenews.fireside.fm/rss'
    }),
    onConfigOpen: async ({ context }) => {
      return {
        prompts: [
          {
            name: 'url',
            type: 'input',
            message: 'org.vue.widgets.news.prompts.url'
          }
        ]
      }
    }
  })
}

UI Plugin API

  • Install Prompts
  • Configuration Screen
  • Augmented Tasks
  • Suggestions
  • Custom page
  • Custom components
  • Shared data
  • Actions
  • Hooks

What's coming up?

Babel 7.0 updates

vue upgrade

Better error overlay

Settings page

Command box and keyboard shortcuts

Global UI Plugins

Project Dashboard

More info

cli.vuejs.org

Silver sponsor

Guillaume Chau

@Akryum

github.com/Akryum

Thank you!

Why vue-cli needed a UI and what you can do with it

By Guillaume Chau

Why vue-cli needed a UI and what you can do with it

We will go through why and how the UI was built and how you can extend it so it can be even more useful!

  • 5,313