質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

Q&A

解決済

1回答

1937閲覧

Node.jsとexpressを駆使してページ遷移と画像表示を両立したい。miyabi-sunさんにもう一度お聞きしたいです。

mariko68311

総合スコア10

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

0グッド

0クリップ

投稿2021/12/29 15:58

夜遅くに失礼します。時間が経ってしまったのですが、前回の質問を参考にし、プログラムを書き換えて実行できないかためしてみようと思ったものの、上手く動くどころかmiyabi-sunさんに教えてもらったexpressを活用したやり方をやってみようとするとそもそも起動しなくなるという状況になってしまい、泣く泣く前回つかっていたhttpなどを使って起動を試みてみたものの、ただ文字化けた文字が表示されるだけで何も読み込めない、という状況になってしまいました。今のコードはこんな感じになっています。

const http = require('http'); const fs = require('fs'); const url = require('url'); const port = 3000; const server = http.createServer(RouteSetting); server.listen(port, () => { console.log(`Server listening on ${port}`); }); //const express = require("express"); //const app = express(); //app.use(express.static(`${__dirname}/public`)); //app.listen(3000); function getType(_url) { var types = { '.html': 'text/html', '.css': 'text/css', '.js': 'text/javascript', '.png': 'image/png', ".jpg": "image/jpeg" } for (var key in types) { if (_url.parse(key)) { return types[key]; } } return 'text/plain'; } function RouteSetting(req, res) { const url_parts = url.parse(req.url); const path = url_parts.pathname === '/' ? `${__dirname}/index_gest.html` : `${__dirname}/${url_parts.pathname}`; if (fs.existsSync(path)) { fs.readFile(path, (err, file) => { if (err) { // errになるということはパーミッション等の問題で読み取れない重篤なエラーになっている console.error(err); res.writeHead(500, {'Content-Type': getType(url)}); res.end('ファイルを読み込む事ができませんでした'); return; } res.writeHead(200, {'Content-Type': getType(url)}); res.end(file); }); return; } // 最後まで適したページがなければ404を返して終わる res.writeHead(404, {'Content-Type': 'text/plain'}); res.end('お探しのページは見つかりません。'); }

文字化けのページはこうなっています。
イメージ説明
そもそも元のプログラムだとfsをconstで指定していたり(追加すればいいだけなのかもしれないと勝手に思っています)、クソだと言っていたhttpでcreateServer(RouteSetting)と書いていたからRouteSettingは反応していたと思うのでexpressを利用した場合でのpublicにhtmlやcssを入れるときプログラムを使おうとしてみると当然反応しないわけで修正しようにも何も分からない状態のまんまなため困り果ててしまっています。ちなみにvscode studio codeのターミナルから今回のjsファイルをnode ~~~と打って起動しようと
しているのですがこれも何か関係があったりするのでしょうか?
前回の質問を何度読んでも打開策が見つからず、もう一度お話をお聞きしたくて書きました。ご迷惑をおかけしますが、よろしくお願いいたします。何か掲示してほしいというものがあったら教えてください。教えてもらう立場になるからには情報源が足りなくて答えられないということになってしまうと申し訳ないので、、、

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/12/29 17:58

HTML の内容も貼ってもらえませんか? 「画像を押した際に他のページへ遷移」って、普通に静的な HTML だけで実現できると思いますが…。
mariko68311

2021/12/30 05:48

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="./css/style_gest.css"> <title>タイトル</title> </head> <body> <!--タイトルロゴ--> <img src="./images/20211101_055808595_iOS.png" class="title" width=1000px height=200px alt="AlgoMatch"> <!--ゲームスタートボタン--> <form id="game" action="./pieceprogramsettings/pieceprogramsettings_if/pieceprogramseetfings1.html"> <div class="start"> <input type="image" src="./images/GameStart1.jpg" width=500px height=100px alt="ゲームスタート"> </div> </form> <!--ログインボタン--> <form id="rog" action="./login/login.html"> <div class="login"> <input type="image" src="./images/Login.jpg" width=210px height=80px alt="ログイン"> </div> </form> </body> </html> こんな感じになってます、確かにその通りなのですがnode.jsのサーバー上だと遷移ができても画像が表示できないのですよね、、、
guest

回答1

0

ベストアンサー

問題が解決してないのに解決にしちゃダメですよ!

文字化けのページはこうなっています。

バイナリを無理やりUTF-8の文字列に直して表示しているみたいですね。

何かは帰ってきているにも関わらず動いてないということは、
ひょっとしてcontent-typeの指定がおかしいんでしょうか?

という訳でコードを見返したところ、
前回の私の回答に不備があったようです。

res.writeHead(500, {'Content-Type': getType(url)});

このurlという変数はファイル冒頭でconst url = require('url');ってやっている奴ですね。
urlモジュール - Node.js リファレンス

URL文字列をパースするのは結構しんどいのでよく使うんですが、
このurlってのがWebサービスだとよく使うんで変数名が衝突してしまうんですよね。

下記のように直してください。

js

1// 要求しているものがUrlのインスタンスだったものをパスのStringに変更 2function getType(path) { 3 const match = path.match(/.([^.]+)$/); 4 if (!match) return 'text/html'; 5 const types = { 6 html: 'text/html', 7 css: 'text/css', 8 js: 'text/javascript', 9 png: 'image/png', 10 jpg: 'image/jpeg', 11 jpeg: 'image/jpeg', 12 txt: 'text/plain', 13 }; 14 return types[match[1]]; 15} 16 17function RouteSetting(req, res) { 18 const url_parts = url.parse(req.url); 19 const path = url_parts.pathname === '/' 20 ? `${__dirname}/index_gest.html` 21 : `${__dirname}/${url_parts.pathname}`; 22 23 if (fs.existsSync(path)) { 24 fs.readFile(path, (err, file) => { 25 if (err) { 26 console.error(err); 27 // エラーが出ているのでtext/plainに切り替え 28 res.writeHead(500, {'Content-Type': 'text/plain'}); 29 res.end('ファイルを読み込む事ができませんでした'); 30 return; 31 } 32 // urlは冒頭で使っているのでpathを使う 33 res.writeHead(200, {'Content-Type': getType(path)}); 34 res.end(file); 35 }); 36 return; 37 } 38 39 // 最後まで適したページがなければ404を返して終わる 40 res.writeHead(404, {'Content-Type': 'text/plain'}); 41 res.end('お探しのページは見つかりません。'); 42}

そもそも元のプログラムだとfsをconstで指定していたり

(追加すればいいだけなのかもしれないと勝手に思っています)

基本的に変数宣言は全てconstを使ってください。
varは巻き上げ等のバグ挙動を生み出すので以後禁止です。
letは一見constと比べて再代入が可能で便利に思えますが「あまり使いたくない」ものだと覚えてください。

JSに於けるletによる変数宣言は、
値が変わるから「常に見張っておけ」という指示として扱います。
みだりに使うと「常に見張る変数」が多くなりすぎて頭がおかしくなって死にます。
for文等でループしながら再代入する用途等、ごく少数の箇所だけで使いましょう。

ちなみにvscode studio codeのターミナルから今回のjsファイルをnode ~~~と打って起動しようと

しているのですがこれも何か関係があったりするのでしょうか?

これに関しては関係ありません。

expressを利用した場合でのpublicにhtmlやcssを入れるときプログラムを使おうとしてみると当然反応しないわけで修正しようにも何も分からない状態のまんまなため困り果ててしまっています。

そういやindex周りの指定が出来てなかったなぁと思いました。
画像やCSSファイルは取れますが、肝心のindex.htmlファイルが/終わりだと反応しないんじゃないかと思います。

という訳でindex.htmlPugを使って10倍早く書くおまじない込みで解説していきます。
(index_gest.htmlなんてものを用意している時点で、いずれ認証システムとか使いたいと思いますので、Pugは避けては通れないでしょうしね)

https://github.com/miyabisun/express-example
最低限動作するWebサーバのスケルトンを用意しました。

これのコマンド通りに実行すれば動くと思いますし、
このディレクトリ構造を参考に組めば動作するようになると思います。
特にCSSはディレクトリを複数切っている事に注意してください。
画像ファイルも上手い感じの配置とsrc指定を頑張ってみてください。

さて、以降目玉機能のPugに関して解説します。

HTMLは親子をタグで管理する中々親子関係を記述するのに適したかっちりした良いファイルフォーマットです。
しかし実際書くと分かるんですが、死ぬほど編集が面倒くさい弱点があります。

HTMLなんて直接人間が書かなくても、
もっと簡潔に書ける言語で書いて、最後の最後でHTMLにすりゃいいじゃん
こういう発想で存在しているのがテンプレートエンジンです。

Node.jsのPugはHTMLテンプレートエンジンの中ではかなりメジャーな方で
VSCode等のエディタは様々な言語のファイルを読み書きする為のプラグインがあるわけですが、
普通にPugのものも出回っており、すぐに導入して書き始められるはずです。
参考記事: VSCode に必ず入れておきたい拡張機能 - Qiita

それがserver.jsに書いてあるこれらのコードで実現しています。

  • app.set("view engine", "pug");
  • res.render("index", {});

さて、実際のPugの書き方ですが、
親子関係を半角スペース2文字、またはタブで管理します。
これはプログラミング言語のPythonを参考にしたような挙動をします。

views/index.pugはこうなっています。

pug

1doctype html 2html 3 head 4 link(rel="stylesheet", type="text/css", href="/css/style.css") 5 body 6 main 7 h1 Webサーバへようこそ 8 p 1段落目 9 p 2段落目

「親子関係が半角スペース2文字」という前情報さえあれば何となく読めると思います。
これがこうなるわけですね。

html

1<!DOCTYPE html> 2<html> 3 <head> 4 <link rel="stylesheet" type="text/css" href="/css/style.css"> 5 </head> 6 <body> 7 <main> 8 <h1>Webサーバへようこそ</h1> 9 <p>1段落目</p> 10 <p>2段落目</p> 11 </main> 12 </body> 13</html>

実際には生成されたHTMLにインデントは全くない状態になるかとおもいますが、
ブラウザが読む上では知ったことではないので……
一応ホワイトスペースが削られる事により半角スペースがなくなる等の弊害がありますので、
一度開いて確認するようにはしてください。

HTMLのより複雑な構造をPugで書ききる為には
Pug公式サイトの右側の「Language Reference」から、下の2セクションは読んでいくと最低限大丈夫でしょう。


んで、Pugファイルをviewsに放り込んだだけではページ遷移が出来るようにはなりません。
下記のようなエンドポイントを自分で指定してやる必要があります。

js

1app.get("/", (req, res) => { 2 res.render("index", {}); 3}); 4app.get("/index", (req, res) => { 5 res.render("index", {}); 6});

ページ数が増えてくるとこれの指定で手間取るんですけどね……
似たようなページはres.render("index", {});{}の部分を、
{title: "ようこそ、ユーザー名様"}みたいに指定して出し分けてやることで、
不用意なページの生成を押さえ込めるはずです。

この辺で暫く頑張ってみてください。

投稿2021/12/29 18:05

編集2021/12/29 19:11
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mariko68311

2021/12/30 14:20

わかりました、ありがとうございます!またこれでわからないようだったらまた質問するかもです!
mariko68311

2021/12/30 15:06

すみません早速でできてしまいました。 まだpugファイルの作成についてはまだ手をつけられていないのですがそのまえに気になったことがあったため質問させていただきます。 最初の質問で教えてもらったconst express等の文に今回の修正文を組み合わせて手始めに実行しようとしたところ、以下のエラー文が表示されました。 Error: Cannot find module 'express' これってそのまま訳したときにexpressが見つからないとあるのですが、指定しているのに見つからないとはどういうことなのでしょうか? それともう一つ聞きたいことがあって、修正した文でもfunction RouteSettingと記述していますが、現状 'RouteSetting' が宣言されていますが、その値が読み取られることはありません。ts(6133) と表示されている状態であり、指定するにも現在express文が正常に機能していないと思えるため組み込むにしても手がつけられません。ここが解決しないとpugファイルの作成どころではないため重ね重ねご迷惑をおかけしますが、よろしくお願いいたします。
miyabi-sun

2021/12/30 16:32

> Error: Cannot find module 'express' Node.jsでrequireするモジュールはnode_modules内に存在しなければなりません。 package.jsonのdependencesキーの中に記載されているので確認しましょう。 これらのファイルは`npm install`コマンドのみで一撃で全てのモジュールをダウンロードしてくれます。 貴方のプロジェクトに持って帰る時は、 package.jsonのdependencesを確認しながら 自分のプロジェクトのpackage.jsonがあるディレクトリに戻ってから`npm install express`等のコマンドを行ってください。 npmがnode_modulesディレクトリにモジュールを導入し、 padckage.jsonのdependencesを書き換えて「これインストールしておいたからね」と教えてくれます。 expressでは関数functions RouteSettingは不要です。 あれはhttpモジュールで何とかしようと頑張った末の工夫であり、 expressを使う場合はそのコードは不要なので捨ててください。 とりあえずserver_http.jsとexpress_server.jsみたいな感じでファイルを分けて管理、 express版でよくね?となったらhttp版のserver_http.jsを削除して取り除きましょう。
mariko68311

2022/01/07 02:29 編集

すみません、新年で忙しかったり体調不良でうごけなかったりで今まで動けませんでした。 pugを使ったシステム処理に関しては無事画像を表示することができたのですが、ページ遷移の指定がうまくいかなくなってしまいました。 viewフォルダの中にあるindex_gest.pugからlogin.pugに遷移したいのですが、 Cannot GET /login.pug とでてしまってうまく指定できません。 ちなみにpug内のformタグでは、 form#rog(action="./login.pug") で、server.js内では、 app.get("/login", (req, res) => { res.render("login", {}); }); と現状指定しています。指定の仕方が悪いのか、それともpugファイルの位置が悪いのか、どちらなのでしょうか?
mariko68311

2022/01/07 02:30

上の質問の内容を大きく変えました。よろしくお願いします。
mariko68311

2022/01/07 05:10

ごめんなさいいけました!ベストアンサーにさせてもらいます、また別件で聞きたいことがあったら聞くかもです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問