Vinextでv1.0のリリースが行われたので試してみた

Vinextでv1.0のリリースが行われたので試してみた

Cloudflareが公開したVinextを使ってNext.jsアプリケーションをAWS Lambda上でSSR化する方法について、プロジェクト構築からデプロイまでの実装例を紹介します。
2026.10.01

こんばんは、情報システム室の夏目です。

先日CloudflareがVinextのv1.0のリリースを行いました。

https://blog.cloudflare.com/vinext-nextjs-on-vite/

今回はこれを使ってNext.jsをAWS LambdaでSSRしてみます。

Vinext

https://vinext.dev/

VinextはCloudflareが作った、Viteを使ってNext.jsアプリケーションを構築するためのツールです。

2月に最初のリリースが行われ、先日v1.0のリリースが行われました。

https://blog.cloudflare.com/ja-jp/vinext/

Next.jsは基本的にTurbopackを使って構築されますが、Vercel以外の場所にデプロイする場合はTurbopackのビルド結果をプラットフォーム毎に再構築する必要があります。

これに対して、Next.jsの出力を適応するのではなく、Next.jsのAPIをVite上で再実装することでCloudflare WorkersやAWS Lambdaなどにデプロイ可能な形式に変換できるようにしたのがVinextです。

Cloudflare Workers以外の環境にデプロイする際には、 Nitro のVite Pluginを使って対応させています。
これにより、AWS Lambdaなど様々な環境に対応した形でビルドすることができます。

試してみる

Cloudflare Workersだとほぼ何も弄らずにデプロイできそうなので、今回はAWSにデプロイすることにします。

具体的にはCloudfrontを前面に置いて、SSRをLambda URL Functions、静的ファイルをS3に置く構成です。
AWSのリソースはTerraformで管理します。

今回のコードは思った以上に多量になったので、完成形のコードをGithubに置いています。

https://github.com/sinofseven/trial-vinext-app

この記事ではコードの説明は最小現になっています。
動くものは上記リポジトリに置いているのでそちらを試してみてください。

1. プロジェクトを作成する

$ npm create vinext-app@latest
npm notice run npx
npm notice run 'create-vinext-app'
  What is your project named? (my-vinext-app) trial-vinext-app
  Choose a deployment platform:
    1. Cloudflare (default)
    2. Node
  Platform [1]: 2

  Pre-render all static routes after build? [y/N]:

Creating a new vinext app in trial-vinext-app.

  Installing dependencies:
    - vinext
    - react-server-dom-webpack

added 159 packages, and audited 160 packages in 10s

29 packages are looking for funding
  run `npm fund` for details

4 moderate severity vulnerabilities

To address all issues, run:
  npm audit fix

Run `npm audit` for details.
npm warn install-scripts 1 package had install scripts blocked because they are not covered by
npm warn install-scripts   fsevents@2.3.3 (install: node-gyp rebuild)
npm warn install-scripts
npm warn install-scripts Run `npm install-scripts ls` to review, or `npm install-scripts approv

  Installing devDependencies:
    - vite
    - @vitejs/plugin-react
    - @vitejs/plugin-rsc

added 10 packages, and audited 170 packages in 1s

31 packages are looking for funding
  run `npm fund` for details

4 moderate severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
npm warn install-scripts 1 package had install scripts blocked because they are not covered by allowScripts:
npm warn install-scripts   fsevents@2.3.3 (install: (install scripts present))
npm warn install-scripts
npm warn install-scripts Run `npm install-scripts ls` to review, or `npm install-scripts approve <pkg>` to allow.

  vinext init complete!

    ✓ Added dependencies to dependencies:
      - vinext
      - react-server-dom-webpack
    ✓ Added dependencies to devDependencies:
      - vite
      - @vitejs/plugin-react
      - @vitejs/plugin-rsc
    ✓ Added "type": "module" to package.json
    ✓ Configured dev script
    ✓ Configured build script
    ✓ Configured start script
    ✓ Generated vite.config.ts
    ✓ Added vinext output directories to .gitignore

  Next steps:

    npm run dev    Start the vinext dev server
    npm run build  Build production output
    npm run start  Start vinext production server

Initialized a git repository.

Success! Created trial-vinext-app at trial-vinext-app

今回はCloudflare WorkersではなくLambda向けにビルドしたいので、PlatformでNodeを選択します。

2. Nitroの設定をする

Cloudflare Workers以外にデプロイするにはNitroが必要なのでそちらもインストールします。

$ cd 
$  npm install nitro

added 18 packages, and audited 188 packages in 2s

31 packages are looking for funding
  run `npm fund` for details

4 moderate severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
npm warn install-scripts 1 package had install scripts blocked because they are not covered by allowScripts:
npm warn install-scripts   fsevents@2.3.3 (install: (install scripts present))
npm warn install-scripts
npm warn install-scripts Run `npm install-scripts ls` to review, or `npm install-scripts approve <pkg>` to allow.

ViteでNitroの設定が必要なので、vite.config.tsを編集します。

vite.config.ts
import vinext from "vinext";
import { defineConfig } from "vite";
+import { nitro } from "nitro/vite";

export default defineConfig({
-  plugins: [vinext()],
+  plugins: [vinext(), nitro({ preset: "aws-lambda" })],
});

AWS Lambda向けにしたいので preset: "aws-lambda" を使用します。

AWS Lambda向けのビルドを行う際、デフォルトで使っているtailwindcssでうまく解決しないという問題が起きました。
@tailwindcss/postcss を使用する場合は app/globals.css を次のように変更します。
(自分はtailwindcssを使っていないので、次のコードはGithubリポジトリに入っていません)

app/globals.css
- @import "tailwindcss";
+ @import "tailwindcss/index.css"

ビルドしてみます。

$ npm run build
npm notice run trial-vinext-app@0.1.0 build
npm notice run vite build
[1/5] analyze client references...
vite v8.3.1 building rsc environment for production...
✓ 269 modules transformed.
✓ built in 258ms
[2/5] analyze server references...
vite v8.3.1 building ssr environment for production...
✓ 142 modules transformed.
✓ built in 60ms
[3/5] build rsc environment...
vite v8.3.1 building rsc environment for production...
✓ 261 modules transformed.
computing gzip size...
node_modules/.nitro/vite/services/rsc/__vinext_cacheability_manifest.js                                                                                                0.02 kB
node_modules/.nitro/vite/services/rsc/__vinext_cacheability_request_projection.js                                                                                      0.02 kB
node_modules/.nitro/vite/services/rsc/__vinext_pregenerated_concrete_paths.js                                                                                          0.05 kB
node_modules/.nitro/vite/services/rsc/_next/static/css/index.t0GYwP6I.css                                                                                              8.43 kB │ gzip:  2.63 kB
node_modules/.nitro/vite/services/rsc/_next/static/route-CL2SpmM5.js                                                                                                   0.08 kB │ gzip:  0.09 kB
node_modules/.nitro/vite/services/rsc/_next/static/client-trace-metadata-DUR2PiYt.js                                                                                   0.34 kB │ gzip:  0.21 kB
node_modules/.nitro/vite/services/rsc/_next/static/request-context-B6eMglmb.js                                                                                         0.54 kB │ gzip:  0.36 kB
node_modules/.nitro/vite/services/rsc/_next/static/rolldown-runtime-lQxo6jP8.js                                                                                        0.74 kB │ gzip:  0.44 kB
node_modules/.nitro/vite/services/rsc/_next/static/framework~index~layout~page~seed-cache~app-route-handler-dispatch~app-page-cache~app-page-c~nozlz7yf-3BE6yltb.js    0.89 kB │ gzip:  0.59 kB
node_modules/.nitro/vite/services/rsc/_next/static/isr-decision-e1jxxm14.js                                                                                            0.89 kB │ gzip:  0.41 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-static-generation-BX8cz43B.js                                                                                   0.91 kB │ gzip:  0.51 kB
node_modules/.nitro/vite/services/rsc/_next/static/next-error-digest-D489CTgr.js                                                                                       1.07 kB │ gzip:  0.61 kB
node_modules/.nitro/vite/services/rsc/_next/static/work-unit-async-storage-C0M1v3Wx.js                                                                                 1.20 kB │ gzip:  0.55 kB
node_modules/.nitro/vite/services/rsc/_next/static/root-params-CA2N3XyK.js                                                                                             1.54 kB │ gzip:  0.76 kB
node_modules/.nitro/vite/services/rsc/_next/static/cacheability-request-CbaS9sm-.js                                                                                    1.88 kB │ gzip:  0.93 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-prerender-endpoints-Cn3yvV87.js                                                                                 2.47 kB │ gzip:  0.99 kB
node_modules/.nitro/vite/services/rsc/_next/static/page-CDT2khaV.js                                                                                                    2.58 kB │ gzip:  0.85 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-page-cache-render-Dq6yKNqD.js                                                                                   2.78 kB │ gzip:  1.23 kB
node_modules/.nitro/vite/services/rsc/_next/static/headers-lmxtuUvP.js                                                                                                 3.14 kB │ gzip:  1.23 kB
node_modules/.nitro/vite/services/rsc/_next/static/seed-cache-SIcRS6_o.js                                                                                              3.46 kB │ gzip:  1.47 kB
node_modules/.nitro/vite/services/rsc/_next/static/unified-request-context-BjVCz3JN.js                                                                                 3.94 kB │ gzip:  1.53 kB
node_modules/.nitro/vite/services/rsc/_next/static/cache-handler-Dw_-7se1.js                                                                                           4.32 kB │ gzip:  1.59 kB
node_modules/.nitro/vite/services/rsc/_next/static/request-pipeline-CgjqB_j6.js                                                                                        4.37 kB │ gzip:  1.82 kB
node_modules/.nitro/vite/services/rsc/_next/static/isr-cache-DqfJsjJL.js                                                                                               4.75 kB │ gzip:  2.25 kB
node_modules/.nitro/vite/services/rsc/_next/static/html-C2-tMIRg.js                                                                                                    5.07 kB │ gzip:  1.80 kB
node_modules/.nitro/vite/services/rsc/_next/static/framework~index~layout~page~seed-cache~app-rsc-response-stage~app-route-handler-dispatch~ap~b2idxmzx-C6la8ZMf.js    5.74 kB │ gzip:  2.37 kB
node_modules/.nitro/vite/services/rsc/_next/static/cache-control-DiNMNVep.js                                                                                           5.77 kB │ gzip:  2.13 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-rsc-response-stage-JZTOCJpg.js                                                                                  7.99 kB │ gzip:  2.82 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-page-cache-ysOcvC7J.js                                                                                          8.12 kB │ gzip:  2.84 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-page-tracing-TgFXcvuC.js                                                                                       11.91 kB │ gzip:  4.73 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-elements-BPJItsVA.js                                                                                           11.95 kB │ gzip:  4.08 kB
node_modules/.nitro/vite/services/rsc/_next/static/cache-request-state-C5z997vW.js                                                                                    12.36 kB │ gzip:  4.09 kB
node_modules/.nitro/vite/services/rsc/_next/static/artifact-compatibility-BEeFGeOC.js                                                                                 12.51 kB │ gzip:  4.33 kB
node_modules/.nitro/vite/services/rsc/_next/static/config-headers-BPxsZtFt.js                                                                                         14.43 kB │ gzip:  4.60 kB
node_modules/.nitro/vite/services/rsc/_next/static/text-stream-iDTzpGjy.js                                                                                            16.78 kB │ gzip:  4.90 kB
node_modules/.nitro/vite/services/rsc/_next/static/fetch-cache-BVe9fcNh.js                                                                                            19.95 kB │ gzip:  7.01 kB
node_modules/.nitro/vite/services/rsc/_next/static/app-route-handler-dispatch-CPWjv0JF.js                                                                             52.45 kB │ gzip: 18.83 kB
node_modules/.nitro/vite/services/rsc/_next/static/framework~index-BdVj9cpT.js                                                                                        74.23 kB │ gzip: 21.29 kB
node_modules/.nitro/vite/services/rsc/index.js                                                                                                                       258.28 kB │ gzip: 74.74 kB

[INEFFECTIVE_DYNAMIC_IMPORT] app/layout.tsx is dynamically imported by \0virtual:vinext-rsc-entry but also statically imported by \0virtual:vinext-rsc-entry, dynamic import will not move modu

✓ built in 209ms
[4/5] build client environment...
vite v8.3.1 building client environment for production...
`output.codeSplitting.groups[0].name` is a function. Set `output.codeSplitting.groups[0].debugName` so the bundler timing report can identify this group.
✓ 134 modules transformed.
computing gzip size...
.output/public/vinext-client-entry-manifest.json                         0.06 kB │ gzip:  0.08 kB
.output/public/.vite/manifest.json                                       1.40 kB │ gzip:  0.35 kB
.output/public/_next/static/css/index.t0GYwP6I.css                       8.43 kB │ gzip:  2.63 kB
.output/public/_next/static/chunks/layout-segment-context-xHwVn8zn.js    0.49 kB │ gzip:  0.34 kB
.output/public/_next/static/chunks/rolldown-runtime-hePW80VL.js          0.71 kB │ gzip:  0.42 kB
.output/public/_next/static/chunks/index-D8BWjOTG.js                   110.49 kB │ gzip: 32.88 kB
.output/public/_next/static/chunks/vinext-CGYk61oO.js                  115.20 kB │ gzip: 34.46 kB
.output/public/_next/static/chunks/framework-2k-VFE-j.js               219.34 kB │ gzip: 68.40 kB

✓ built in 145ms
[5/5] build ssr environment...
vite v8.3.1 building ssr environment for production...
✓ 146 modules transformed.
computing gzip size...
node_modules/.nitro/vite/services/ssr/_next/static/app-prefetch-fetch-queue-DbU8Gz3U.js    0.10 kB │ gzip:  0.11 kB
node_modules/.nitro/vite/services/ssr/_next/static/static.edge-E5lAR9Dk.js                 0.26 kB │ gzip:  0.19 kB
node_modules/.nitro/vite/services/ssr/_next/static/jsx-runtime-27n2UEVc.js                 0.45 kB │ gzip:  0.31 kB
node_modules/.nitro/vite/services/ssr/_next/static/layout-segment-context-cr8sPef1.js      0.47 kB │ gzip:  0.33 kB
node_modules/.nitro/vite/services/ssr/_next/static/streamed-icons-B9GBQCvm.js              0.71 kB │ gzip:  0.46 kB
node_modules/.nitro/vite/services/ssr/_next/static/navigation-errors-s7TvMxYv.js           0.81 kB │ gzip:  0.51 kB
node_modules/.nitro/vite/services/ssr/_next/static/client-page-root-JXRoOV7e.js            1.49 kB │ gzip:  0.88 kB
node_modules/.nitro/vite/services/ssr/_next/static/navigation-server-BePrdUON.js           1.80 kB │ gzip:  0.68 kB
node_modules/.nitro/vite/services/ssr/_next/static/app-router-scroll-C8ls_oLd.js           2.68 kB │ gzip:  1.22 kB
node_modules/.nitro/vite/services/ssr/_next/static/react-dom-BbTx3uMj.js                   3.89 kB │ gzip:  1.41 kB
node_modules/.nitro/vite/services/ssr/_next/static/error-boundary-CJbiIYs3.js              5.78 kB │ gzip:  1.76 kB
node_modules/.nitro/vite/services/ssr/_next/static/react-c3y_GGvx.js                       8.30 kB │ gzip:  3.22 kB
node_modules/.nitro/vite/services/ssr/_next/static/slot-BZ86rCV8.js                       16.52 kB │ gzip:  5.10 kB
node_modules/.nitro/vite/services/ssr/index.js                                           277.24 kB │ gzip: 86.97 kB

[INEFFECTIVE_DYNAMIC_IMPORT] node_modules/vinext/dist/shims/default-global-error.js is dynamically imported by \0virtual:vite-rsc/client-references but also statically imported by node_module

✓ built in 174ms
ℹ Skipping RSC (already built)                                              nitro 5:52:17 PM

◐ Building [Nitro] (preset: aws-lambda, compatibility: 2026-10-01)           nitro 5:52:17 PM
✔ Generated public .output/public                                           nitro 5:52:17 PM
vite v8.3.1 building nitro environment for production...
`output.codeSplitting.groups[0].name` is a function. Set `output.codeSplitting.groups[0].debugName` so the bundler timing report can identify this group.
✓ 110 modules transformed.
nf3: could not resolve `traceInclude` entry "@alinea/generated" from any root
nf3: could not resolve `traceInclude` entry "@appsignal/nodejs" from any root
nf3: could not resolve `traceInclude` entry "@aws-sdk/client-s3" from any root
nf3: could not resolve `traceInclude` entry "@aws-sdk/s3-presigned-post" from any root
nf3: could not resolve `traceInclude` entry "@blockfrost/blockfrost-js" from any root
nf3: could not resolve `traceInclude` entry "@highlight-run/node" from any root
nf3: could not resolve `traceInclude` entry "@huggingface/transformers" from any root
nf3: could not resolve `traceInclude` entry "@jpg-store/lucid-cardano" from any root
nf3: could not resolve `traceInclude` entry "@libsql/client" from any root
nf3: could not resolve `traceInclude` entry "@mikro-orm/core" from any root
nf3: could not resolve `traceInclude` entry "@mikro-orm/knex" from any root
nf3: could not resolve `traceInclude` entry "@node-rs/argon2" from any root
nf3: could not resolve `traceInclude` entry "@node-rs/bcrypt" from any root
nf3: could not resolve `traceInclude` entry "@prisma/client" from any root
nf3: could not resolve `traceInclude` entry "@react-pdf/renderer" from any root
nf3: could not resolve `traceInclude` entry "@sentry/profiling-node" from any root
nf3: could not resolve `traceInclude` entry "@sparticuz/chromium" from any root
nf3: could not resolve `traceInclude` entry "@sparticuz/chromium-min" from any root
nf3: could not resolve `traceInclude` entry "@statsig/statsig-node-core" from any root
nf3: could not resolve `traceInclude` entry "@swc/core" from any root
nf3: could not resolve `traceInclude` entry "@xenova/transformers" from any root
nf3: could not resolve `traceInclude` entry "@zenstackhq/runtime" from any root
nf3: could not resolve `traceInclude` entry "argon2" from any root
nf3: could not resolve `traceInclude` entry "autoprefixer" from any root
nf3: could not resolve `traceInclude` entry "aws-crt" from any root
nf3: could not resolve `traceInclude` entry "bcrypt" from any root
nf3: could not resolve `traceInclude` entry "better-sqlite3" from any root
nf3: could not resolve `traceInclude` entry "canvas" from any root
nf3: could not resolve `traceInclude` entry "chromadb-default-embed" from any root
nf3: could not resolve `traceInclude` entry "config" from any root
nf3: could not resolve `traceInclude` entry "cpu-features" from any root
nf3: could not resolve `traceInclude` entry "cypress" from any root
nf3: could not resolve `traceInclude` entry "dd-trace" from any root
nf3: could not resolve `traceInclude` entry "eslint" from any root
nf3: could not resolve `traceInclude` entry "express" from any root
nf3: could not resolve `traceInclude` entry "firebase-admin" from any root
nf3: could not resolve `traceInclude` entry "htmlrewriter" from any root
nf3: could not resolve `traceInclude` entry "import-in-the-middle" from any root
nf3: could not resolve `traceInclude` entry "isolated-vm" from any root
nf3: could not resolve `traceInclude` entry "jest" from any root
nf3: could not resolve `traceInclude` entry "jsdom" from any root
nf3: could not resolve `traceInclude` entry "keyv" from any root
nf3: could not resolve `traceInclude` entry "libsql" from any root
nf3: could not resolve `traceInclude` entry "mdx-bundler" from any root
nf3: could not resolve `traceInclude` entry "mongodb" from any root
nf3: could not resolve `traceInclude` entry "mongoose" from any root
nf3: could not resolve `traceInclude` entry "newrelic" from any root
nf3: could not resolve `traceInclude` entry "next-mdx-remote" from any root
nf3: could not resolve `traceInclude` entry "next-seo" from any root
nf3: could not resolve `traceInclude` entry "node-cron" from any root
nf3: could not resolve `traceInclude` entry "node-pty" from any root
nf3: could not resolve `traceInclude` entry "node-web-audio-api" from any root
nf3: could not resolve `traceInclude` entry "onnxruntime-node" from any root
nf3: could not resolve `traceInclude` entry "oslo" from any root
nf3: could not resolve `traceInclude` entry "pg" from any root
nf3: could not resolve `traceInclude` entry "pino" from any root
nf3: could not resolve `traceInclude` entry "pino-pretty" from any root
nf3: could not resolve `traceInclude` entry "pino-roll" from any root
nf3: could not resolve `traceInclude` entry "playwright" from any root
nf3: could not resolve `traceInclude` entry "playwright-core" from any root
nf3: could not resolve `traceInclude` entry "prettier" from any root
nf3: could not resolve `traceInclude` entry "prisma" from any root
nf3: could not resolve `traceInclude` entry "puppeteer" from any root
nf3: could not resolve `traceInclude` entry "puppeteer-core" from any root
nf3: could not resolve `traceInclude` entry "ravendb" from any root
nf3: could not resolve `traceInclude` entry "require-in-the-middle" from any root
nf3: could not resolve `traceInclude` entry "rimraf" from any root
nf3: could not resolve `traceInclude` entry "shiki" from any root
nf3: could not resolve `traceInclude` entry "sqlite3" from any root
nf3: could not resolve `traceInclude` entry "thread-stream" from any root
nf3: could not resolve `traceInclude` entry "ts-morph" from any root
nf3: could not resolve `traceInclude` entry "ts-node" from any root
nf3: could not resolve `traceInclude` entry "vscode-oniguruma" from any root
nf3: could not resolve `traceInclude` entry "websocket" from any root
nf3: could not resolve `traceInclude` entry "zeromq" from any root
ℹ Tracing dependencies:                                                           5:52:19 PM
- postcss (8.5.28)
- sharp (0.35.5)
- typescript (7.0.2)
- webpack (5.111.1)
- @img/colour (1.1.0)
- @img/sharp-darwin-arm64 (0.35.5)
- nanoid (3.3.19)
- picocolors (1.1.1)
- source-map-js (1.2.2)
- semver (7.8.5)
- detect-libc (2.1.2)
- es-module-lexer (2.3.2)
- @img/sharp-libvips-darwin-arm64 (1.3.4)
- webpack-sources (3.6.0)
- schema-utils (4.5.0)
- tapable (2.3.3)
- graceful-fs (4.2.11)
- enhanced-resolve (5.26.0)
- chrome-trace-event (1.0.4)
- watchpack (2.5.2)
- mime-db (1.54.0)
- @webassemblyjs/wasm-parser (1.14.1)
- @webassemblyjs/ast (1.14.1)
- @webassemblyjs/wasm-edit (1.14.1)
- ajv-keywords (5.1.0)
- ajv-formats (3.0.1)
- ajv (8.20.0)
- minimizer-webpack-plugin (5.12.0)
- @webassemblyjs/utf8 (1.13.2)
- @webassemblyjs/helper-api-error (1.13.2)
- @webassemblyjs/ieee754 (1.13.2)
- @webassemblyjs/leb128 (1.13.2)
- @webassemblyjs/helper-wasm-bytecode (1.13.2)
- @webassemblyjs/helper-numbers (1.13.2)
- @webassemblyjs/wasm-opt (1.14.1)
- browserslist (4.29.3)
- jest-worker (27.5.1)
- @webassemblyjs/wasm-gen (1.14.1)
- @jridgewell/trace-mapping (0.3.31)
- @webassemblyjs/helper-wasm-section (1.14.1)
- @webassemblyjs/helper-buffer (1.14.1)
- lightningcss (1.32.0)
- terser (5.51.2)
- baseline-browser-mapping (2.11.26)
- node-releases (2.0.57)
- electron-to-chromium (1.5.443)
- @webassemblyjs/floating-point-hex-parser (1.13.2)
- caniuse-lite (1.0.30001814)
- @xtuc/long (4.2.2)
- @xtuc/ieee754 (1.2.0)
- fast-deep-equal (3.1.3)
- json-schema-traverse (1.0.0)
- fast-uri (3.1.8)
- @jridgewell/sourcemap-codec (1.6.0)
- @jridgewell/resolve-uri (3.1.2)
- acorn (8.18.0)
- @jridgewell/source-map (0.3.11)
- supports-color (8.1.1)
- merge-stream (2.0.0)
- @jridgewell/gen-mapping (0.3.13)
- has-flag (4.0.0)
- @typescript/typescript-darwin-arm64 (7.0.2)
- lightningcss-darwin-arm64 (1.32.0)
✔ Traced 63 dependencies (1407 files) in 2449ms.                                  5:52:19 PM
[5:52:19 PM] ℹ Ensure your production environment matches the builder OS and architecture (darwin-arm64) to avoid native module issues.
computing gzip size...
.output/server/_ssr/route-CL2SpmM5.mjs                         0.08 kB │ gzip:   0.09 kB
.output/server/_ssr/app-prefetch-fetch-queue-DbU8Gz3U.mjs      0.09 kB │ gzip:   0.10 kB
.output/server/_runtime.mjs                                    0.17 kB │ gzip:   0.16 kB
.output/server/_ssr/static.edge-E5lAR9Dk.mjs                   0.24 kB │ gzip:   0.17 kB
.output/server/_ssr/client-trace-metadata-DUR2PiYt.mjs         0.34 kB │ gzip:   0.21 kB
.output/server/_ssr/jsx-runtime-27n2UEVc.mjs                   0.42 kB │ gzip:   0.29 kB
.output/server/_ssr/layout-segment-context-cr8sPef1.mjs        0.43 kB │ gzip:   0.31 kB
.output/server/_chunks/ssr-renderer.mjs                        0.46 kB │ gzip:   0.29 kB
.output/server/_ssr/streamed-icons-B9GBQCvm.mjs                0.69 kB │ gzip:   0.45 kB
.output/server/_ssr/rolldown-runtime-lQxo6jP8.mjs              0.70 kB │ gzip:   0.41 kB
.output/server/_ssr/isr-decision-e1jxxm14.mjs                  0.74 kB │ gzip:   0.35 kB
.output/server/_ssr/app-static-generation-BX8cz43B.mjs         0.87 kB │ gzip:   0.49 kB
.output/server/_ssr/client-page-root-JXRoOV7e.mjs              1.45 kB │ gzip:   0.85 kB
.output/server/_ssr/navigation-server-BePrdUON.mjs             1.48 kB │ gzip:   0.59 kB
.output/server/_ssr/cacheability-request-CbaS9sm-.mjs          1.76 kB │ gzip:   0.86 kB
.output/server/_ssr/app-page-cache-render-Dq6yKNqD.mjs         2.25 kB │ gzip:   1.04 kB
.output/server/_ssr/app-prerender-endpoints-Cn3yvV87.mjs       2.42 kB │ gzip:   0.96 kB
.output/server/_ssr/page-CDT2khaV.mjs                          2.45 kB │ gzip:   0.77 kB
.output/server/_ssr/app-router-scroll-C8ls_oLd.mjs             2.63 kB │ gzip:   1.19 kB
.output/server/_ssr/seed-cache-SIcRS6_o.mjs                    3.34 kB │ gzip:   1.42 kB
.output/server/_ssr/react-dom-BbTx3uMj.mjs                     3.85 kB │ gzip:   1.39 kB
.output/server/index.mjs                                       3.91 kB │ gzip:   1.82 kB
.output/server/_ssr/request-context-B6eMglmb.mjs               3.98 kB │ gzip:   1.58 kB
.output/server/_ssr/cache-handler-Dw_-7se1.mjs                 4.43 kB │ gzip:   1.63 kB
.output/server/_ssr/error-boundary-CJbiIYs3.mjs                5.67 kB │ gzip:   1.72 kB
.output/server/_libs/srvx.mjs                                  6.31 kB │ gzip:   2.57 kB
.output/server/_ssr/app-rsc-response-stage-JZTOCJpg.mjs        7.15 kB │ gzip:   2.45 kB
.output/server/_ssr/app-page-cache-ysOcvC7J.mjs                7.35 kB │ gzip:   2.53 kB
.output/server/_ssr/react-c3y_GGvx.mjs                         8.24 kB │ gzip:   3.18 kB
.output/server/_libs/unstorage.mjs                             8.90 kB │ gzip:   3.18 kB
.output/server/_ssr/config-headers-BPxsZtFt.mjs               14.36 kB │ gzip:   4.56 kB
.output/server/_ssr/slot-BZ86rCV8.mjs                         17.25 kB │ gzip:   5.44 kB
.output/server/_libs/h3+rou3+srvx.mjs                         21.69 kB │ gzip:   8.18 kB
.output/server/_libs/ocache.mjs                               23.79 kB │ gzip:   8.89 kB
.output/server/_ssr/fetch-cache-BVe9fcNh.mjs                  33.41 kB │ gzip:  11.20 kB
.output/server/_ssr/app-route-handler-dispatch-CPWjv0JF.mjs   50.44 kB │ gzip:  18.08 kB
.output/server/_ssr/ssr.mjs                                  280.09 kB │ gzip:  87.41 kB
.output/server/_ssr/rsc.mjs                                  400.96 kB │ gzip: 116.12 kB

✓ built in 2.86s
ℹ Generated .output/nitro.json                                                    5:52:19 PM

✔ You can preview this build using npx vite preview                         nitro 5:52:19 PM

途中 nf3: could not resolve `traceInclude` entry "@alinea/generated" from any root などのメッセージが出ましたが、ビルドそのものは正常終了しました。

.output というディレクトリにビルド結果があります。

$ eza -lT -L 2 -F auto --time-style=long-iso .output
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52 .output/
.rw-r--r--@  343 natsume.yuta 2026-10-01 17:52 ├── nitro.json
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52 ├── public/
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52 │   ├── _next/
.rw-r--r--@   65 natsume.yuta 2026-10-01 17:52 │   └── vinext-client-entry-manifest.json
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52 └── server/
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52     ├── _chunks/
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52     ├── _libs/
.rw-r--r--@  173 natsume.yuta 2026-10-01 17:52     ├── _runtime.mjs
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52     ├── _ssr/
.rw-r--r--@ 3.9k natsume.yuta 2026-10-01 17:52     ├── index.mjs
drwxr-xr-x@    - natsume.yuta 2026-10-01 17:52     ├── node_modules/
.rw-r--r--@ 2.3k natsume.yuta 2026-10-01 17:52     └── package.json

.output/public に静的なファイルが、 .output/server にLambda用のコードが入っています。

なので、次のようにしてAWSにデプロイする必要があります。

  • .output/server の中身をzipで固めて、ハンドラーを index.handler とするLambda Functionを作成し、Lambda URL Functionで叩けるようにする
  • .output/public の中身をS3 Bucketに配置する
  • Cloudfrontのディストリビューションを作成し次のように設定する
    • Lambda URL FunctionとS3 Bucketをオリジンにする
    • デフォルトビヘイビアのオリジンをLambda URL Functionとする
    • /_next/* パス配下のビヘイビアを作成し、S3オリジンを参照するようにする

ざっくりと言うとこれだけやれば動くようになります。
.output/public 配下についてはassetsなどのディレクトリが増えたら都度ビヘイビアを増やす必要があります。

3. Githubに上げたコードの解説

Githubに上げたコードは以下のようになっています。

$ eza -alT -F auto --time-style=long-iso
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:17 ./
.rw-r--r--@   53 natsume.yuta 2026-10-01 18:17 ├── .env
.rw-r--r--@  145 natsume.yuta 2026-10-01 18:14 ├── .gitignore
.rw-r--r--@  520 natsume.yuta 2026-10-01 18:14 ├── .oxfmtrc.jsonc
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 ├── app/
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 │   ├── about/
.rw-r--r--@  249 natsume.yuta 2026-10-01 18:14 │   │   └── page.tsx
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 │   ├── api/
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 │   │   └── hello/
.rw-r--r--@   91 natsume.yuta 2026-10-01 18:14 │   │       └── route.ts
.rw-r--r--@   35 natsume.yuta 2026-10-01 18:14 │   ├── globals.css
.rw-r--r--@  580 natsume.yuta 2026-10-01 18:14 │   ├── layout.tsx
.rw-r--r--@  206 natsume.yuta 2026-10-01 18:14 │   └── page.tsx
.rw-r--r--@  104 natsume.yuta 2026-10-01 18:14 ├── next.config.ts
.rw-r--r--@ 137k natsume.yuta 2026-10-01 18:14 ├── package-lock.json
.rw-r--r--@  692 natsume.yuta 2026-10-01 18:14 ├── package.json
.rw-r--r--@  902 natsume.yuta 2026-10-01 18:14 ├── README.md
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 ├── terraform/
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 │   ├── envs/
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 │   │   └── prd/
.rw-r--r--@  975 natsume.yuta 2026-10-01 18:14 │   │       └── terraform.tf
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 │   └── modules/
drwxr-xr-x@    - natsume.yuta 2026-10-01 18:14 │       └── common/
.rw-r--r--@ 2.4k natsume.yuta 2026-10-01 18:14 │           ├── cloudfront.tf
.rw-r--r--@   70 natsume.yuta 2026-10-01 18:14 │           ├── common_data.tf
.rw-r--r--@  601 natsume.yuta 2026-10-01 18:14 │           ├── iam.tf
.rw-r--r--@ 2.1k natsume.yuta 2026-10-01 18:14 │           ├── lambda.tf
.rw-r--r--@  133 natsume.yuta 2026-10-01 18:14 │           ├── logs.tf
.rw-r--r--@  159 natsume.yuta 2026-10-01 18:14 │           ├── output.tf
.rw-r--r--@ 1.1k natsume.yuta 2026-10-01 18:14 │           └── s3.tf
.rw-r--r--@  575 natsume.yuta 2026-10-01 18:14 ├── tsconfig.json
.rw-r--r--@  193 natsume.yuta 2026-10-01 18:14 └── vite.config.ts

terraform/ 配下がAWSリソース管理用のコードになっています。
terraform/envs/prd/terraform.tf がルートとなっており、 terraform/modules/common を参照してリソースの管理をしています。

デプロイは以下の手順で行います。
(環境変数などを使ってAWS CLIでAWSに触れるようにする必要もあります)

$ npm ci
$ npm run build
$ cd terraform/envs/prd
$ terraform init
$ terraform apply -auto-approve

Apply complete!

Outputs:

cloudfront_domain = "00000000000000.cloudfront.net"
public_bucket_name = "trial-vinext-app-000000000000-ap-northeast-1-an"

$ cd ../../../.output/public
$ aws s3 sync . s3://trial-vinext-app-000000000000-ap-northeast-1-an

この後、cloudfront_domainに出力したドメインをブラウザで開けば、動いていることがわかります。

Terraformのコードは特別なことはしていないので、Cloudfrontを使用する場合のサンプルという程度です。

SSRやRoute APIを確認するためのページを作成して、動作を確認してます。


3-1. SSRがきちんとできているか確認するコード

app/check-ssr/page.tsx では環境変数から値を受け取るようにしています。
Lambdaに対して環境変数を設定し、SSRができているか確認するためのコードになっています。

app/about/page.tsx
import Link from "next/link";

export default function CheckSsr() {
  return (
    <>
      <h1 className="title">Check SSR</h1>
      <p>
        <Link href="/">戻る</Link>
      </p>
      <hr />
      <p>{process.env.ABOUT_MESSAGE}</p>
    </>
  );
}
.env
ABOUT_MESSAGE="ローカル用の.envから読み込んでいます"
terraform/modules/common/lambda.tf
resource "aws_lambda_function" "ssr" {
  function_name    = "trial-vinext-tmp-ssr"
  role             = aws_iam_role.lambda.arn
  runtime          = "nodejs24.x"
  architectures    = ["arm64"]
  handler          = "index.handler"
  memory_size      = 512
  timeout          = 30
  s3_bucket        = aws_s3_object.lambda_deploy_package.bucket
  s3_key           = aws_s3_object.lambda_deploy_package.key
  source_code_hash = data.archive_file.lambda_deploy_package.output_base64sha256
  publish          = true
  environment {
    variables = {
      ABOUT_MESSAGE = "SSRで値を入れました!"
    }
  }
}

.env にはローカル開発用の値を、 terraform/modules/common/lambda.tf の環境変数に本番用のコードを書いています。

/check-ssr をブラウザで見ると動いていることがわかります。


npm run dev によってローカルで動かしたとき


Cloudfrontにデプロイしたときの画像


3-2. API Routeが動くことを確認

app/check-ssr/page.tsx ではNext.jsのAPI Routeが動くことを確認しています。
Vinextで作ったプロジェクトには最初から app/api/hello/route.ts があるので、Client Componentのページを作って試しています。

app/check-ssr/page.tsx
"use client";
import Link from "next/link";

export default function CheckApi() {
  async function call() {
    const resp = await fetch("/api/hello");
    const data = (await resp.json()) as { message: string };
    alert(data.message);
  }
  return (
    <>
      <h1 className="title">Check API</h1>
      <p>
        <Link href="/">戻る</Link>
      </p>
      <hr />
      <p>
        <button className="button" onClick={call}>
          Call API hello
        </button>
      </p>
    </>
  );
}


Call API hello ボタンをクリックしたときの画像

動くことは確認できました。

まとめ

今回はv1.0がリリースされたVinextを試してみました。

Next.jsをViteによって構築することで、他の環境へのデプロイを容易にするという意味で非常に便利そうです。
他にもViteで構築しているからこそ、Viteのプラグインを色々使えるというのも良さそうです。

何かのお役に立てたら幸いです。

この記事をシェアする

関連記事