diff --git a/gulpfile.js b/gulpfile.js index b7aa4e328..90f8ebaab 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -37,7 +37,6 @@ gulp.task('copy:client:locales', cb => { gulp.task('build:backend:script', () => { return gulp.src(['./packages/backend/src/server/web/boot.js', './packages/backend/src/server/web/bios.js', './packages/backend/src/server/web/cli.js']) - .pipe(replace('VERSION', JSON.stringify(meta.version))) .pipe(replace('LANGS', JSON.stringify(Object.keys(locales)))) .pipe(terser({ toplevel: true diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts index 7f765463e..c2e6bea45 100644 --- a/packages/backend/src/config/load.ts +++ b/packages/backend/src/config/load.ts @@ -25,6 +25,7 @@ const path = process.env.NODE_ENV === 'test' export default function load() { const meta = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/meta.json`, 'utf-8')); + const clientManifest = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/_client_dist_/manifest.json`, 'utf-8')); const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source; const mixin = {} as Mixin; @@ -45,6 +46,7 @@ export default function load() { mixin.authUrl = `${mixin.scheme}://${mixin.host}/auth`; mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`; mixin.userAgent = `Misskey/${meta.version} (${config.url})`; + mixin.clientEntry = clientManifest['src/init.ts'].file.replace(/^_client_dist_\//, ''); if (!config.redis.prefix) config.redis.prefix = mixin.host; diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 58a27803c..948545db7 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -80,6 +80,7 @@ export type Mixin = { authUrl: string; driveUrl: string; userAgent: string; + clientEntry: string; }; export type Config = Source & Mixin; diff --git a/packages/backend/src/server/web/boot.js b/packages/backend/src/server/web/boot.js index 751e8619b..a9ee0df4f 100644 --- a/packages/backend/src/server/web/boot.js +++ b/packages/backend/src/server/web/boot.js @@ -58,15 +58,11 @@ ? `?salt=${localStorage.getItem('salt')}` : ''; - const script = document.createElement('script'); - script.setAttribute('src', `/assets/app.${v}.js${salt}`); - script.setAttribute('async', 'true'); - script.setAttribute('defer', 'true'); - script.addEventListener('error', async () => { - await checkUpdate(); - renderError('APP_FETCH_FAILED'); - }); - document.head.appendChild(script); + import(`/assets/${CLIENT_ENTRY}${salt}`) + .catch(async () => { + await checkUpdate(); + renderError('APP_FETCH_FAILED'); + }) //#endregion //#region Theme diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 061ea5060..9e31f2389 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -4,6 +4,7 @@ import { dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { PathOrFileDescriptor, readFileSync } from 'node:fs'; import ms from 'ms'; import Koa from 'koa'; import Router from '@koa/router'; @@ -73,6 +74,9 @@ app.use(views(_dirname + '/views', { extension: 'pug', options: { version: config.version, + clientEntry: () => process.env.NODE_ENV === 'production' ? + config.clientEntry : + JSON.parse(readFileSync(`${_dirname}/../../../../../built/_client_dist_/manifest.json`, 'utf-8'))['src/init.ts'].file.replace(/^_client_dist_\//, ''), config, }, })); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 151320831..d79354d11 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -50,6 +50,10 @@ html style include ../style.css + script. + var VERSION = "#{version}"; + var CLIENT_ENTRY = "#{clientEntry()}"; + script include ../boot.js diff --git a/packages/client/@types/theme.d.ts b/packages/client/@types/theme.d.ts new file mode 100644 index 000000000..b8b906b82 --- /dev/null +++ b/packages/client/@types/theme.d.ts @@ -0,0 +1,5 @@ +import { Theme } from '../src/scripts/theme'; + +declare module '@/themes/*.json5' { + export = Theme; +} diff --git a/packages/client/package.json b/packages/client/package.json index e533e1fb8..1d62d78d8 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,8 +1,8 @@ { "private": true, "scripts": { - "watch": "webpack --watch", - "build": "webpack", + "watch": "vite build --watch --mode development", + "build": "vite build", "lint": "eslint --quiet \"src/**/*.{ts,vue}\"" }, "resolutions": { @@ -12,8 +12,11 @@ "dependencies": { "@discordapp/twemoji": "13.1.1", "@fortawesome/fontawesome-free": "6.1.1", + "@rollup/plugin-alias": "3.1.9", + "@rollup/plugin-json": "4.1.0", "@syuilo/aiscript": "0.11.1", "@typescript-eslint/parser": "5.20.0", + "@vitejs/plugin-vue": "2.3.1", "@vue/compiler-sfc": "3.2.33", "abort-controller": "3.0.0", "autobind-decorator": "2.4.0", @@ -28,8 +31,6 @@ "chartjs-plugin-zoom": "1.2.1", "compare-versions": "4.1.3", "content-disposition": "0.5.4", - "css-loader": "6.7.1", - "cssnano": "5.1.7", "date-fns": "2.28.0", "escape-regexp": "0.0.1", "eslint": "8.14.0", @@ -40,7 +41,6 @@ "idb-keyval": "6.1.0", "insert-text-at-cursor": "0.3.0", "json5": "2.2.1", - "json5-loader": "4.0.1", "katex": "0.15.3", "matter-js": "0.18.0", "mfm-js": "0.21.0", @@ -51,8 +51,6 @@ "parse5": "6.0.1", "photoswipe": "5.2.4", "portscanner": "2.2.0", - "postcss": "8.4.12", - "postcss-loader": "6.2.1", "prismjs": "1.28.0", "private-ip": "2.3.3", "promise-limit": "2.7.0", @@ -63,19 +61,17 @@ "random-seed": "0.3.0", "reflect-metadata": "0.1.13", "rndstr": "1.0.0", + "rollup": "2.70.2", "s-age": "1.1.2", "sass": "1.50.1", - "sass-loader": "12.6.0", "seedrandom": "3.0.5", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", - "style-loader": "3.3.1", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", "three": "0.139.2", "throttle-debounce": "4.0.1", "tinycolor2": "1.4.2", - "ts-loader": "9.2.8", "tsc-alias": "1.5.0", "tsconfig-paths": "3.14.1", "twemoji-parser": "14.0.0", @@ -83,15 +79,11 @@ "uuid": "8.3.2", "v-debounce": "0.1.2", "vanilla-tilt": "1.7.2", + "vite": "2.9.6", "vue": "3.2.33", - "vue-loader": "17.0.0", "vue-prism-editor": "2.0.0-alpha.2", "vue-router": "4.0.14", - "vue-style-loader": "4.1.3", - "vue-svg-loader": "0.17.0-beta.2", "vuedraggable": "4.0.1", - "webpack": "5.72.0", - "webpack-cli": "4.9.2", "websocket": "1.0.34", "ws": "8.5.0" }, @@ -113,8 +105,6 @@ "@types/throttle-debounce": "4.0.0", "@types/tinycolor2": "1.4.3", "@types/uuid": "8.3.4", - "@types/webpack": "5.28.0", - "@types/webpack-stream": "3.2.12", "@types/websocket": "1.0.5", "@types/ws": "8.5.3", "@typescript-eslint/eslint-plugin": "5.20.0", diff --git a/packages/client/src/account.ts b/packages/client/src/account.ts index f4dcab319..6f806ccc5 100644 --- a/packages/client/src/account.ts +++ b/packages/client/src/account.ts @@ -1,5 +1,5 @@ import { del, get, set } from '@/scripts/idb-proxy'; -import { reactive } from 'vue'; +import { defineAsyncComponent, reactive } from 'vue'; import * as misskey from 'misskey-js'; import { apiUrl } from '@/config'; import { waiting, api, popup, popupMenu, success, alert } from '@/os'; @@ -141,7 +141,7 @@ export async function openAccountMenu(opts: { onChoose?: (account: misskey.entities.UserDetailed) => void; }, ev: MouseEvent) { function showSigninDialog() { - popup(import('@/components/signin-dialog.vue'), {}, { + popup(defineAsyncComponent(() => import('@/components/signin-dialog.vue')), {}, { done: res => { addAccount(res.id, res.i); success(); @@ -150,7 +150,7 @@ export async function openAccountMenu(opts: { } function createAccount() { - popup(import('@/components/signup-dialog.vue'), {}, { + popup(defineAsyncComponent(() => import('@/components/signup-dialog.vue')), {}, { done: res => { addAccount(res.id, res.i); switchAccountWithToken(res.i); diff --git a/packages/client/src/components/abuse-report.vue b/packages/client/src/components/abuse-report.vue index b67cef209..46d45b690 100644 --- a/packages/client/src/components/abuse-report.vue +++ b/packages/client/src/components/abuse-report.vue @@ -43,20 +43,20 @@ export default defineComponent({ MkSwitch, }, - emits: ['resolved'], - props: { report: { type: Object, required: true, } - } + }, + + emits: ['resolved'], data() { return { forward: this.report.forwarded, }; - } + }, methods: { acct, diff --git a/packages/client/src/components/analog-clock.vue b/packages/client/src/components/analog-clock.vue index 59b8e9730..18dd1e3f4 100644 --- a/packages/client/src/components/analog-clock.vue +++ b/packages/client/src/components/analog-clock.vue @@ -42,7 +42,7 @@