lumijoe
@lumijoe

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

ローカルとVercelデプロイでの表示齟齬をなくしたい

ローカルで表示されるように、デプロイでも表示させたい

スクリーンショット 2023-11-13 13.02.24.png

Node.jsde EJSを利用してvercelにデプロイした時に発生しました。
解決方法をご教示ください。

ディレクトリ構造

スクリーンショット 2023-11-13 13.03.59.png

app.js

// app.js 
const http = require('http');
const fs = require('fs').promises;
const ejs = require('ejs');
const url = require('url');
const path = require('path');

// ファイルから読み込む処理をバックグラウンドで実行する非同期処理、readFileメソッド
// 各種ファイルの読み込み
const readIndexPage = fs.readFile(path.join(__dirname, 'index.ejs'), 'utf-8')
  .catch(err => {
     console.error('Error reading index.ejs:', err);
     return '';
  });
const readOtherPage = fs.readFile('./other.ejs', 'utf-8');

var server = http.createServer(getFromClient);

// 開発環境でのPORT3000サーバー指定、デプロイでのVercelサーバー指定をパイプさせる
server.listen(process.env.PORT || 3000);
console.log('Server start!');

// ここまでメインプログラム========

// createServerの処理
async function getFromClient(request, response) {
    var url_parts = url.parse(request.url);
    let content;

    switch (url_parts.pathname) {
        case '/':
            const indexPage = await readIndexPage;
            content = ejs.render(indexPage, {
                title: "Index",
                content: "これはIndexページです。",
            });
            response.writeHead(200, { 'Content-Type': 'text/html' });
            response.write(content);
            response.end();
            break;

        case '/other':
            const otherPage = await readOtherPage;
            content = ejs.render(otherPage, {
                title: "Other",
                content: "これは新しく用意したページです。",
            });
            response.writeHead(200, { 'Content-Type': 'text/html' });
            response.write(content);
            response.end();
            break;

        default:
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.write('no page...');
            response.end();
            break;
    }
}

index.ejs (表示させたいもの)

<!-- index.ejs -->

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta http-equiv="content-type"
        content="text/html"; charset="UTF-8">
    <title><%= title %></title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        crossorigin="anonymous">
</head>

<body class="container">
    <header>
        <h1 class="display-4"><%= title %></h1>
    </header>
    <div role="main">
        <p><%= content %></p>
        <p><a href="/other">Other Pageに移動 &gt;&gt;</a></p>
    </div>
</body>

</html>

package.json

{
  "name": "node-app",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "dev": "nodemon app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "http": "0.0.1-security",
    "nodemon": "^3.0.1"
  },
  "dependencies": {
    "ejs": "^3.1.9"
  }
}

デプロイvercelで表示されてしまうindex.html

<!-- index.html -->

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta http-equiv="content-type"
          content="text/html"; charset="UTF-8">
    <title>Index</title>
</head>

<body>
    <h1>Index</h1>
    <p>これは、Indexページです。</p>   
</body>

</html>

試したり検索したりを繰り返しても、ローカルとデプロイで表示齟齬がある理由がわからない

色々検索し,nodeのversionをvercelと揃えたり、package.jsonのmainをindex.ejsに変更したりしましたが詰んでいます。

・Vercelでは自動でビルドしてデプロイしてくれるものは言語によって違う(今回は手動でビルドが必要なのか?)
・ビルドしていない事が原因?
・package.jsonでmainを指定し間違えてる?
・index.htmlとindex.ejsがデプロイの時にややこしくなってしまっている?

よろしくお願いいたします

0

2Answer

Vercel は package.json の main フィールドを認識せず、 app.js を実行することはありません。また Vercel はサーバーレスなプラットフォームであり、 http モジュールや Express などのサーバーを使ったアプリケーションをデプロイするには向いていません。基本的には Next.js 他の Vercel に対応したフレームワークを使ってください。

どうしてもサーバーを使うのであれば、サーバーレスファンクションとしてサーバーを実行する方法があります。詳しくは以下のページを参照してください。


今のような齟齬が発生している原因は、 Vercel が以下の手順でビルドとデプロイを実行しているためです。

  1. package.json で何らかのフレームワークをインストールしていることが検出されれば、そのフレームワークに合わせたビルドコマンドを実行する。検出されなければカスタムビルドコマンドを実行する(デフォルトでは未設定で、何もしない)。
  2. フレームワークに応じた生成物ディレクトリの内容をデプロイする。フレームワークが検出されなければ public ディレクトリの、それもなければルートディレクトリの内容を生成物とする。

今回はフレームワークをインストールしていないので手順1では何も実行されず、手順2でルートディレクトリの内容がデプロイされます。デフォルトのページは index.html なので、 Vercel で / を開くとその内容が表示されます。

ビルドとデプロイの設定については以下のページに書いてあります。

3Like

Comments

  1. @lumijoe

    Questioner

    これ、URLで試行錯誤したのですが結局解決に至っていません。原因や対策はよく分かりました。本当にありがとうございます!ただ。。。URLを見に行っても手順などが理解し難くまだ解決に至ってないので、Q&Aは閉じずに、再開します。解決実現のための手順がわかるよって方は助けてやってください。どうもメカニズムはわかっても、それをどうやってコードを追加したり修正したりして、VercelのサイトでどうUIをいじればいいのかが理解できていません。

ローカルで検証せず、コツコツ、GitHubリポジトリにpushしながらデプロイしては?

Vercel社の日本法人があるのでしょうか?

indexの拡張子(.tsx)が異なるので別のものなら失礼します。上記urlはNext.jsのサンプルでした。

英語のサンプルでもnode.js少ないです。

p.s. 【爆速でwebサイトが構築できる】python開発フレームワークstreamlitの謳い文句でawsにwebサーバをたてましたが、SPAの開発手法が分からず苦労してます。python2でライブラリーにあったgoto文がSPAであるstreamlit開発に有効であると、今日、検証で確信を得たのは幸いでした。

皆さんも【爆速でwebサイトが構築できる】のキャッチコピーに騙されないで下さい。

1Like

Comments

  1. @lumijoe

    Questioner

    少しづつpushは最近覚えました!デバッグしやすくエラーも発見しやすいので本当にその通りだなと実感しています。先輩エンジニアさんやできるな〜と感じるエンジニアさんは皆さん口を揃えておしゃってますよね、忘れずコツコツやっていきます!色々アドバイスありがとうございます!感謝です!

Your answer might help someone💌