Why can't I require files which are available due to app.use? - node.js

If a directory has been made available to a node application in the server.js file which sits in the main directory using:
app.use("/scripts",express.static(__dirname + "/scripts"));
and I attempt to use require from a file inside of that directory (/scripts/custom.js) using:
var Testing123 = require('../app/models/article');
Is there a reason this is not possible? and is there a solution to that problem?
Edit: In one of my views (views/tree.ejs) I use:
<script type="text/javascript" src="../scripts/custom.js"></script>
to access my Custom script which sits inside my scripts folder which is made available using express.static, Custom uses a web scraper to scrape articles and present them in circles (in the form of an image, title and link) on views/tree.ejs, I now want custom.js to save each article it creates to a mongodb database but to do so, it needs access to things like my Article Schema hence the problem above.

You cannot because Node.js scripts and browser scripts do not run in the same context. Your app.use call just exposes a /scripts route that serves assets statically on your HTTP Server.
Your scripts/custom.js script seems to be a browser-side script (Because you load it with a script tag inside an ejs view) but you want to use require inside it and this will not work as this is a Node.js function.
Have a look at LearnYouNode which is an excellent Node beginner tutorial so that you will understand how modules work in Node and know a bit more about the separation between server-side and client-side JS.

Related

docker httpd/Apache - adding new node,js modules

I'm new to the web developing stuff and currently watching on udemy a 70h course.
I like to practice new learned stuff in real world applications. Therefore I've setted up an httpd container (https://hub.docker.com/_/httpd) with a bootstrap template in it (https://startbootstrap.com/theme/sb-admin-2)
My question: how do I add new node.js modules to this template? I want to add a module to connect the website to my postgres database.
The volume I made for the httpd container is as follows: /usr/local/apache2/sb/src/:/usr/local/apache2/htdocs/
In this directory I have installed the postgres module via npm and wrote a simple javascript code in index.js. If I call index.js via node index.js from the terminal it works fine. If I try to call it from the website it doesnt work. I know I missed something important to get this module work but I can't figure it out.
Edit
It was a really simple example of using extern modules in node.js shown in udemy. I've tried to use this example in my website.
index.js
var superhero = require('superheroes');
var hero = superhero.random();
function testCall(){
// alert("just a test!");
alert(hero);
}
In index.html I call the "testCall" function as follows
<body id="page-top" onload="testCall()">
This part works well, If I put a simple string as alert, for instance "alert("just a test!");"
I want to build a dashboard to display some values stored in postgres

Sails.js: can't find variable require (react-bootstrap-datetimepicker)

I'm using Sails js and I want to use a nodejs module.
I also use React js.
I want to use react-bootstrap-datetimepicker in my javascript script.
react-bootstrap-datetimepicker
I installed my module with npm install react-bootstrap-datetimepicker
I tried in config/boostrap.js to add this line var DateTimeField = require('react-bootstrap-datetimepicker');, but DateTimeField isn't recognised in my js script.
Uncaught ReferenceError: DateTimeField is not defined
I also tried to add this line directly in my script, but I have this error:
ReferenceError: Can't find variable: require
And also this one in my script: import DateTimeField from "react-bootstrap-datetimepicker";
I have all these errors in the navigator console.
EDIT 1:
I understand what you said, thank you for your answer.
BUT, for example with react-bootstrap, I can use:
var Input = ReactBootstrap.Input;
var ButtonInput = ReactBootstrap.ButtonInput;
There is exactly the same architecture with react-bootstrap-datetimepicker, so I maybe I can do the same?
var DateTimePicker = ... . DateTimePicker
I tried to include like you said, but it doesn't recognise DateTimePicker.
Here is the doc:
Installation :
npm install react-bootstrap-datetimepicker
Then
javascript
var DateTimeField = require('react-bootstrap-datetimepicker');
render: function() {
return <DateTimeField />;
}
See (examples/) for more details.
And in examples/, the line is:
import DateTimeField from "react-bootstrap-datetimepicker";
Ok, first you have to understand the division of server side and client side javascript, even thought you are using the same language, and you can share libraries, bare in mind, that for client side js you need to supply the user browser with the libraries and scripts it needs, so those have to be in the html you serve the user. When you require any module in sails bootstrap or similar, you are loading the script into the server memory, not serving it to the users browser, that means you can use in the server code, but not in client code.
For you use case, you have to download the library code, and put it in your assets/js folder and if you have the script tags in the layout, sails will automatically inject it there for you, but if not or you are using other template engine like jade, just manually add it.
example:
<html>
....
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/<react-version>/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/<react-version>/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/<version>/react-bootstrap.min.js">
<script src='/js/react-bootstrap-datetimepicker.min.js'></script>
// The other js files that depend on datetimepicker go here
</html>
Now just to be clear, require is a node.js function, node.js is not the same as javascript, its a piece of software with its own functions, thats why you are getting an error related to it when trying to use it in the browser, there is no require method there, so you can't use it, at least not directly. You can use browserify to sort of emulate the node workflow, where you have a node_modules folder and use require on those, browserify will bundle (search for the modules and merge them) and give you a javascript file that you can then link in your html code. That is more setup work, and unless you really need it, because you have a lot of files, i think is not worth the effort.. lets say for just one file using require.
So i think you were misguided by that github repo, because it says npm-install. Just ignore it (unless you use browsefify like i said) and download the link i gave you above ( the .min.js).
So to sumarize, you issue have nothing to do with sails, just link the library in the html you provide to the user, like any other client side script.

nwjs reactjs, confused about my context. Document is undefined

In my nwjs application i am using React to build my UI. Currently, React is being loaded via a <script> tag in the main file, index.html. index.html has another <script> tag which loads main.js containing code which defines and renders my React components as well as requiring (require()) a few Node modules such as "fs" and "McFly".
This all seems to be working, however when i try using another node module (react-inlinesvg) i get an error, "document is undefined".
Having looked online for help, i have come to the conclusion that React now believes that it is being run on the server? Which is odd, as before i started using the react-inlinesvg module it was happily rendering components using React.render (clientside rendering).
If you need any more context or information then please ask.
It could be that you are rendering on the server side, or also that you are rendering both sides. In the second case you could simple nest the line that is causing you error with:
if (process.env.BROWSER) {
the line causing the error
}
If the error disappears, it means that you are on the server side also!
I hope this helps...
Basically if you code is universal (or isomorphic, if you want...) with this check you can execute the code only on client side, you want to do this to use a particular style-sheet for example:
if (process.env.BROWSER) {
require("../style/main.scss");
}
Naturally if you want to do stuff server-side you can check
if (!process.env.BROWSER) {
}
if any one face this he can solve it in 2 ways:
Solution 1: if you are using nw.js 15 or above try to enable mix context mode:
in your package.json add this flag:
"chromium-args": "--mixed-context"
Solution 2: expose document to the global object using this hack:
global.document = window.document;

Including remote library with Node.js?

I've noticed that every time I want to use a package in Node I need to "npm install" it locally and then use the require keyword. I wanted to know if there's a way I could include a remote library kind of like that way we can include remote files using client side html when we use a CDN:
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
require() in node core is synchronous, so there is no way to do it natively (since network i/o is async in node). You'd have to write some function to fetch the resource first and then require() it.
You can't actually supply a URL to "require", but you can of course fetch a remote resource from a URL, including a javascript resource. And then load it locally.
The following answer even links to a "remote_require" that someone wrote to do another kludgy version of this.
how to require from URL in Node.js
If you are trying to use other JavaScript files in your application, you will need to export all of the functions defined by those JavaScript files.
You would export a function like so:
exports.nameOfExport = function(x, y, z) {
// Function content
};
You would then require this file in the file you are trying to use it in with this line:
var myFileName = require('./routes/folder1/myFileName'); // Relative path to required file
If this doesn't answer your question, I suggest going to https://www.npmjs.org/ to search for a package that does what you are trying to do.

Working with Node.JS

Last night I dump windows 7 and formatted my hard driver to port to a Linux based operating system, Purely for the reasons that I wanted to start working with Node.JS
So I have installed Node.JS and have done a few test stuff, the http server and sockets etc.
What I would like to do is build a HTTP Server that is tightly intergrated with an MVC Framework, but before I get started on all that I need to learn how to build efficiently in Node.
For example within PHP as my framework I would create a bootloading system to load all base classes etc, then i would fire my events system ready to start attaching callbacks.
I would continue to process the request etc until the output is generated which then gets sent of to an output handler that would process headers etc etc
But Node s a totally new environment for this and im wondering on the best practises to build an system in Node.
The information im looking for is more to do with the design structure rather then the actual coding of the application, how to load the lib where to load the libs, etc etc
Any help is appreciated.
So far my WebApplication is coming along nicely, I have built my application pretty traditionally and a little procedural.
What i have started out is creating a directory structure like so:
<root>
startup.js
/public/
favicon.ico
/images/
/stylesheets/
/javascripts/
/system/
init.js
config.js
/libs/
/exceptions/
http.js
server.js
/application/
/views/
/_override/
/errors/
generic.view
/partials/
sidebar.voew
index.view
/controllers/
index.js
/models/
users.js
This directory structure is like most MVC Based Web Applications out there so using this method I feel comfortable.
The startup file is whats executed by node as the entry point, node startup & and looks like so:
/*
* Header of t he file, Copyright etc
*/
var _Intitialize = require("./system/init.js");
//Displays the command line header, title, copyright etc
_Intitialize.DisplayCommandLineHeader();
//Check the enviroment, Permissions, Ports etc
_Intitialize.CheckEnviroment();
//Start the server and listen the port.
_Initialize.StartServer();
the init file is the main work, its what tells all other areas of the system to run, stop etc.
I have a file in libs called serverhandler.js, and this is required into init.js, I then create a server and assign the callback to the ServerHandler.Listener. Who then listens for requests, checks to see if the file exists in public directory, if so it then reads in chunks and sends back.
if no file was found in public it would then create a route with Route.Create("/path?params"); which deters 3 elements, Controller, Method, Params from the uri, and then the controller files are loaded if exists.
I've taken on the approach of throwing error pages like so:
if(!FileSystem.exists(RequiredPath))
{
throw new HTTPExceptions.FileNotFound();
}
Hope this helps some people getting started in Node.
Have a look at
http://dailyjs.com/2010/11/01/node-tutorial/ , it's pretty relevant.
I would suggest looking at the current modules too
https://github.com/joyent/node/wiki/modules
and reading the code of any of the projects in the areas you are interested in, esp. the middleware, routing and module loaders.

Resources