123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- const path = require('path')
- const fs = require('fs-extra')
- const { processStats } = require('./utils/stats')
- /** @typedef {import('../apollo-server/api/PluginApi')} PluginApi */
- /**
- * @param {PluginApi} api
- */
- module.exports = api => {
- const { getSharedData, setSharedData, removeSharedData } = api.namespace('org.vue.webpack.')
- let firstRun = true
- let hadFailed = false
- // Specific to each modes (serve, build, ...)
- const fields = {
- status: null,
- progress: {},
- operations: null,
- sizes: null,
- problems: null,
- url: null
- }
- // Common fields for all mode
- const commonFields = {
- 'modern-mode': false
- }
- // Init data
- api.onProjectOpen(setup)
- api.onPluginReload(setup)
- function setup () {
- for (const key of ['serve', 'build', 'build-modern']) {
- setupSharedData(key)
- }
- setupCommonData()
- }
- // Called when opening a project
- function setupSharedData (mode) {
- resetSharedData(mode)
- }
- // Called when opening a project
- function setupCommonData () {
- for (const field in commonFields) {
- setSharedData(field, getSharedDataInitialValue(field, commonFields[field]))
- }
- }
- function resetSharedData (mode, clear = false) {
- for (const field in fields) {
- const id = `${mode}-${field}`
- setSharedData(id, getSharedDataInitialValue(id, fields[field], clear))
- }
- }
- function getSharedDataInitialValue (id, defaultValue, clear) {
- if (!clear) {
- const data = getSharedData(id)
- if (data != null) return data.value
- }
- return defaultValue
- }
- async function onWebpackMessage ({ data: message }) {
- if (message.webpackDashboardData) {
- const modernMode = getSharedData('modern-mode').value
- const type = message.webpackDashboardData.type
- for (const data of message.webpackDashboardData.value) {
- const id = `${type}-${data.type}`
- if (data.type === 'stats') {
- // Stats are read from a file
- const statsFile = path.resolve(api.getCwd(), `./node_modules/.stats-${type}.json`)
- const value = await fs.readJson(statsFile)
- const { stats, analyzer } = processStats(value)
- setSharedData(id, stats, { disk: true })
- setSharedData(`${id}-analyzer`, analyzer, { disk: true })
- await fs.remove(statsFile)
- } else if (data.type === 'progress') {
- if (type === 'serve' || !modernMode) {
- setSharedData(id, {
- [type]: data.value
- })
- } else {
- // Display two progress bars
- const progress = getSharedData(id).value
- progress[type] = data.value
- for (const t of ['build', 'build-modern']) {
- setSharedData(`${t}-${data.type}`, {
- build: progress.build || 0,
- 'build-modern': progress['build-modern'] || 0
- })
- }
- }
- } else {
- // Don't display success until both build and build-modern are done
- if (type !== 'serve' && modernMode && data.type === 'status' && data.value === 'Success') {
- if (type === 'build-modern') {
- for (const t of ['build', 'build-modern']) {
- setSharedData(`${t}-status`, data.value)
- }
- }
- } else {
- setSharedData(id, data.value)
- }
- // Notifications
- if (type === 'serve' && data.type === 'status') {
- if (data.value === 'Failed') {
- api.notify({
- title: 'Build failed',
- message: 'The build has errors.',
- icon: 'error'
- })
- hadFailed = true
- } else if (data.value === 'Success') {
- if (hadFailed) {
- api.notify({
- title: 'Build fixed',
- message: 'The build succeeded.',
- icon: 'done'
- })
- hadFailed = false
- } else if (firstRun) {
- api.notify({
- title: 'App ready',
- message: 'The build succeeded.',
- icon: 'done'
- })
- firstRun = false
- }
- }
- }
- }
- }
- }
- }
- // Tasks
- const views = {
- views: [
- {
- id: 'org.vue.webpack.views.dashboard',
- label: 'org.vue.vue-webpack.dashboard.title',
- icon: 'dashboard',
- component: 'org.vue.webpack.components.dashboard'
- },
- {
- id: 'org.vue.webpack.views.analyzer',
- label: 'org.vue.vue-webpack.analyzer.title',
- icon: 'donut_large',
- component: 'org.vue.webpack.components.analyzer'
- }
- ],
- defaultView: 'org.vue.webpack.views.dashboard'
- }
- api.describeTask({
- match: /vue-cli-service serve(\s+--\S+(\s+\S+)?)*$/,
- description: 'org.vue.vue-webpack.tasks.serve.description',
- link: 'https://cli.vuejs.org/guide/cli-service.html#vue-cli-service-serve',
- icon: '/public/webpack-logo.png',
- prompts: [
- {
- name: 'open',
- type: 'confirm',
- default: false,
- description: 'org.vue.vue-webpack.tasks.serve.open'
- },
- {
- name: 'mode',
- type: 'list',
- default: 'development',
- choices: [
- {
- name: 'development',
- value: 'development'
- },
- {
- name: 'production',
- value: 'production'
- },
- {
- name: 'test',
- value: 'test'
- },
- {
- name: '(unset)',
- value: ''
- }
- ],
- description: 'org.vue.vue-webpack.tasks.serve.mode'
- },
- {
- name: 'host',
- type: 'input',
- default: '',
- description: 'org.vue.vue-webpack.tasks.serve.host'
- },
- {
- name: 'port',
- type: 'input',
- default: undefined,
- description: 'org.vue.vue-webpack.tasks.serve.port'
- },
- {
- name: 'https',
- type: 'confirm',
- default: false,
- description: 'org.vue.vue-webpack.tasks.serve.https'
- }
- ],
- onBeforeRun: ({ answers, args }) => {
- // Args
- if (answers.open) args.push('--open')
- if (answers.mode) args.push('--mode', answers.mode)
- if (answers.host) args.push('--host', answers.host)
- if (answers.port) args.push('--port', answers.port)
- if (answers.https) args.push('--https')
- args.push('--dashboard')
- // Data
- resetSharedData('serve', true)
- firstRun = true
- hadFailed = false
- },
- onRun: () => {
- api.ipcOn(onWebpackMessage)
- },
- onExit: () => {
- api.ipcOff(onWebpackMessage)
- removeSharedData('serve-url')
- },
- ...views
- })
- api.describeTask({
- match: /vue-cli-service build(\s+--\S+(\s+\S+)?)*$/,
- description: 'org.vue.vue-webpack.tasks.build.description',
- link: 'https://cli.vuejs.org/guide/cli-service.html#vue-cli-service-build',
- icon: '/public/webpack-logo.png',
- prompts: [
- {
- name: 'modern',
- type: 'confirm',
- default: false,
- message: 'org.vue.vue-webpack.tasks.build.modern.label',
- description: 'org.vue.vue-webpack.tasks.build.modern.description',
- link: 'https://cli.vuejs.org/guide/browser-compatibility.html#modern-mode'
- },
- {
- name: 'mode',
- type: 'list',
- default: 'production',
- choices: [
- {
- name: 'development',
- value: 'development'
- },
- {
- name: 'production',
- value: 'production'
- },
- {
- name: 'test',
- value: 'test'
- },
- {
- name: '(unset)',
- value: ''
- }
- ],
- description: 'org.vue.vue-webpack.tasks.build.mode'
- },
- {
- name: 'dest',
- type: 'input',
- default: '',
- description: 'org.vue.vue-webpack.tasks.build.dest'
- },
- {
- name: 'target',
- type: 'list',
- default: 'app',
- choices: [
- {
- name: 'org.vue.vue-webpack.tasks.build.target.app',
- value: 'app'
- },
- {
- name: 'org.vue.vue-webpack.tasks.build.target.lib',
- value: 'lib'
- },
- {
- name: 'org.vue.vue-webpack.tasks.build.target.wc',
- value: 'wc'
- },
- {
- name: 'org.vue.vue-webpack.tasks.build.target.wc-async',
- value: 'wc-async'
- }
- ],
- description: 'org.vue.vue-webpack.tasks.build.target.description'
- },
- {
- name: 'name',
- type: 'input',
- default: '',
- description: 'org.vue.vue-webpack.tasks.build.name'
- },
- {
- name: 'watch',
- type: 'confirm',
- default: false,
- description: 'org.vue.vue-webpack.tasks.build.watch'
- }
- ],
- onBeforeRun: ({ answers, args }) => {
- // Args
- if (answers.mode) args.push('--mode', answers.mode)
- if (answers.dest) args.push('--dest', answers.dest)
- if (answers.target) args.push('--target', answers.target)
- if (answers.name) args.push('--name', answers.name)
- if (answers.watch) args.push('--watch')
- if (answers.modern) args.push('--modern')
- setSharedData('modern-mode', !!answers.modern)
- args.push('--dashboard')
- // Data
- resetSharedData('build', true)
- resetSharedData('build-modern', true)
- },
- onRun: () => {
- api.ipcOn(onWebpackMessage)
- },
- onExit: () => {
- api.ipcOff(onWebpackMessage)
- },
- ...views
- })
- // vue inspect
- api.addTask({
- name: 'inspect',
- command: 'vue-cli-service inspect',
- description: 'org.vue.vue-webpack.tasks.inspect.description',
- link: 'https://cli.vuejs.org/guide/webpack.html#inspecting-the-project-s-webpack-config',
- icon: '/public/webpack-inspect-logo.png',
- prompts: [
- {
- name: 'mode',
- type: 'list',
- default: 'production',
- choices: [
- {
- name: 'development',
- value: 'development'
- },
- {
- name: 'production',
- value: 'production'
- },
- {
- name: 'test',
- value: 'test'
- },
- {
- name: '(unset)',
- value: ''
- }
- ],
- description: 'org.vue.vue-webpack.tasks.inspect.mode'
- },
- {
- name: 'verbose',
- type: 'confirm',
- default: false,
- description: 'org.vue.vue-webpack.tasks.inspect.verbose'
- }
- ],
- onBeforeRun: ({ answers, args }) => {
- if (answers.mode) args.push('--mode', answers.mode)
- if (answers.verbose) args.push('--verbose')
- }
- })
- if (process.env.VUE_APP_CLI_UI_DEV) {
- // Add dynamic components in dev mode (webpack dashboard & analyzer)
- api.addClientAddon({
- id: 'org.vue.webpack.client-addon.dev',
- url: 'http://localhost:8096/index.js'
- })
- } else {
- // Webpack dashboard
- api.addClientAddon({
- id: 'org.vue.webpack.client-addon',
- path: '@vue/cli-ui-addon-webpack/dist'
- })
- }
- // Open app button
- api.ipcOn(({ data }) => {
- if (data.vueServe) {
- setSharedData('serve-url', data.vueServe.url)
- }
- })
- }
|