🚀

Devcontainer 使用時に TSServer の初回起動時間が5分を超えたので18秒に短縮してさらに tsgo で1.4秒にした

に公開

はじめに

Devcontainer 上に Turborepo で構築したモノレポ環境において、Next.js プロジェクトの TSServer の初回起動時間がどんどん長くなっていき、5分を超えるようになってきたので調査と最適化を行いました。

作業環境

項目 名前
OS MacOS
IDE VSCode
コンテナ Devcontainer Debian Bookworm
ランタイム Bun v1.3
モノレポ Turborepo v2.5.8
言語 TypeScript v5.9.2
ライブラリ React 19.1.0
フレームワーク Next.js v15.5.4

まずはログを出力

デフォルトだと TypeScript はログ出力をしないので設定を行います。

settings.json
{
  "typescript.tsserver.log": "normal",
}
出力されたログ

.ts.tsx ファイルを開いた状態でコマンドパレットを開いて > TypeScript: Open TS Server log を実行すると直近のログが開きます。

tsserver.log
Info 0    [23:46:30.986] Starting TS Server
Info 1    [23:46:30.986] Version: 5.9.2
Info 2    [23:46:30.986] Arguments: /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/node /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/tsserver.js --useInferredProjectPerProjectRoot --enableTelemetry --cancellationPipeName /tmp/vscode-typescript1000/d74736e0fa61273b0273/tscancellation-b090924e1e375714707e.tmp* --logVerbosity normal --logFile /home/user/.vscode-server/data/logs/20251011T234623/exthost1/vscode.typescript-language-features/tsserver-log-6eFIQ4/tsserver.log --globalPlugins @vscode/copilot-typescript-server-plugin --pluginProbeLocations /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5 --locale en --noGetErrOnBackgroundUpdate --canUseWatchEvents --validateDefaultNpmLocation --useNodeIpc
Info 3    [23:46:30.986] Platform: linux NodeVersion: v22.18.0 CaseSensitive: true
Info 4    [23:46:30.986] ServerMode: undefined hasUnknownServerMode: undefined
Info 5    [23:46:30.988] currentDirectory:: /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829 useCaseSensitiveFileNames:: true
Info 6    [23:46:30.988] libs Location:: /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib
Info 7    [23:46:30.988] globalTypingsCacheLocation:: /home/user/.cache/typescript/5.9
Info 8    [23:46:30.991] Host information vscode
Info 9    [23:46:31.329] getConfigFileNameForFile:: File: /home/user/app/apps/ui/src/app/page.tsx ProjectRootPath: /home/user/app:: Result: /home/user/app/apps/ui/tsconfig.json
Info 10   [23:46:31.329] Creating ConfiguredProject: /home/user/app/apps/ui/tsconfig.json, currentDirectory: /home/user/app/apps/ui
Info 11   [23:46:31.389] Config: /home/user/app/apps/ui/tsconfig.json : {
 "rootNames": [
  "/home/user/app/apps/ui/next-env.d.ts",
  "/home/user/app/apps/ui/next.config.ts",
  "/home/user/app/apps/ui/src/middleware.ts",
  "/home/user/app/apps/ui/src/app/api/auth/[...nextauth]/route.ts",
  "/home/user/app/apps/ui/src/app/api/env/route.ts",
  "/home/user/app/apps/ui/src/components/index.ts",
  "/home/user/app/apps/ui/src/components/Element/index.ts",
  "/home/user/app/apps/ui/src/components/Element/Box/index.ts",
  "/home/user/app/apps/ui/src/components/Element/Form/index.ts",
  "/home/user/app/apps/ui/src/components/Element/Image/index.ts",
  "/home/user/app/apps/ui/src/components/Element/Link/index.ts",
  "/home/user/app/apps/ui/src/components/Element/Text/index.ts",
  "/home/user/app/apps/ui/src/components/Header/index.ts",
  "/home/user/app/apps/ui/src/components/Loading/index.ts",
  "/home/user/app/apps/ui/src/components/Mui/index.ts",
  "/home/user/app/apps/ui/src/components/Sidebar/index.ts",
  "/home/user/app/apps/ui/src/stories/Button.stories.ts",
  "/home/user/app/apps/ui/src/stories/Header.stories.ts",
  "/home/user/app/apps/ui/src/stories/Page.stories.ts",
  "/home/user/app/apps/ui/src/types/index.ts",
  "/home/user/app/apps/ui/src/types/loading.ts",
  "/home/user/app/apps/ui/src/types/next-auth.d.ts",
  "/home/user/app/apps/ui/src/utils/actions.ts",
  "/home/user/app/apps/ui/src/utils/atom.ts",
  "/home/user/app/apps/ui/src/utils/auth.ts",
  "/home/user/app/apps/ui/src/utils/env.ts",
  "/home/user/app/apps/ui/src/utils/index.ts",
  "/home/user/app/apps/ui/src/utils/server.ts",
  "/home/user/app/apps/ui/src/app/layout.tsx",
  "/home/user/app/apps/ui/src/app/page.tsx",
  "/home/user/app/apps/ui/src/app/(no-sidebar)/layout.tsx",
  "/home/user/app/apps/ui/src/app/(with-sidebar)/layout.tsx",
  "/home/user/app/apps/ui/src/app/(with-sidebar)/dashboard/page.tsx",
  "/home/user/app/apps/ui/src/components/Element/Box/FlexBox.tsx",
  "/home/user/app/apps/ui/src/components/Element/Form/FormInput.tsx",
  "/home/user/app/apps/ui/src/components/Element/Image/BrandLogo.tsx",
  "/home/user/app/apps/ui/src/components/Element/Link/Link.tsx",
  "/home/user/app/apps/ui/src/components/Element/Text/CopyrightText.tsx",
  "/home/user/app/apps/ui/src/components/Header/Header.stories.tsx",
  "/home/user/app/apps/ui/src/components/Header/Header.tsx",
  "/home/user/app/apps/ui/src/components/Loading/Loading.tsx",
  "/home/user/app/apps/ui/src/components/Mui/MuiProvider.tsx",
  "/home/user/app/apps/ui/src/components/Sidebar/Sidebar.stories.tsx",
  "/home/user/app/apps/ui/src/components/Sidebar/Sidebar.tsx",
  "/home/user/app/apps/ui/src/stories/Button.tsx",
  "/home/user/app/apps/ui/src/stories/Header.tsx",
  "/home/user/app/apps/ui/src/stories/Page.tsx",
  "/home/user/app/apps/ui/.next/types/routes.d.ts",
  "/home/user/app/apps/ui/.next/types/validator.ts"
 ],
 "options": {
  "declaration": true,
  "declarationMap": true,
  "esModuleInterop": true,
  "incremental": false,
  "isolatedModules": true,
  "lib": [
   "lib.es2022.d.ts",
   "lib.dom.d.ts",
   "lib.dom.iterable.d.ts"
  ],
  "moduleDetection": 3,
  "noUncheckedIndexedAccess": true,
  "resolveJsonModule": true,
  "skipLibCheck": true,
  "strict": true,
  "target": 9,
  "plugins": [
   {
    "name": "next"
   }
  ],
  "module": 99,
  "moduleResolution": 100,
  "allowJs": true,
  "jsx": 1,
  "noEmit": true,
  "baseUrl": "/home/user/app/apps/ui",
  "paths": {
   "@/*": [
    "./src/*"
   ]
  },
  "experimentalDecorators": true,
  "pathsBasePath": "/home/user/app/apps/ui",
  "configFilePath": "/home/user/app/apps/ui/tsconfig.json"
 }
}
Info 12   [23:46:31.390] Enabling plugin next from candidate paths: /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5,/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js/../../..
Info 13   [23:46:31.390] Loading next from /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5 (resolved to /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules)
Info 14   [23:46:31.399] Loading next from /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js/../../.. (resolved to /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/node_modules)
Info 15   [23:46:31.399] Failed to load module 'next' from /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules: Error: Could not resolve JS module 'next' starting at '/home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules'. Looked in: /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules/next/package.json, /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules/next.js, /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules/next.jsx, /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules/next/index.js, /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules/next/index.jsx, /home/user/.vscode-server/extensions/node_modules/next/package.json, /home/user/.vscode-server/extensions/node_modules/next.js, /home/user/.vscode-server/extensions/node_modules/next.jsx, /home/user/.vscode-server/extensions/node_modules/next/index.js, /home/user/.vscode-server/extensions/node_modules/next/index.jsx, /home/user/.vscode-server/node_modules/next/package.json, /home/user/.vscode-server/node_modules/next.js, /home/user/.vscode-server/node_modules/next.jsx, /home/user/.vscode-server/node_modules/next/index.js, /home/user/.vscode-server/node_modules/next/index.jsx, /home/user/node_modules/next/package.json, /home/user/node_modules/next.js, /home/user/node_modules/next.jsx, /home/user/node_modules/next/index.js, /home/user/node_modules/next/index.jsx, /home/node_modules/next/package.json, /home/node_modules/next.js, /home/node_modules/next.jsx, /home/node_modules/next/index.js, /home/node_modules/next/index.jsx, /node_modules/next/package.json, /node_modules/next.js, /node_modules/next.jsx, /node_modules/next/index.js, /node_modules/next/index.jsx
    at resolveJSModule (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:45067:11)
    at Object.require (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:8396:30)
    at _Project.importServicePluginSync (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:187231:27)
    at _ProjectService.requestEnablePlugin (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:193117:16)
    at ConfiguredProject2.enablePlugin (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:188529:25)
    at ConfiguredProject2.enablePluginsWithOptions (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189285:14)
    at _ProjectService.loadConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:191191:13)
    at _ProjectService.reloadConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:191465:10)
    at ConfiguredProject2.updateGraph (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189214:29)
    at updateWithTriggerFile (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189762:11)
    at updateConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189770:9)
    at updateProjectFoundUsingFind (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189705:28)
    at _ProjectService.findCreateOrReloadConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192356:62)
    at _ProjectService.tryFindDefaultConfiguredProjectForOpenScriptInfo (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192391:25)
    at _ProjectService.tryFindDefaultConfiguredProjectAndLoadAncestorsForOpenScriptInfo (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192549:25)
    at _ProjectService.assignProjectToOpenedScriptInfo (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192302:27)
    at /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192855:27
    at Array.forEach (<anonymous>)
    at _ProjectService.applyChangesInOpenFiles (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192852:56)
    at updateOpen (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:194084:29)
    at /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196809:15
    at IpcIOSession.executeWithRequestId (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196798:14)
    at IpcIOSession.executeCommand (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196807:29)
    at IpcIOSession.onMessage (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196855:68)
    at process.<anonymous> (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/_tsserver.js:519:14)
    at process.emit (node:events:518:28)
    at emit (node:internal/child_process:949:14)
    at process.processTicksAndRejections (node:internal/process/task_queues:91:21)
Info 16   [23:46:31.399] Failed to load module 'next' from /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/node_modules: Error: Could not resolve JS module 'next' starting at '/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/node_modules'. Looked in: /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/next/package.json, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/next.js, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/next.jsx, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/next/index.js, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/next/index.jsx, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/node_modules/next/package.json, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/node_modules/next.js, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/node_modules/next.jsx, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/node_modules/next/index.js, /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/node_modules/next/index.jsx, /vscode/vscode-server/bin/linux-arm64/node_modules/next/package.json, /vscode/vscode-server/bin/linux-arm64/node_modules/next.js, /vscode/vscode-server/bin/linux-arm64/node_modules/next.jsx, /vscode/vscode-server/bin/linux-arm64/node_modules/next/index.js, /vscode/vscode-server/bin/linux-arm64/node_modules/next/index.jsx, /vscode/vscode-server/bin/node_modules/next/package.json, /vscode/vscode-server/bin/node_modules/next.js, /vscode/vscode-server/bin/node_modules/next.jsx, /vscode/vscode-server/bin/node_modules/next/index.js, /vscode/vscode-server/bin/node_modules/next/index.jsx, /vscode/vscode-server/node_modules/next/package.json, /vscode/vscode-server/node_modules/next.js, /vscode/vscode-server/node_modules/next.jsx, /vscode/vscode-server/node_modules/next/index.js, /vscode/vscode-server/node_modules/next/index.jsx, /vscode/node_modules/next/package.json, /vscode/node_modules/next.js, /vscode/node_modules/next.jsx, /vscode/node_modules/next/index.js, /vscode/node_modules/next/index.jsx, /node_modules/next/package.json, /node_modules/next.js, /node_modules/next.jsx, /node_modules/next/index.js, /node_modules/next/index.jsx
    at resolveJSModule (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:45067:11)
    at Object.require (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:8396:30)
    at _Project.importServicePluginSync (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:187231:27)
    at _ProjectService.requestEnablePlugin (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:193117:16)
    at ConfiguredProject2.enablePlugin (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:188529:25)
    at ConfiguredProject2.enablePluginsWithOptions (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189285:14)
    at _ProjectService.loadConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:191191:13)
    at _ProjectService.reloadConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:191465:10)
    at ConfiguredProject2.updateGraph (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189214:29)
    at updateWithTriggerFile (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189762:11)
    at updateConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189770:9)
    at updateProjectFoundUsingFind (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:189705:28)
    at _ProjectService.findCreateOrReloadConfiguredProject (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192356:62)
    at _ProjectService.tryFindDefaultConfiguredProjectForOpenScriptInfo (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192391:25)
    at _ProjectService.tryFindDefaultConfiguredProjectAndLoadAncestorsForOpenScriptInfo (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192549:25)
    at _ProjectService.assignProjectToOpenedScriptInfo (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192302:27)
    at /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192855:27
    at Array.forEach (<anonymous>)
    at _ProjectService.applyChangesInOpenFiles (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:192852:56)
    at updateOpen (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:194084:29)
    at /vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196809:15
    at IpcIOSession.executeWithRequestId (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196798:14)
    at IpcIOSession.executeCommand (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196807:29)
    at IpcIOSession.onMessage (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js:196855:68)
    at process.<anonymous> (/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/_tsserver.js:519:14)
    at process.emit (node:events:518:28)
    at emit (node:internal/child_process:949:14)
    at process.processTicksAndRejections (node:internal/process/task_queues:91:21)
Info 17   [23:46:31.399] Couldn't find next
Info 18   [23:46:31.399] Loading global plugin @vscode/copilot-typescript-server-plugin
Info 19   [23:46:31.399] Enabling plugin @vscode/copilot-typescript-server-plugin from candidate paths: /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5,/vscode/vscode-server/bin/linux-arm64/385651c938df8a906869babee516bffd0ddb9829/extensions/node_modules/typescript/lib/typescript.js/../../..
Info 20   [23:46:31.400] Loading @vscode/copilot-typescript-server-plugin from /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5 (resolved to /home/user/.vscode-server/extensions/github.copilot-chat-0.31.5/node_modules)
Info 21   [23:46:31.404] Plugin validation succeeded
Info 22   [23:46:31.406] Starting updateGraphWorker: Project: /home/user/app/apps/ui/tsconfig.json
Info 23   [23:46:52.087] Finishing updateGraphWorker: Project: /home/user/app/apps/ui/tsconfig.json projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed: 20681.587550999997ms
Info 24   [23:46:52.088] Project '/home/user/app/apps/ui/tsconfig.json' (Configured)
Info 25   [23:46:52.088] 	Files (1549)

Info 26   [23:46:52.088] -----------------------------------------------
Info 27   [23:47:07.346] AutoImportProviderProject: found 21989 root files in 9 dependencies 0 referenced projects in 15259.004922999997 ms
Info 28   [23:47:07.347] Creating AutoImportProviderProject: /dev/null/autoImportProviderProject1*, currentDirectory: /home/user/app/apps/ui
Info 29   [23:48:22.463] Starting updateGraphWorker: Project: /dev/null/autoImportProviderProject1*
Info 30   [23:52:07.531] Finishing updateGraphWorker: Project: /dev/null/autoImportProviderProject1* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed: 225067.282058ms
Info 31   [23:52:07.531] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 32   [23:52:07.531] 	Files (23722)

Info 33   [23:52:07.531] -----------------------------------------------
Info 34   [23:52:07.543] Project '/home/user/app/apps/ui/tsconfig.json' (Configured)
Info 34   [23:52:07.543] 	Files (1549)

Info 34   [23:52:07.543] -----------------------------------------------
Info 34   [23:52:07.543] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 34   [23:52:07.543] 	Files (23722)

Info 34   [23:52:07.543] -----------------------------------------------
Info 34   [23:52:07.543] Open files: 
Info 34   [23:52:07.543] 	FileName: /home/user/app/apps/ui/src/app/page.tsx ProjectRootPath: /home/user/app
Info 34   [23:52:07.543] 		Projects: /home/user/app/apps/ui/tsconfig.json
Info 34   [23:52:07.544] Host configuration update for file /home/user/app/apps/ui/src/app/page.tsx
Info 35   [23:52:07.545] FileWatcher:: Triggered with /home/user/app/apps/ui/.next/types/routes.d.ts 1:: WatchInfo: /home/user/app/apps/ui/.next/types/routes.d.ts 500 undefined WatchType: Closed Script info
Info 36   [23:52:07.545] Elapsed:: 0.42858299997169524ms FileWatcher:: Triggered with /home/user/app/apps/ui/.next/types/routes.d.ts 1:: WatchInfo: /home/user/app/apps/ui/.next/types/routes.d.ts 500 undefined WatchType: Closed Script info
Info 37   [23:52:07.545] FileWatcher:: Triggered with /home/user/app/apps/ui/.next/types/routes.d.ts 1:: WatchInfo: /home/user/app/apps/ui/.next/types/routes.d.ts 500 undefined WatchType: Closed Script info
Info 38   [23:52:07.545] Elapsed:: 0.08854100003372878ms FileWatcher:: Triggered with /home/user/app/apps/ui/.next/types/routes.d.ts 1:: WatchInfo: /home/user/app/apps/ui/.next/types/routes.d.ts 500 undefined WatchType: Closed Script info
Info 39   [23:52:07.545] FileWatcher:: Triggered with /home/user/app/apps/ui/.next/types/validator.ts 1:: WatchInfo: /home/user/app/apps/ui/.next/types/validator.ts 500 undefined WatchType: Closed Script info
Info 40   [23:52:07.545] Elapsed:: 0.028708000027108938ms FileWatcher:: Triggered with /home/user/app/apps/ui/.next/types/validator.ts 1:: WatchInfo: /home/user/app/apps/ui/.next/types/validator.ts 500 undefined WatchType: Closed Script info
Info 41   [23:52:07.546] Project '/home/user/app/apps/ui/tsconfig.json' (Configured)
Info 41   [23:52:07.546] 	Files (1549)

Info 41   [23:52:07.546] -----------------------------------------------
Info 41   [23:52:07.546] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 41   [23:52:07.546] 	Files (23722)

Info 41   [23:52:07.546] -----------------------------------------------
Info 41   [23:52:07.546] Open files: 
Info 41   [23:52:07.554] getConfigFileNameForFile:: File: /home/user/app/apps/ui/src/app/page.tsx ProjectRootPath: /home/user/app:: Result: /home/user/app/apps/ui/tsconfig.json
Info 42   [23:52:07.554] Starting updateGraphWorker: Project: /home/user/app/apps/ui/tsconfig.json
Info 43   [23:52:07.575] Finishing updateGraphWorker: Project: /home/user/app/apps/ui/tsconfig.json projectStateVersion: 2 projectProgramVersion: 1 structureChanged: false structureIsReused:: Not Elapsed: 20.748041999991983ms
Info 44   [23:52:07.581] Project '/home/user/app/apps/ui/tsconfig.json' (Configured)
Info 44   [23:52:07.581] 	Files (1549)

Info 44   [23:52:07.581] -----------------------------------------------
Info 44   [23:52:07.581] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 44   [23:52:07.581] 	Files (23722)

Info 44   [23:52:07.581] -----------------------------------------------
Info 44   [23:52:07.581] Open files: 
Info 44   [23:52:07.581] 	FileName: /home/user/app/apps/ui/src/app/page.tsx ProjectRootPath: /home/user/app
Info 44   [23:52:07.581] 		Projects: /home/user/app/apps/ui/tsconfig.json
Info 44   [23:52:07.582] Host configuration update for file /home/user/app/apps/ui/src/app/page.tsx
Info 45   [23:52:10.046] Before ensureProjectForOpenFiles:
Info 46   [23:52:10.046] Project '/home/user/app/apps/ui/tsconfig.json' (Configured)
Info 46   [23:52:10.046] 	Files (1549)

Info 46   [23:52:10.046] -----------------------------------------------
Info 46   [23:52:10.046] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 46   [23:52:10.046] 	Files (23722)

Info 46   [23:52:10.046] -----------------------------------------------
Info 46   [23:52:10.046] Open files: 
Info 46   [23:52:10.046] 	FileName: /home/user/app/apps/ui/src/app/page.tsx ProjectRootPath: /home/user/app
Info 46   [23:52:10.046] 		Projects: /home/user/app/apps/ui/tsconfig.json
Info 46   [23:52:10.046] After ensureProjectForOpenFiles:
Info 47   [23:52:10.046] Project '/home/user/app/apps/ui/tsconfig.json' (Configured)
Info 47   [23:52:10.046] 	Files (1549)

Info 47   [23:52:10.046] -----------------------------------------------
Info 47   [23:52:10.046] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 47   [23:52:10.046] 	Files (23722)

Info 47   [23:52:10.046] -----------------------------------------------
Info 47   [23:52:10.046] Open files: 
Info 47   [23:52:10.046] 	FileName: /home/user/app/apps/ui/src/app/page.tsx ProjectRootPath: /home/user/app
Info 47   [23:52:10.046] 		Projects: /home/user/app/apps/ui/tsconfig.json
Info 47   [23:52:10.046] got projects updated in background /home/user/app/apps/ui/src/app/page.tsx

このログから以下の事が分かりました。

  1. next プラグインの読み込みに失敗している
  2. 起動に5分40秒かかっている (23:46:30 ~ 23:52:10)
    特に autoImportProviderProject1 のグラフ更新に3分45秒もかかっている
  3. autoImportProviderProject1 のグラフ更新の対象ファイルが 23722 ファイルもある

それぞれ原因調査と対応を行いました。

next プラグインの読み込みに失敗している

ログを見て初めて気付いたのですが実は next プラグインの読み込みに失敗していました。
解決方法は公式にあります。
デフォルトでは VSCode 組み込みの TypeScript が自動で使われるみたいなので、node_modules 内の TypeScript を使うように設定を変更します。

.ts ファイル等を開いた状態でコマンドパレットで以下を実行します。

> TypeScript: Select TypeScript Version...
Use WorkSpace Version

これでエラーが解消されます。

起動時間を短縮する

分析

まず何にどれだけかかっているかを分析しました。

項目 所要時間 備考
サーバー起動 1s -
プラグイン読み込み <1s 失敗している
メインプロジェクトのグラフ更新 21s 1549ファイルが対象
現在のプロジェクトの依存関係スキャン 15s 9個の依存関係とそれに紐づく21989ファイル
現在のプロジェクトの作成 75s apps/uiimport プロジェクトを新規作成
現在のプロジェクトのグラフ更新 225s 23722ファイルが対象
事後処理 3s -

作業プロジェクト (apps/ui) に関連する処理が大半を占めています。
なので apps/ui/tsconfig.json を重点的に見直しました。

以下、修正前の tsconfig.json です。
ほぼ turbo で初期化した時のままの状態で使っていました。

tsconfig.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "esModuleInterop": true,
    "isolatedModules": true,
    "lib": ["es2022", "DOM", "DOM.Iterable"],
    "moduleDetection": "force",
    "noUncheckedIndexedAccess": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "strict": true,
    "target": "ES2022",
    "plugins": [{ "name": "next" }],
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "allowJs": true,
    "jsx": "preserve",
    "noEmit": true,

    "experimentalDecorators": true,
    "incremental": false,
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] }
  },
  "exclude": [
    "node_modules",
    ".turbo"
  ],
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "next-env.d.ts",
    "next.config.ts",
    ".next/types/**/*.ts"
  ]
}

5分40秒 -> 1分41秒

キャッシュを削除したら起動速度が劇的に改善しました。
やったことは以下です。

  • Devcontainer を Without Cache で起動
    -> Devcontainer を使っていない場合は OS 毎に個別の場所に作成される cache を削除しにいく必要があります。以下参考

https://qiita.com/yarnaimo/items/3e3c39d4b0e0c0ade8e5

  • node_modules を削除して再インストール
    -> 成り行きで同時にやってしまいましたが、やらなくてもいいかも知れません。
tsserver.log (一部)
Info 0    [06:36:20.741] Starting TS Server
Info 1    [06:36:20.741] Version: 5.9.2
・
・
・
Info 29   [06:38:01.450] Finishing updateGraphWorker: Project: /dev/null/autoImportProviderProject1* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed: 89967.958082ms
Info 30   [06:38:01.450] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 31   [06:38:01.450] 	Files (23722)

1分41秒 -> 42秒

autoImportProviderProject1 のグラフ更新の際に23722ファイルが収集対象として抽出されています。
構築したばかりの小規模なプロジェクトであったため、これは異常に大きい数値です。
原因を調査したところ、プロジェクトで依存関係に含めていたアイコン集のパッケージが原因でした。
弊社では MaterialUI を使用していて、その流れで @mui/icons-material を使用しているのですが、このアイコン集には 2100+アイコン * 5バリエーション計10500超 のコンポーネントが含まれており、TSServer 起動時にこの大量のコンポーネントの型定義や依存関係ノードを構築するのに時間がかかっていたみたいでした。

一旦、このアイコン集を依存関係から外した際の結果が以下です。
ファイル数が 23722 -> 2175 と激減し、起動時間もかなり改善しました。
今後のアイコンの使用方法については、ローカルパッケージに切り出して必要なもののみをエクスポートするなり、自前で個別に作成するなりの対応方を考えていきます。

tsserver.log (一部)
Info 0    [07:51:13.413] Starting TS Server
Info 1    [07:51:13.413] Version: 5.9.2
・
・
・
Info 29   [07:51:55.430] Finishing updateGraphWorker: Project: /dev/null/autoImportProviderProject1* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed: 5838.458212000005ms
Info 30   [07:51:55.430] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 31   [07:51:55.430] 	Files (2175)

42秒 -> 18秒

tsconfig.json を見直しました。
以下修正した箇所です。
特に declaration の設定を変更した際の効果が大きい印象です。

tsconfig.json
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "compilerOptions": {
-   "declaration": true,
-   "declarationMap": true,
+   "declaration": false, // ライブラリ公開しないので.d.tsは不要
+   "declarationMap": false, // ライブラリ公開しないので.d.ts.mapは不要
    "esModuleInterop": true,
    "isolatedModules": true,
    "lib": ["es2022", "DOM", "DOM.Iterable"],
    "moduleDetection": "force",
    "noUncheckedIndexedAccess": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "strict": true,
    "target": "ES2022",
    "plugins": [{ "name": "next" }],
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "allowJs": true,
    "jsx": "preserve",
    "noEmit": true,

    "experimentalDecorators": true,
-   "incremental": false,
+   "incremental": true, // 増分コンパイルを有効化
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] }
  },
  "exclude": [
    "node_modules",
    ".turbo",
+   ".next"
  ],
  "include": [
    ".next/types/**/*.ts", 
-   "**/*.ts",
-   "**/*.tsx",
-   "next-env.d.ts",
-   "next.config.ts"
+   "./src/**/*.ts",
+   "./src/**/*.tsx",
+   "./next-env.d.ts",
+   "./next.config.ts"
  ]
}
tsserver.log (一部)
Info 0    [09:47:30.107] Starting TS Server
Info 1    [09:47:30.107] Version: 5.9.2
・
・
・
Info 29   [09:47:48.776] Finishing updateGraphWorker: Project: /dev/null/autoImportProviderProject1* projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed: 7220.886045000001ms
Info 30   [09:47:48.776] Project '/dev/null/autoImportProviderProject1*' (AutoImportProvider)
Info 31   [09:47:48.776] 	Files (2175)

おまけ: Devcontainer固有のキャッシュ削除

Devcontainer使用時の VSCode のキャッシュは vscode という名前のボリュームにも蓄積されるみたいで、こちらを削除することで場合によっては速度改善が期待できます。

蓄積されるキャッシュの内容は主に拡張機能関連ですが、全てのDevcontainerで利用している拡張機能関連のキャッシュが単一の vscode ボリュームに蓄積されていきます。
複数のDevcontainerを使っていてコンテナ内に拡張機能を大量にインストールしているような場合は、キャッシュが肥大化してしまっている可能性があるので一度確認してみるのをオススメします。

以下削除後のボリュームのサイズですが、削除前は数GBありました。。

ざっくり手順

  1. 対象のボリュームを確認
  2. 対象のボリュームを使用しているコンテナを確認して削除
  3. 対象のボリュームを削除
vscode volume 削除
# vscode ボリュームのサイズ確認: 無ければ以降の操作は不要です
docker system df -v | grep vscode
# 結果が返ってくること

# vscode ボリュームを使用しているコンテナを確認
docker ps -a --filter volume=vscode
# 削除
docker rm $(docker ps -a -q --filter volume=vscode)
# 成功すること

# vscode ボリュームの削除
docker volume rm vscode
# 成功すること

結果

初回起動を5分40秒から最終的に18秒まで短縮できました。
TSServer の起動の遅さに悩んでいる方いらっしゃいましたら参考にしてみてください。

また以下おまけで tsgo も検証したので結果を貼っておきます。
起動時間はめっちゃ早くなりますが、まだ AutoImportProvider の機能がないみたいで、import の候補が表示されません。
そのため採用はもうちょい先になりそうです。

おまけ2: tsgo (1.4秒)

初回起動時間が1.4秒になりました。。。

パッケージのインストール

bun add -d @typescript/native-preview

設定の編集

settings.json
{
  "typescript.experimental.useTsgo": true
}

拡張機能のインストール

https://marketplace.visualstudio.com/items?itemName=TypeScriptTeam.native-preview

結果

tsgo.log (ログの形式が少し異なります)
Starting language server...
[09:46:20.845] Processed 1 file changes in 50.791µs
・
・
・
======== Cache Statistics ========
[09:46:21.733] Open file count:        1
[09:46:21.733] Cached disk files:   1703
[09:46:21.733] Project count:          1
[09:46:21.733] Config count:           1
[09:46:21.733] Parse cache size:             1549
[09:46:21.733] Program count:                   1
[09:46:21.733] Extended config cache size:      0
・
・
・
[09:46:22.180] Updated watches in 447.39475ms
HCプロデューステックブログ

Discussion