Skip to content

Commit

Permalink
feat(console): enhance build workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jan 24, 2022
1 parent c56884e commit b0b8c7a
Show file tree
Hide file tree
Showing 28 changed files with 260 additions and 198 deletions.
96 changes: 96 additions & 0 deletions build/frontend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { buildExtension } from '@koishijs/builder/src'
import { copyFile } from 'fs/promises'
import { cwd, getPackages } from './utils'
import vue from '@vitejs/plugin-vue'
import vite from 'vite'
import cac from 'cac'

const { args } = cac().help().parse()

function findModulePath(id: string) {
const path = require.resolve(id).replace(/\\/g, '/')
const keyword = `/node_modules/${id}/`
return path.slice(0, path.indexOf(keyword)) + keyword.slice(0, -1)
}

export async function build(root: string, config: vite.UserConfig) {
const { rollupOptions } = config.build || {}
await vite.build({
root,
build: {
outDir: '../dist',
minify: 'esbuild',
emptyOutDir: true,
...config.build,
rollupOptions: {
...rollupOptions,
external: [
root + '/vue.js',
root + '/vue-router.js',
root + '/client.js',
],
output: rollupOptions?.input ? {
format: 'module',
entryFileNames: '[name].js',
...rollupOptions.output,
} : undefined,
},
},
plugins: [vue()],
resolve: {
alias: {
'vue': root + '/vue.js',
'vue-router': root + '/vue-router.js',
'./client': root + '/client.js',
'../client': root + '/client.js',
},
},
})
}

async function buildConsole(folder: string) {
const root = cwd + '/' + folder + '/client'
const dist = cwd + '/' + folder + '/dist'

// build for console main
await build(root, { base: './' })

await copyFile(findModulePath('vue') + '/dist/vue.runtime.esm-browser.prod.js', dist + '/vue.js')

// build for console client entry
await build(cwd, {
build: {
outDir: dist,
emptyOutDir: false,
rollupOptions: {
input: {
'client': root + '/client.ts',
'vue-router': findModulePath('vue-router') + '/dist/vue-router.esm-browser.js',
},
treeshake: false,
preserveEntrySignatures: 'strict',
},
},
})
}

;(async () => {
const folders = await getPackages(args)

for (const folder of folders) {
if (folder === 'plugins/frontend/console') {
await buildConsole(folder)
} else {
await buildExtension(cwd + '/' + folder, {
plugins: [{
name: 'fuck-echarts',
renderChunk(code, chunk) {
if (chunk.fileName.includes('echarts')) {
return code.replace(/\bSymbol(?!\.toStringTag)/g, 'FuckSymbol')
}
},
}],
})
}
}
})()
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"dep": "node -r ./build/register build/dep",
"docs": "yarn workspace docs",
"draft": "node -r ./build/register build/release",
"fe": "node -r ./build/register plugins/frontend/builder/src/build",
"fe": "node -r ./build/register build/frontend",
"test": "mocha --no-warnings --experimental-vm-modules --enable-source-maps",
"test:json": "c8 -r json yarn test",
"test:html": "rimraf coverage && c8 -r html yarn test",
Expand Down
56 changes: 0 additions & 56 deletions plugins/frontend/builder/src/build.ts

This file was deleted.

62 changes: 23 additions & 39 deletions plugins/frontend/builder/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,41 @@
/* eslint-disable quote-props */

import * as vite from 'vite'
import pluginVue from '@vitejs/plugin-vue'
import { build, mergeConfig, UserConfig } from 'vite'
import { existsSync } from 'fs'
import vue from '@vitejs/plugin-vue'

export async function build(root: string, config: vite.UserConfig) {
const { rollupOptions } = config.build || {}
await vite.build({
...config,
export async function buildExtension(root: string, config: UserConfig = {}) {
if (!existsSync(root + '/client')) return

return build(mergeConfig({
root,
build: {
outDir: '../dist',
outDir: 'dist',
minify: 'esbuild',
assetsDir: '',
emptyOutDir: true,
...config.build,
lib: {
entry: root + '/client/index.ts',
formats: ['es'],
},
rollupOptions: {
...rollupOptions,
external: [root + '/vue.js', root + '/vue-router.js', root + '/client.js'],
output: rollupOptions?.input ? {
format: 'module',
entryFileNames: '[name].js',
globals: {
[root + '/vue.js']: 'Vue',
[root + '/vue-router.js']: 'VueRouter',
[root + '/client.js']: 'KoishiClient',
},
...rollupOptions.output,
} : undefined,
external: [
root + '/vue.js',
root + '/vue-router.js',
root + '/client.js',
],
output: {
format: 'iife',
},
},
},
plugins: [pluginVue(), ...config.plugins || []],
plugins: [vue()],
resolve: {
alias: {
'vue': root + '/vue.js',
'vue-router': root + '/vue-router.js',
'~/client': root + '/client.js',
...config.resolve?.alias,
},
},
})
}

export function buildExtension(root: string) {
return build(root, {
build: {
outDir: 'dist',
assetsDir: '',
minify: 'esbuild',
rollupOptions: {
input: root + '/client/index.ts',
output: {
format: 'iife',
},
},
},
})
}, config))
}
11 changes: 8 additions & 3 deletions plugins/frontend/chat/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,25 @@ export function apply(ctx: Context, options: Config = {}) {

ctx.using(['console'], (ctx) => {
const { devMode, apiPath } = ctx.console.config
const filename = devMode ? '../client/index.ts' : '../dist/index.js'
const whitelist = [...builtinWhitelist, ...options.whitelist || []]

ctx.console.global.whitelist = whitelist
ctx.console.global.maxMessages = options.maxMessages
ctx.console.addEntry(resolve(__dirname, filename))

if (devMode) {
ctx.console.addEntry(resolve(__dirname, '../client/index.ts'))
} else {
ctx.console.addEntry(resolve(__dirname, '../dist/index.js'))
ctx.console.addEntry(resolve(__dirname, '../dist/style.css'))
}

ctx.console.addListener('chat', async ({ content, platform, selfId, channelId, guildId }) => {
if (ctx.assets) content = await ctx.assets.transform(content)
ctx.bots.get(`${platform}:${selfId}`)?.sendMessage(channelId, content, guildId)
})

ctx.on('chat/receive', async (message) => {
Object.values(ctx.console.handles).forEach((handle) => {
Object.values(ctx.console.ws.handles).forEach((handle) => {
handle.socket.send(JSON.stringify({ type: 'chat', body: message }))
})
})
Expand Down
7 changes: 5 additions & 2 deletions plugins/frontend/commands/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ export function apply(ctx: Context, config: Dict<Config>) {
ctx.using(['console'], (ctx) => {
ctx.plugin(CommandProvider)

const filename = ctx.console.config.devMode ? '../client/index.ts' : '../dist/index.js'
ctx.console.addEntry(resolve(__dirname, filename))
if (ctx.console.config.devMode) {
ctx.console.addEntry(resolve(__dirname, '../client/index.ts'))
} else {
ctx.console.addEntry(resolve(__dirname, '../dist/index.js'))
}
})
}
53 changes: 24 additions & 29 deletions plugins/frontend/console/client/client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ref, reactive, h, markRaw, defineComponent, resolveComponent, watch, Ref } from 'vue'
import { App, ref, reactive, h, markRaw, defineComponent, resolveComponent, watch, Ref } from 'vue'
import { createWebHistory, createRouter, START_LOCATION, RouteRecordNormalized } from 'vue-router'
import { ClientConfig, Sources } from '@koishijs/plugin-console'
import { EChartsOption } from 'echarts'
import { ClientConfig, Console } from '@koishijs/plugin-console'
import { Disposable, Extension, PageOptions, Store, ViewOptions } from '~/client'

// data api
Expand Down Expand Up @@ -85,8 +84,10 @@ export const extensions = reactive<Record<string, Context>>({})

export const routes: Ref<RouteRecordNormalized[]> = ref([])

class Context {
disposables: Disposable[] = []
export class Context {
static app: App

public disposables: Disposable[] = []

addView(options: ViewOptions) {
options.order ??= 0
Expand Down Expand Up @@ -148,8 +149,21 @@ const initTask = new Promise<void>((resolve) => {
const { redirect } = router.currentRoute.value.query
const tasks = newValue.map(async (path) => {
if (extensions[path]) return
const { default: callback } = await import(/* @vite-ignore */ path)
callback(extensions[path] = new Context())
extensions[path] = new Context()

if (path.endsWith('.css')) {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = path
document.head.appendChild(link)
extensions[path].disposables.push(() => {
document.head.removeChild(link)
})
return
}

const exports = await import(/* @vite-ignore */ path)
exports.default?.(extensions[path])
if (typeof redirect === 'string') {
const location = router.resolve(redirect)
if (location.matched.length) {
Expand Down Expand Up @@ -185,7 +199,7 @@ router.beforeEach(async (to, from) => {
// component helper

export namespace Card {
function createFieldComponent(render: Function, fields: readonly (keyof Sources)[] = []) {
export function create(render: Function, fields: readonly (keyof Console.Services)[] = []) {
return defineComponent({
render: () => fields.every(key => store[key]) ? render() : null,
})
Expand All @@ -195,7 +209,7 @@ export namespace Card {
icon: string
title: string
type?: string
fields?: (keyof Sources)[]
fields?: (keyof Console.Services)[]
content: (store: Store) => any
}

Expand All @@ -206,25 +220,6 @@ export namespace Card {
icon, title,
}, () => content(store))

return createFieldComponent(render, fields)
}

export interface ChartOptions {
title: string
fields?: (keyof Sources)[]
options: (store: Store) => EChartsOption
}

export function echarts({ title, fields, options }: ChartOptions) {
return createFieldComponent(() => {
const option = options(store)
return h(resolveComponent('k-card'), {
class: 'frameless',
title,
}, () => option ? h(resolveComponent('k-chart'), {
option,
autoresize: true,
}) : '暂无数据。')
}, fields)
return create(render, fields)
}
}
Loading

0 comments on commit b0b8c7a

Please sign in to comment.