revert(dev): フロントエンド・バックエンドを分離する開発モードを廃止

(cherry picked from commit 35104d87d5174a080143d3604e50bbef974ab04e)

Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
This commit is contained in:
あわわわとーにゅ 2025-01-26 06:47:36 +09:00
parent eda6d6f455
commit d18599458c
No known key found for this signature in database
GPG key ID: 6AFBBF529601C1DB
9 changed files with 14 additions and 240 deletions

View file

@ -115,25 +115,10 @@ pnpm dev
command. command.
- Server-side source files and automatically builds them if they are modified. Automatically start the server process(es). - Server-side source files and automatically builds them if they are modified. Automatically start the server process(es).
- Vite HMR (just the `vite` command) is available. The behavior may be different from production.
- Service Worker is watched by esbuild. - Service Worker is watched by esbuild.
- The front end can be viewed by accessing `http://localhost:5173`. - Vite HMR (just the `vite` command) is available. The behavior may be different from production.
- The backend listens on the port configured with `port` in .config/default.yml. - Vite runs behind the backend (the backend will proxy Vite at /vite except for websocket used for HMR).
If you have not changed it from the default, it will be "http://localhost:3000".
If "port" in .config/default.yml is set to something other than 3000, you need to change the proxy settings in packages/frontend/vite.config.local-dev.ts.
### `MK_DEV_PREFER=backend pnpm dev`
pnpm dev has another mode with `MK_DEV_PREFER=backend`.
```
MK_DEV_PREFER=backend pnpm dev
```
- This mode is closer to the production environment than the default mode.
- Vite runs behind the backend (the backend will proxy Vite at /vite).
- You can see Misskey by accessing `http://localhost:3000` (Replace `3000` with the port configured with `port` in .config/default.yml). - You can see Misskey by accessing `http://localhost:3000` (Replace `3000` with the port configured with `port` in .config/default.yml).
- To change the port of Vite, specify with `VITE_PORT` environment variable.
- HMR may not work in some environments such as Windows.
### Dev Container ### Dev Container
Instead of running `pnpm` locally, you can use Dev Container to set up your development environment. Instead of running `pnpm` locally, you can use Dev Container to set up your development environment.

View file

@ -303,9 +303,12 @@ export class ClientServerService {
done(); done();
}); });
} else { } else {
const configUrl = new URL(this.config.url);
const urlOriginWithoutPort = configUrl.origin.replace(/:\d+$/, '');
const port = (process.env.VITE_PORT ?? '5173'); const port = (process.env.VITE_PORT ?? '5173');
fastify.register(fastifyProxy, { fastify.register(fastifyProxy, {
upstream: 'http://localhost:' + port, upstream: urlOriginWithoutPort + ':' + port,
prefix: '/vite', prefix: '/vite',
rewritePrefix: '/vite', rewritePrefix: '/vite',
}); });

View file

@ -4,7 +4,6 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"watch": "vite", "watch": "vite",
"dev": "vite --config vite.config.local-dev.ts --debug hmr",
"build": "vite build", "build": "vite build",
"storybook-dev": "nodemon --verbose --watch src --ext \"mdx,ts,vue\" --ignore \"*.stories.ts\" --exec \"pnpm build-storybook-pre && pnpm exec storybook dev -p 6006 --ci\"", "storybook-dev": "nodemon --verbose --watch src --ext \"mdx,ts,vue\" --ignore \"*.stories.ts\" --exec \"pnpm build-storybook-pre && pnpm exec storybook dev -p 6006 --ci\"",
"build-storybook-pre": "(tsc -p .storybook || echo done.) && node .storybook/generate.js && node .storybook/preload-locale.js && node .storybook/preload-theme.js", "build-storybook-pre": "(tsc -p .storybook || echo done.) && node .storybook/generate.js && node .storybook/preload-locale.js && node .storybook/preload-theme.js",

View file

@ -1,95 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
// devモードで起動される際index.htmlを使うときはrouterが暴発してしまってうまく読み込めない。
// よって、devモードとして起動されるときはビルド時に組み込む形としておく。
// (pnpm start時はpugファイルの中で静的リソースとして読み込むようになっており、この問題は起こっていない)
import '@tabler/icons-webfont/dist/tabler-icons.scss';
await main();
import('@/_boot_.js');
/**
* backend/src/server/web/boot.jsで差し込まれている起動処理のうち
*/
async function main() {
const forceError = localStorage.getItem('forceError');
if (forceError != null) {
renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.');
}
//#region Detect language & fetch translations
// dev-modeの場合は常に取り直す
const supportedLangs = _LANGS_.map(it => it[0]);
let lang: string | null | undefined = localStorage.getItem('lang');
if (lang == null || !supportedLangs.includes(lang)) {
if (supportedLangs.includes(navigator.language)) {
lang = navigator.language;
} else {
lang = supportedLangs.find(x => x.split('-')[0] === navigator.language);
// Fallback
if (lang == null) lang = 'en-US';
}
}
// TODO:今のままだと言語ファイル変更後はpnpm devをリスタートする必要があるので、chokidarを使ったり等で対応できるようにする
const locale = _LANGS_FULL_.find(it => it[0] === lang);
localStorage.setItem('lang', lang);
localStorage.setItem('locale', JSON.stringify(locale[1]));
localStorage.setItem('localeVersion', _VERSION_);
//#endregion
//#region Theme
const theme = localStorage.getItem('theme');
if (theme) {
for (const [k, v] of Object.entries(JSON.parse(theme))) {
document.documentElement.style.setProperty(`--${k}`, v.toString());
// HTMLの theme-color 適用
if (k === 'htmlThemeColor') {
for (const tag of document.head.children) {
if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
tag.setAttribute('content', v);
break;
}
}
}
}
}
const colorScheme = localStorage.getItem('colorScheme');
if (colorScheme) {
document.documentElement.style.setProperty('color-scheme', colorScheme);
}
//#endregion
const fontSize = localStorage.getItem('fontSize');
if (fontSize) {
document.documentElement.classList.add('f-' + fontSize);
}
const useSystemFont = localStorage.getItem('useSystemFont');
if (useSystemFont) {
document.documentElement.classList.add('useSystemFont');
}
const wallpaper = localStorage.getItem('wallpaper');
if (wallpaper) {
document.documentElement.style.backgroundImage = `url(${wallpaper})`;
}
const customCss = localStorage.getItem('customCss');
if (customCss && customCss.length > 0) {
const style = document.createElement('style');
style.innerHTML = customCss;
document.head.appendChild(style);
}
}
function renderError(code: string, details?: string) {
console.log(code, details);
}

View file

@ -1,36 +0,0 @@
<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->
<!--
開発モードのviteはこのファイルを起点にサーバーを起動します。
このファイルに書かれた [t]js のリンクと (s)cssのリンクと、その依存関係にあるファイルはビルドされます
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>[DEV] Loading...</title>
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy-Report-Only"
content="default-src 'self' https://newassets.hcaptcha.com/ https://challenges.cloudflare.com/ http://localhost:7493/ https://fonts.gstatic.com/ https://www.google-analytics.com/ https://www.googletagmanager.com/;
worker-src 'self';
script-src 'self' 'unsafe-eval' https://*.hcaptcha.com https://challenges.cloudflare.com https://www.googletagmanager.com https://esm.sh;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://fonts.gstatic.com https://www.googletagmanager.com;
img-src 'self' data: blob: www.google.com xn--931a.moe localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 https://fonts.gstatic.com https://www.googletagmanager.com;
media-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000;
connect-src 'self' localhost:3000 localhost:5173 127.0.0.1:5173 127.0.0.1:3000 https://newassets.hcaptcha.com https://api.pwnedpasswords.com https://www.google-analytics.com https://analytics.google.com;
frame-src *;"
/>
<meta property="og:site_name" content="[DEV BUILD] Misskey" />
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="misskey_app"></div>
<script type="module" src="./_dev_boot_.ts"></script>
</body>
</html>

View file

@ -53,6 +53,7 @@ function getInstanceIcon(instance: Misskey.entities.FederationInstance): string
if (!instance.iconUrl) { if (!instance.iconUrl) {
return ''; return '';
} }
return getProxiedImageUrl(instance.iconUrl, 'preview'); return getProxiedImageUrl(instance.iconUrl, 'preview');
} }

View file

@ -1,89 +0,0 @@
import dns from 'dns';
import { readFile } from 'node:fs/promises';
import { defineConfig } from 'vite';
import * as yaml from 'js-yaml';
import locales from '../../locales/index.js';
import { getConfig } from './vite.config.js';
dns.setDefaultResultOrder('ipv4first');
const defaultConfig = getConfig();
const { port } = yaml.load(await readFile('../../.config/default.yml', 'utf-8'));
const httpUrl = `http://localhost:${port}/`;
const websocketUrl = `ws://localhost:${port}/`;
const devConfig = {
// 基本の設定は vite.config.js から引き継ぐ
...defaultConfig,
root: 'src',
publicDir: '../assets',
base: './',
server: {
host: 'localhost',
port: 5173,
proxy: {
'/api': {
changeOrigin: true,
target: httpUrl,
},
'/assets': httpUrl,
'/static-assets': httpUrl,
'/client-assets': httpUrl,
'/files': httpUrl,
'/twemoji': httpUrl,
'/fluent-emoji': httpUrl,
'/sw.js': httpUrl,
'/streaming': {
target: websocketUrl,
ws: true,
},
'/favicon.ico': httpUrl,
'/identicon': {
target: httpUrl,
rewrite(path) {
return path.replace('@localhost:5173', '');
},
},
'/url': httpUrl,
'/proxy': httpUrl,
'/_info_card_': httpUrl,
'/bios': httpUrl,
'/cli': httpUrl,
'/inbox': httpUrl,
'/emoji/': httpUrl,
'/queue': httpUrl,
'/notes': {
target: httpUrl,
headers: {
'Accept': 'application/activity+json',
},
},
'/users': {
target: httpUrl,
headers: {
'Accept': 'application/activity+json',
},
},
'/.well-known': {
target: httpUrl,
},
},
},
build: {
...defaultConfig.build,
rollupOptions: {
...defaultConfig.build?.rollupOptions,
input: 'index.html',
},
},
define: {
...defaultConfig.define,
_LANGS_FULL_: JSON.stringify(Object.entries(locales)),
},
};
export default defineConfig(({ command, mode }) => devConfig);

View file

@ -3,6 +3,8 @@ import pluginReplace from '@rollup/plugin-replace';
import pluginVue from '@vitejs/plugin-vue'; import pluginVue from '@vitejs/plugin-vue';
import typescript from '@rollup/plugin-typescript'; import typescript from '@rollup/plugin-typescript';
import { type UserConfig, defineConfig } from 'vite'; import { type UserConfig, defineConfig } from 'vite';
import * as yaml from 'js-yaml';
import { promises as fsp } from 'fs';
import locales from '../../locales/index.js'; import locales from '../../locales/index.js';
import meta from '../../package.json'; import meta from '../../package.json';
@ -10,6 +12,9 @@ import packageInfo from './package.json' with { type: 'json' };
import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-module-class-name.js'; import pluginUnwindCssModuleClassName from './lib/rollup-plugin-unwind-css-module-class-name.js';
import pluginJson5 from './vite.json5.js'; import pluginJson5 from './vite.json5.js';
const url = process.env.NODE_ENV === 'development' ? yaml.load(await fsp.readFile('../../.config/default.yml', 'utf-8')).url : null;
const host = url ? (new URL(url)).hostname : undefined;
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue']; const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.json', '.json5', '.svg', '.sass', '.scss', '.css', '.vue'];
/** /**
@ -65,6 +70,7 @@ export function getConfig(): UserConfig {
base: '/vite/', base: '/vite/',
server: { server: {
host,
port: 5173, port: 5173,
}, },

View file

@ -64,7 +64,7 @@ execa('pnpm', ['--filter', 'backend', 'dev'], {
stderr: process.stderr, stderr: process.stderr,
}); });
execa('pnpm', ['--filter', 'frontend', process.env.MK_DEV_PREFER === 'backend' ? 'watch' : 'dev'], { execa('pnpm', ['--filter', 'frontend', 'watch'], {
cwd: _dirname + '/../', cwd: _dirname + '/../',
stdout: process.stdout, stdout: process.stdout,
stderr: process.stderr, stderr: process.stderr,