Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/min.node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22.22.2
24.17.0
3 changes: 0 additions & 3 deletions .github/workflows/test-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ jobs:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v6.0.9
- name: Install FFmpeg
run: |
sudo apt install -y ffmpeg
- name: Use Node.js
uses: actions/setup-node@v7.0.0
with:
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/test-federation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ jobs:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v6.0.9
- name: Install FFmpeg
run: |
sudo apt install -y ffmpeg
- name: Use Node.js
uses: actions/setup-node@v7.0.0
with:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## 2026.8.0

### Note
- Node.js v22のサポートを終了しました。Node.js v22では動作しません。Node.js v24, v26をご利用ください。

### General
-

Expand All @@ -8,6 +11,7 @@
- Fix: 画像の表示時にBlurhashが描画されない場合があるのを修正

### Server
- Enhance: 動画処理のパフォーマンスを改善
- Fix: 既にミュートしているスレッドに対して再度スレッドミュートを作成しようとするとサーバーエラーになる問題を修正


Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ ENV PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ffmpeg tini curl libjemalloc-dev libjemalloc2 \
tini curl libjemalloc-dev libjemalloc2 \
&& ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so \
&& groupadd -g "${GID}" misskey \
&& useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey \
Expand Down
74 changes: 74 additions & 0 deletions packages/backend/lib/backend-dev-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { execa, execaNode } from 'execa';
import fkill from 'fkill';
import type { ResultPromise } from 'execa';
import type { Plugin } from 'rolldown';

/**
* Watchモード時にバックエンドの起動・停止制御を行うプラグイン
*/
export function backendDevServerPlugin(): Plugin {
let backendProcess: ResultPromise | null = null;
let backendShutdownPromise: Promise<void> | null = null;

async function runBuildAssets() {
await execa('pnpm', ['run', 'build-assets'], {
cwd: '../../',
stdout: process.stdout,
stderr: process.stderr,
});
}

async function killBackendProcess() {
if (backendShutdownPromise) return backendShutdownPromise;
if (!backendProcess) return;

const processToKill = backendProcess;
backendProcess = null;
processToKill.catch(() => {}); // プロセスの終了によって発生する例外を無視するためにcatch()を呼び出す

backendShutdownPromise = (async () => {
if (process.platform === 'win32' && processToKill.pid != null) {
await fkill(processToKill.pid, {
force: true,
tree: true,
silent: true,
waitForExit: 5000,
});
} else {
processToKill.kill();
}

await processToKill.catch(() => {});
})().finally(() => {
backendShutdownPromise = null;
});

return backendShutdownPromise;
}

return {
name: 'backend-dev-server',
async closeBundle() {
await runBuildAssets();
if (backendProcess) {
await killBackendProcess();
}
backendProcess = execaNode('./built/entry.js', [], {
stdout: process.stdout,
stderr: process.stderr,
env: {
NODE_ENV: 'development',
},
});
},
async watchChange() {
if (backendProcess) {
await killBackendProcess();
await runBuildAssets();
}
},
async closeWatcher() {
await killBackendProcess();
},
};
}
75 changes: 75 additions & 0 deletions packages/backend/lib/esm-shim.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { RolldownMagicString } from 'rolldown';
import type { Plugin } from 'rolldown';

const cjsSyntaxRegex = /__filename|__dirname|require\(|require\.resolve\(/;

const shimComment = '// -- ESM Shim --';

export function esmShimPlugin(): Plugin {
return {
name: 'esm-shim',
renderChunk(code, _, opts, meta) {
if (opts.format === 'es') {
if (code.includes(shimComment) || !cjsSyntaxRegex.test(code)) {
return null;
}

const ast = this.parse(code, {
sourceType: 'module',
});

let lastImportIndex = -1;
let isFilenameShimmed = false;
let isDirnameShimmed = false;
let isRequireShimmed = false;

for (const [index, node] of ast.body.entries()) {
switch (node.type) {
case 'ImportDeclaration':
lastImportIndex = index;
break;
case 'VariableDeclaration':
for (const decl of node.declarations) {
if (decl.id.type === 'Identifier') {
if (decl.id.name === '__filename') {
isFilenameShimmed = true;
} else if (decl.id.name === '__dirname') {
isDirnameShimmed = true;
} else if (decl.id.name === 'require') {
isRequireShimmed = true;
}
}
}
break;
}
}

const shimLines: string[] = [];
if (!isFilenameShimmed) {
shimLines.push('const __filename = import.meta.filename;');
}
if (!isDirnameShimmed) {
shimLines.push('const __dirname = import.meta.dirname;');
}
if (!isRequireShimmed) {
shimLines.push('import { createRequire as cjsShimCreateRequire } from \'node:module\';');
shimLines.push('const require = cjsShimCreateRequire(import.meta.url);');
}

if (shimLines.length > 0) {
const magicString = meta.magicString ?? new RolldownMagicString(code);
const shimCode = `${shimComment}\n${shimLines.join('\n')}\n`;
if (lastImportIndex >= 0) {
const lastImportNode = ast.body[lastImportIndex];
magicString.appendLeft(lastImportNode.end, `\n${shimCode}`);
} else {
magicString.prepend(`${shimCode}\n`);
}
return magicString;
}
}

return null;
},
};
}
15 changes: 10 additions & 5 deletions packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"type": "module",
"engines": {
"node": "^22.22.2 || ^24.17.0 || ^26.4.0"
"node": "^24.17.0 || ^26.4.0"
},
"scripts": {
"start": "pnpm compile-config && node ./built/entry.js",
Expand Down Expand Up @@ -34,6 +34,14 @@
"generate-api-json": "pnpm compile-config && node ./scripts/generate_api_json.js"
},
"optionalDependencies": {
"@seydx/node-av-darwin-arm64": "6.1.1",
"@seydx/node-av-darwin-x64": "6.1.1",
"@seydx/node-av-linux-arm64": "6.1.1",
"@seydx/node-av-linux-x64": "6.1.1",
"@seydx/node-av-win32-arm64-mingw": "6.1.1",
"@seydx/node-av-win32-arm64-msvc": "6.1.1",
"@seydx/node-av-win32-x64-mingw": "6.1.1",
"@seydx/node-av-win32-x64-msvc": "6.1.1",
"bufferutil": "4.1.0",
"slacc-android-arm-eabi": "0.1.5",
"slacc-android-arm64": "0.1.5",
Expand Down Expand Up @@ -82,7 +90,6 @@
"cacheable-lookup": "7.0.0",
"chalk": "6.0.0",
"chalk-template": "1.1.2",
"chokidar": "5.0.0",
"color-convert": "3.1.3",
"content-disposition": "2.0.1",
"date-fns": "4.4.0",
Expand All @@ -91,7 +98,6 @@
"fastify-raw-body": "6.0.1",
"feed": "6.0.0",
"file-type": "22.0.1",
"fluent-ffmpeg": "2.1.3",
"got": "15.1.0",
"hpagent": "1.2.0",
"http-link-header": "1.1.4",
Expand All @@ -111,6 +117,7 @@
"ms": "3.0.0-canary.202508261828",
"nanoid": "6.0.1",
"nested-property": "4.0.0",
"node-av": "6.1.1",
"node-fetch": "3.3.2",
"node-html-parser": "9.0.1",
"nodemailer": "9.0.5",
Expand Down Expand Up @@ -148,12 +155,10 @@
"devDependencies": {
"@kitajs/ts-html-plugin": "4.1.4",
"@nestjs/platform-express": "11.1.29",
"@rollup/plugin-esm-shim": "0.1.8",
"@sentry/vue": "10.70.0",
"@sinonjs/fake-timers": "15.4.0",
"@types/accepts": "1.3.7",
"@types/archiver": "8.0.0",
"@types/fluent-ffmpeg": "2.1.28",
"@types/http-link-header": "1.0.7",
"@types/jsonld": "1.5.15",
"@types/mime-types": "3.0.1",
Expand Down
89 changes: 12 additions & 77 deletions packages/backend/rolldown.config.ts
Original file line number Diff line number Diff line change
@@ -1,80 +1,8 @@
import { defineConfig } from 'rolldown';
import { version as summalyVersion } from '@misskey-dev/summaly';
import type { Plugin, ExternalOption } from 'rolldown';
import { execa, execaNode } from 'execa';
import type { ResultPromise } from 'execa';
import fkill from 'fkill';
import esmShim from '@rollup/plugin-esm-shim';

/**
* Watchモード時にバックエンドの起動・停止制御を行うプラグイン
*/
function backendDevServerPlugin(): Plugin {
let backendProcess: ResultPromise | null = null;
let backendShutdownPromise: Promise<void> | null = null;

async function runBuildAssets() {
await execa('pnpm', ['run', 'build-assets'], {
cwd: '../../',
stdout: process.stdout,
stderr: process.stderr,
});
}

async function killBackendProcess() {
if (backendShutdownPromise) return backendShutdownPromise;
if (!backendProcess) return;

const processToKill = backendProcess;
backendProcess = null;
processToKill.catch(() => {}); // プロセスの終了によって発生する例外を無視するためにcatch()を呼び出す

backendShutdownPromise = (async () => {
if (process.platform === 'win32' && processToKill.pid != null) {
await fkill(processToKill.pid, {
force: true,
tree: true,
silent: true,
waitForExit: 5000,
});
} else {
processToKill.kill();
}

await processToKill.catch(() => {});
})().finally(() => {
backendShutdownPromise = null;
});

return backendShutdownPromise;
}

return {
name: 'backend-dev-server',
async closeBundle() {
await runBuildAssets();
if (backendProcess) {
await killBackendProcess();
}
backendProcess = execaNode('./built/entry.js', [], {
stdout: process.stdout,
stderr: process.stderr,
env: {
NODE_ENV: 'development',
},
});
},
async watchChange() {
if (backendProcess) {
await killBackendProcess();
await runBuildAssets();
}
},
async closeWatcher() {
await killBackendProcess();
},
};
}
import type { ExternalOption } from 'rolldown';
import { backendDevServerPlugin } from './lib/backend-dev-server.ts';
import { esmShimPlugin } from './lib/esm-shim.ts';

export default defineConfig((args) => {
const isWatchMode = args.watch != null && args.watch !== 'false';
Expand All @@ -97,6 +25,7 @@ export default defineConfig((args) => {
'sharp',
'jsdom',
're2',
/^@seydx\/node-av-.*/,
'ipaddr.js',
'file-type',
// バンドルするとSentryの自動計装が正しく行われなくなるため外しておく
Expand All @@ -114,7 +43,7 @@ export default defineConfig((args) => {
platform: 'node',
tsconfig: './test-server/tsconfig.json',
plugins: [
esmShim(),
esmShimPlugin(),
],
transform: {
define,
Expand All @@ -126,6 +55,9 @@ export default defineConfig((args) => {
cleanDir: true,
format: 'esm',
},
experimental: {
nativeMagicString: true,
},
external: externalModules,
};
} else {
Expand All @@ -140,7 +72,7 @@ export default defineConfig((args) => {
platform: 'node',
tsconfig: true,
plugins: [
esmShim(),
esmShimPlugin(),
(isWatchMode ? backendDevServerPlugin() : undefined),
],
transform: {
Expand All @@ -158,6 +90,9 @@ export default defineConfig((args) => {
include: ['src/**/*.{ts,js,mjs,cjs,tsx,json}'],
clearScreen: false,
},
experimental: {
nativeMagicString: true,
},
// ビルドの高速化のために、watchモードのときは外部モジュールは全てバンドルしないようにする
external: isWatchMode ? /^(?!@\/|\0)[^.\/](?!:[\/\\])/ : externalModules,
};
Expand Down
Loading
Loading