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,239