0

I am a newbie, experimenting with JS. I was trying to build a small Node.js app, with a JS script embedded in the index.html, but when I run nodemon, it returns 404 for the script and cant find it. The same html page with embedded script works fine with parcel. What am I doing wrong?

My app.js :

const express = require('express')
app = express()

app.get('/', (req, res, next)=>{
    
    res.sendFile('D:/Node.js Folder/My first project/views/index.html')
    
})

app.get('/add-user', (req, res, next)=>{
    
    res.sendFile('D:/Node.js Folder/My first project/views/add-user.html')
    
})

app.get('/show-user', (req, res, next)=>{
    
    res.sendFile('D:/Node.js Folder/My first project/views/show-users.html')
    
})

app.listen(3000)

HTML File :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
</head>
<body class = "text-gray-400">
    
    <div>
        <div class = "text-3xl">
            <nav>
                <h1>
                    Hello! Welcome to the first page!
                </h1>
                <h1 class = "chat-notification-title">
                    Hello! Welcome to the first page!
                </h1>
                <form>
                    <label for="cname">Company Name</label><br>
                    <input type="text" id="cname" name="cname"><br>
                    <label for="ccode">Company Code</label><br>
                    <input type="text" id="ccode" name="ccode">
                  </form> 
                  <button class ='btn-submit' type = "submit">Add Record</button>
            </nav>
        </div>
    </div><script src="../controller/controller-1.js"></script>
</body>
</html>

Embedded Script :

'use strict'


console.log(document)
const button = document.querySelector('.btn-submit')
console.log(button)
button.addEventListener('click', function () {
    
    console.log('BUTTON PRESSED')
    alert("Pressed")
})

3 Answers3

0

Nodemon are supposed to be used on the server side, often running an express or similar server. parcel serve is what you are supposed to use on the client side (without server), to serve the html files directly.

You should also not use paths to your own disk. Luckily when the project is running it creates a dist folder with the same files. You are meant to link those to paths in code. Ie on res.sendFile you should write res.sendFile(path.resolve("../client/dist/index.html")) or res.sendFile(path.resolve("../dist/views/index.html))

You import path as import * as path from "path"

If you want to use it with a server, then you should do this:

Client json "dev" should parcel watch index.html, and server "dev" should nodemon server.js. Both these scripts are supposed to be run in the root package.json file, with concurrently, allowing them to run simultaneously

"dev": "concurrently npm:server:dev npm:client:dev",
"server:dev": "cd server && npm run dev",
"client:dev": "cd client && npm run dev",

In the server file, you should then do something like this:

import express from "express"; //import express
const app = express(); // use express
app.use(express.static("../client/dist/")); // allows express to server static files

app.use((req, res, next) => {
  if (req.method === "GET" && !req.path.startsWith("/api")) {
    return res.sendFile(path.resolve("../client/dist/index.html"));
  } else {
    next();
  }
}); // checks if url is trying to reach an api, if not it returns the file you are looking for

const server = app.listen(process.env.PORT || 3000, () => {
  console.log("Server started on http://localhost:" + server.address().port);
}); // starts server and logs the localhost url

You are then meant to access your site from the server side, and every time you change the server, nodemon will restart the server for you, and every time you change the client, parcel will do the same

eskiltb
  • 92
  • 8
0

One thing you need to do is stop using absolute paths

for eg. 'D:/Node.js Folder/My first project/views/index.html'

should be ./views/index.html

assuming that the app.js file is in the same folder as the views folder.

The server on which you might deploy this code is not going to have the same path as your pc.

You also might wanna make a static folder and move your html, script (controller) folder inside that and add the following line to the app.js

app.use('/', express.static('static'))

// or

app.use('/', express.static('./static'))

this way you won't have to serve the individual files like you are doing right now.

if you have the src for the embedded file set to ./controller/controller-1.js it will work fine.

  • Edited my question to include code –  May 31 '22 at 13:28
  • Ok, I solved it by adding this to my app.js - app.get('/controller/controller-1.js', (req, res, next)=>{ res.sendFile('D:/Node.js Folder/My first project/controller/controller-1.js') }) Is there another way to get this done? –  May 31 '22 at 13:34
  • you need to stop using absolute paths ASAP – SuperSaiyan99000 May 31 '22 at 14:24
  • Ok, should I use path? const path = require('path'); module.exports = path.dirname(require.main.filename); Or is there a better way to do it? –  Jun 01 '22 at 07:37
  • No I am simply say You need to use canonical paths (these are relative paths and does not depend on the systems file structure only the file structure of the directory you will deploy on the server). I have explained this in the answer. – SuperSaiyan99000 Jun 01 '22 at 17:27
  • `Ok, should I use path? ` Path is used for a better way to modify paths in NodeJS. for which You can use normal string but why would you. – SuperSaiyan99000 Jun 01 '22 at 17:33
  • I explained it as well, you should use `res.sendFile(path.resolve("../client/dist/index.html"));` and `import * as path from "path";` – eskiltb Jun 02 '22 at 11:55
0

I solved it by adding this to my app.js :

app.get('/controller/controller-1.js', (req, res, next)=>{

res.sendFile('D:/Node.js Folder/My first project/controller/controller-1.js')

})

Help from this thread : How to include javascript on client side of node.js?

Is there a better way to do this?

  • 1
    Look at my answer, you are not meant to run from your own drive, but the dist folder. This is so Heroku for instance, and other external services can also access the files – eskiltb May 31 '22 at 13:37
  • Yes that works! Thank you so much. This is a much easier way to do it. Thank you!! –  May 31 '22 at 14:01