4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Next.jsをCloud FunctionsにDeployする

Last updated at Posted at 2021-08-17

Cloud Functionsは、イベントドリブンサーバーレスプラットフォームです。コードをuploadすると、HTTPリクエスト経由で呼び出すことができます。

Next.jsで作ったクライアントサイドのアプリをホスティングします。

これは、「Cloud Functions を使用した動的コンテンツの配信とマイクロサービスのホスティング」というやり方らしいです。

プロジェクトの作成

を参考に作成します。

node -v: v15.9.0
だった。versionについては調べずにざっくり作業していきます。

npx create-next-app --example with-firebase-hosting with-firebase-hosting-app

.firebasercにプロジェクトIDを書き込む。

.firebaserc
{
  "projects": {
    "default": "hoge-XXXXXX"
  }
}
firebase use default

で、defaultプロジェクトを現在の「アクティブ プロジェクト」として使用します。

Deploy

npm run deploy
> deploy
> firebase deploy --only functions,hosting


=== Deploying to 'hoge-XXXXXX'...

i  deploying functions, hosting
Running command: npm --prefix "$PROJECT_DIR" install

up to date, audited 1020 packages in 2s

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

found 0 vulnerabilities
Running command: npm --prefix "$PROJECT_DIR" run build

> build
> next build src/

info  - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
info  - Checking validity of types  
warn  - No ESLint configuration detected. Run next lint to begin setup
info  - Creating an optimized production build  
info  - Compiled successfully
info  - Collecting page data  
info  - Generating static pages (4/4)
info  - Finalizing page optimization  

Page                             Size     First Load JS
┌ ○ /                            1.76 kB        68.7 kB
├ ○ /404                         194 B          67.1 kB
└ ○ /about                       1.76 kB        68.7 kB
+ First Load JS shared by all    66.9 kB
  ├ chunks/framework.65bc65.js   42 kB
  ├ chunks/main.870523.js        23.1 kB
  ├ chunks/pages/_app.9bccc5.js  977 B
  └ chunks/webpack.61f1b6.js     778 B

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)
   (ISR)     incremental static regeneration (uses revalidate in getStaticProps)

✔  functions: Finished running predeploy script.
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
✔  functions: required API cloudfunctions.googleapis.com is enabled
⚠  functions: missing required API cloudbuild.googleapis.com. Enabling now...

Error: Your project hoge-XXXXX must be on the Blaze (pay-as-you-go) plan to complete this command. Required API cloudbuild.googleapis.com can't be enabled until the upgrade is complete. To upgrade, visit the following URL:

Your project hoge-XXXXX must be on the Blaze (pay-as-you-go) plan to complete this command. Required API cloudbuild.googleapis.com can't be enabled until the upgrade is complete. To upgrade, visit the following URL:

「Blazeプランじゃないとコマンドは完了できないよ」という文言が丁寧に表示されます。従量課金プランじゃないとダメなようです。

Blazeプランに変更した

npm run deploy

を再度試みる。

> deploy
> firebase deploy --only functions,hosting


=== Deploying to 'hoge-XXXXXX'...

i  deploying functions, hosting
Running command: npm --prefix "$PROJECT_DIR" install

up to date, audited 1020 packages in 2s

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

found 0 vulnerabilities
Running command: npm --prefix "$PROJECT_DIR" run build

> build
> next build src/

info  - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
info  - Checking validity of types  
warn  - No ESLint configuration detected. Run next lint to begin setup
info  - Creating an optimized production build  
info  - Compiled successfully
info  - Collecting page data  
info  - Generating static pages (4/4)
info  - Finalizing page optimization  

Page                             Size     First Load JS
┌ ○ /                            1.76 kB        68.7 kB
├ ○ /404                         194 B          67.1 kB
└ ○ /about                       1.76 kB        68.7 kB
+ First Load JS shared by all    66.9 kB
  ├ chunks/framework.65bc65.js   42 kB
  ├ chunks/main.870523.js        23.1 kB
  ├ chunks/pages/_app.9bccc5.js  977 B
  └ chunks/webpack.61f1b6.js     778 B

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)
●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)
   (ISR)     incremental static regeneration (uses revalidate in getStaticProps)

✔  functions: Finished running predeploy script.
i  functions: ensuring required API cloudfunctions.googleapis.com is enabled...
i  functions: ensuring required API cloudbuild.googleapis.com is enabled...
⚠  functions: missing required API cloudbuild.googleapis.com. Enabling now...
✔  functions: required API cloudfunctions.googleapis.com is enabled
✔  functions: required API cloudbuild.googleapis.com is enabled
i  functions: preparing . directory for uploading...
i  functions: packaged . (9.91 MB) for uploading
✔  functions: . folder uploaded successfully
i  hosting[hoge-XXXXXX]: beginning deploy...
i  hosting[hoge-XXXXXX]: found 0 files in public
✔  hosting[hoge-XXXXXX]: file upload complete
i  functions: creating Node.js 14 function nextjsFunc(us-central1)...
✔  functions[nextjsFunc(us-central1)]: Successful create operation. 
i  functions: cleaning up build files...
Function URL (nextjsFunc(us-central1)): https://us-central1-hoge-XXXXXX.cloudfunctions.net/nextjsFunc
i  hosting[hoge-XXXXXX]: finalizing version...
✔  hosting[hoge-XXXXXX]: version finalized
i  hosting[hoge-XXXXXX]: releasing new version...
✔  hosting[hoge-XXXXXX]: release complete

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/hoge-XXXXXX/overview
Hosting URL: https://hoge-XXXXXX.web.app

Hosting URLにアクセスすると確かに表示されました。

スクリーンショット 2021-08-17 11.46.21.png

SSGとSSR

Next.jsはSSRとSSGに対応しているのでその辺の挙動を確認してみます。

SSGの確認

src/index.jsxを以下のように変更します。

src/index.jsx
import App from "../components/App";

export default function Home(props) {
  return (
    <App>
      <div>
        <div>{props.isSSR ? <h2>SSR Working</h2> : <h2>SSR Not Works</h2>}</div>

        <div>
          {props.isStatic ? <h2>Static generated</h2> : <h2>is Not Static</h2>}
        </div>
      </div>
    </App>
  );
}

export async function getStaticProps() {
  return { props: { isStatic: true } };
}

ローカルで動かした場合

npm run dev

スクリーンショット 2021-08-17 12.08.20.png

Firebaseにdeployしてみます。

npm run deploy

スクリーンショット 2021-08-17 12.12.21.png

URLをうすしてないので無意味な画像ですが、確かに、Static Generatedと表示されています。

SSRの確認

src/index.jsx
import App from "../components/App";

export default function Home(props) {
  return (
    <App>
      <div>
        <div>{props.isSSR ? <h2>SSR Working</h2> : <h2>SSR Not Works</h2>}</div>

        <div>
          {props.isStatic ? <h2>Static generated</h2> : <h2>is Not Static</h2>}
        </div>
      </div>
    </App>
  );
}

export async function getServerSideProps() {
  return { props: { isSSR: true } };
}

ローカルで動かす

npm run dev

スクリーンショット 2021-08-17 12.15.22.png

Deployしてみましょう。

スクリーンショット 2021-08-17 12.20.12.png

まあ、ローカルと一緒ですね。

getServerSidePropsgetStaticPropsは同時に使えません。ビルドエラーが出ます。

理解する。

ルートディレクトリにfirebaseFunctions.jsなるファイルがあります。

firebaseFunctions.js
const { join } = require('path')
const { https } = require('firebase-functions')
const { default: next } = require('next')

const nextjsDistDir = join('src', require('./src/next.config.js').distDir)

const nextjsServer = next({
  dev: false,
  conf: {
    distDir: nextjsDistDir,
  },
})
const nextjsHandle = nextjsServer.getRequestHandler()

exports.nextjsFunc = https.onRequest((req, res) => {
  return nextjsServer.prepare().then(() => nextjsHandle(req, res))
})

nextjsFuncという関数が定義されています。これは、firebase.jsonhosting.rewritesの中のfunctionsで宣言されています。

firebase.json
{
  "hosting": {
    "public": "public",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "function": "nextjsFunc"
      }
    ]
  },
  "functions": {
    "source": ".",
    "predeploy": [
      "npm --prefix \"$PROJECT_DIR\" install",
      "npm --prefix \"$PROJECT_DIR\" run build"
    ],
    "runtime": "nodejs14"
  }
}

predeployでinstallやbuildをしています。

Cloud Functionsでのリクエストの処理がどういう挙動になっているかというと、

  • まずFirebase Hostingにリクエストが送られる
  • リクエストの送り先が、nexjsFuncというCloud Functionsの関数へと書き換えられる
  • firebaseFunctions.jsの中のnexjsFunc関数がリクエストを処理し、Next.jsのサーバーとしてレンダリングし、レスポンスを返す

となっているようです。

firebaseFunctions.jsの正体は、Cloud Function For Firebaseにデプロイするjsファイルでした。package.jsonのなかでmainkeyのところで設定されています。

package.json
{
  "private": true,
  "main": "firebaseFunctions.js",
}

他にもいろいろ、Firebaseの設定ファイルがあります。Next.jsのレポジトリにドキュメントがあるので見てみましょう。

この辺を参考にしました。

参考

4
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?