I have a server application which uses this to display the home page
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "/index.html"));
});
and my js file in the index.html has these lines in the head
<script src="/public/js/controller.js" type="module"></script>
<script src="/public/js/main.js" type="module"></script>
the main.js is for the frontend js while the controller is for the backed and it imports model.js and model.js use fs using this line
const fs = require("fs");
but when I try to load the index.html using the node server http://localhost:3000 I get this error
model.js:2 Uncaught ReferenceError: require is not defined
at model.js:2
so I added the require.js library and then used it like this
<script src="/public/js/require.js" ></script>
And then I still get this error
require.js:108 Uncaught Error: Module name "fs" has not been loaded yet for context: _. Use require([])
https://requirejs.org/docs/errors.html#notloaded
at makeError (require.js:108)
at Object.s [as require] (require.js:947)
at requirejs (require.js:134)
at model.js:2
Can someone please advise, what should one do to make this work? I am stuck for more than 2 days on this and I am pretty new to node.js and this 'require' thing.. but I know it's a very important part of node.js.
So I would like to have some clarity and some advise/help on what an html page that's not using a bundler and running directly from a node server have to do to handle this..
and just so that I am clear about what I mean by 'this' all I am trying to do is get a list of folder names that I want use as navigation menu (li items) on the front-end.. I am using this command on node.js to do get the array..
fs.readdir('./data/')
I need to have this array in my index.html which is on the same server/folder/application that is running on node.js..
I assumed that if node.js is displaying an html file (with app.get) I would be able to use the fs command this way.. am I wrong? If so, what do I have to do to use readdir and get the array to display as menu on the front-end?
The "fs" module is a built-in module in NodeJS to allow you to work with the filesystem. It isn't available on the client-side (imagine people can access your webpage and manipulate your filesystem!!).
What you're trying to do is get a list of folder names that you want use as navigation menu (li items) on the front-end. For that, you can get the list of folder names on the server-side using "fs" module, then using template engine to render HTML file with the data.
For NodeJS, there are some popular template engines: EJS, pug, nunjucks....
You might have your server.js as a ES6 module, which is a good thing as it took me an hour to set it up like that myself.
You can do import * as fs from 'fs'; or import {fs} from 'fs'; but I did import { promises as fs } from "fs"; because I like my fs calls async.
Gives it a python feel.
Related
I have a project by Three.js.
Like below pic, i have an index.html that uses js codes from scripts.js (in sub-Directory of js).
also, this scripts.js , uses three and OrbitControls libs of package of three.js.
PROBLEM:
after running my project, browser, shows HTML and CSS fine, but it do not works by javascript and gives this error:
i can't find any solution, after half a Day searching & manipulating!
can any one help please?
1)project structure:
root
|------server.js
|------/public
| |---index.html
| |---/js/scripts.js
| |---/css/index.css
2)root/public/index.html:
3)root/public/js/scripts.js:
4)root/server.js:
const express = require("express");
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, '/public')));
app.get('/',function(req,res) {
res.sendFile("public/index.html")
});
app.listen(3000, () => {console.log("listening on port 3000");});
Multiple things going on here. First, require() is nodejs ONLY, is not present in the browser. You are trying to load and run js/scripts.js in the browser and thus cannot use require() in that script.
Separately, when you use type="module" in a script tag, that means the module is an ESM module which can use import to load other modules, but import needs to specify a URL that your express server will handle and serve the right file with.
I'm also guessing that you will have a problem loading the script files because they need to be served by express.static() in your server and need to have the appropriate URL paths in your web page so that express.static() will work. You don't show the server-side file structure for all those scripts so it's hard for us to know exactly what the URLs should be.
And, in the future, please don't ever post screen shots of code. That makes it a lot harder for us to use your code in tests or in answers (because we have to retype it all from scratch) and it can't be searched, is harder to read on mobile, etc... Don't put code in images.
I am currently making a project using vue-cli which generates a Node project with webpack. I can build all scripts and use the pug language within .vue files. When building, the project uses HTML-Webpack-Plugin, though, which outputs the code as static HTML with client-side scripts.
How do I pass variables from the server-side to these client-side scripts? I previously was using pug, which made this process easy, but since it now gets built into .html files, this can no longer be done.
I have two attempts, both suboptimal:
1. Send variables into clientside scripts
script.
const clinetSideVar = `!{serverSideVar}`;
The problem with this approach is that I cannot pass this variable into the vue instance, since it gets obfuscated when built and I have no way of accessing it (or do I? I haven't found a way).
2. Using AJAX requests
I could also make a restful API for server-side site data and retrieve it using AJAX, but this seems like a real hack and this would lose quite a bit of performance over just sending the data plainly through a pug template (with no. 1 I'd too, since client-side JS would have to insert the data into the DOM).
I'd recommend using JSONP (since your index.html is built ahead of time in Vue-cli).
In your public/index.html (which is a template)
<head>
...
<script>function getServerData(data) { window.__SERVER_DATA__ = data; }</script>
<script src="/api/server-data.json?callback=getServerData"></script>
</head>
In your Node Express routes definition
const app = express();
// ...
app.get('/api/server-data.json', (req, res) => {
res.jsonp({
foo: 'foo',
bar: 'bar'
});
});
Then just access window.__SERVER_DATA__ from within any Vue component.
I have web application which is following below structure.
app_name
bin
node_modules
public
images
javascripts
stylesheets
views
index.html
app.js
package.json
i'm unable to use require() inside /public/javascripts/xxx.js file,it says Uncaught ReferenceError: require is not defined
i'm i missing something ? plz advice.
Uncaught ReferenceError: require is not defined means that you are trying use require in the browser (client side javascript). You cannot require CommonJS modules (i.e. those used in node.js) in the browser.
There are several ways to get around this, including RequireJS and Browserify.
I would suggest using Browserify. You can get a good overview of the pros of using Browserify here
I've managed to properly use webpack dev server alongside with a node server (express), using the plugin section inside webpack's config.
It all works fine but now I'm trying to go isomorphic and use client-side components inside the express application.
So far the only problem I'm encountering is that without webpack 'parsing' my server-side code I get to a situation where I require components but the paths are not solved
I.E.
Inside a component
'use strict';
import React from 'react';
import { RouteHandler, Link } from 'react-router';
import Header from 'components/header/main'; // <-- This line causes the error because webpack is not working when parsing this JSX server-side
export default React.createClass({
displayName: 'App',
render() {
return ( // ... More code
Shall I configure webpack in another way or do I have to change all the imports to be valid server-side?
the codebase is here in case you want to see the actual state https://github.com/vshjxyz/es6-react-flux-node-quickstart
In order to be able to require components in a way such as require('components/Header.js'); and avoid using long relative paths such as require('../../../../../../Header.js'); you can add this code to your node app before any require() calls:
process.env.NODE_PATH = __dirname;
require('module').Module._initPaths();
However, since this relies on a private Node.js core method, this is
also a hack that might stop working on the previous or next version of
node.
Other possible solutions to this problem can be found at https://gist.github.com/branneman/8048520
I see 2 options:
Compile client code with webpack as well. If client's entry
point is in the same dir as server's - it should work with your
present code. This looks natural to me.
Use relative paths i.e.
import Header from './components/header/main'
I'd like to create a dropdown list of files available in a directory on the server.
I believe this is possible using
fs.readFile()
However, in my controller I dont seem to have access to fs.
When I do this:
var fs = require('fs');
I get an error as the following:
Uncaught Error: Module name "fs" has not been loaded yet for context: _. Use require([])
How can I allow fs to be loaded in my controller js file?