XHRs from an outside js file makes app crash - javascript

I have an api.js file where I make a couple of XHR-equests. I was using it inside a script tag inside an .ejs file, but it was getting too crowded. So after I moved everything to the api.js I'm no longer able to access its data.
Every time I try to require it from my app.js my program crashes.[nodemon] app crashed - waiting for file changes before starting... I've tried putting it inside my public folder and some other places, but it never works.
Should I export the data from api.js like I would if it was a data schema? If so, how would I do that? (something like module.exports = mongoose.model("Data", dataSchema); ? I don't have any models in api.js, it's just a couple of requests)
The .ejs file that is supposed to make use of api.js has a route like this:
app.get('/home', function(req, res){
res.render('home', { moment: moment }); //home is an .ejs file
});
The { moment: moment } is from moment.js.,.if I'm supposed to export api.js, how could I use it in this route since I'm already using moment.js. I think I can't just do
res.render('home', { moment: moment }, {api: api});
The main problem might be the app crashing since without solving this issue I won't be able to solve anything else.
Any help is appreciated. Thanks!

I'm not sure how much of the process you understand, but your ejs file is a "template" --- you pass "variables" to it and "render" it, and then express sends the html file. After it renders it, the "variables" are no longer accessible unless they're passed into a <script> tag like you might be doing. (I'm not sure how you're using moment --- or maybe you only use moment to render something server side)
Instead of trying to pass api, your html file can use the script tag, which can refer to other files like
<script src='/js/api.js'></script>
But your server (through express.js) needs to serve this file.
That is the common option, and should work for you.
You generally don't "pass" a module or library to the template engine unless you need it to render something. But if you wanted to, you can also read the api.js file as a string and "inject" it into the script tag... (I don't usually see it done this way)
<script><%= api %></script>

Related

Make a small HTML application update a JSON file

I want to make a local HTML application read and update a JSON file and use its content to display HTML content. Alas, I'm stuck at the very first step, as I can't seem to setup any sort of test file that simply notices and reads a JSON file. From what I see online, I need to use other libraries. I attempted to use require.js but I can't make it work and the documentation doesn't help me.
I imported the require.js with a tag and attempt to launch something out of what I got from the documentation, but there's nothing to do. It doesn't look like it's willing to take .json files.
requirejs([
'example'
], function(example) {
const config = require('./config.json')
});
My issue is to get the program to read the file. From there I believe I can make the display of it, but this JS thing is all alien to me.
The recommended way would be to run a web server or use something like Electron and build a desktop app (as #chrisG points out in the comments). But if you wanna do this in the browser without an web server you could do something like:
Run Chrome with the --allow-file-access-from-files (or however you allow local file access in your browser of choice)
Put your JSON in a js file and load it (to just do this you don't need the flag, but if you want to use absolute path you'll need it)

Can I send a React component to the client while doing Server Side Rendering?

I have a Reactjs application built on a Node/Express server. I am doing server side rendering via something like:
route.js
var Group = require('./react/component/groups');
var props = {foo: 'bar'};
var groupHtml = React.renderToString(Group(props));
res.render('index.ejs', {
reactOutput: groupHtml,
jsonProps: JSON.stringify(props),
start: 'lessonlist'
});
index.ejs
<div id="react-main-mount"><%- reactOutput %></div>
<script id="props" type="application/json"><%- jsonProps %></script>
<script src="/js/<%= start %>.js"></script>
This works really great! But here is my problem:
One of my pages/components will have a child component. But this child component can be one of 50+ different components.
I assume I could Require every single component, even though only one will be used. This seems like a bad idea since my main.js file will be huge.
I tried sending it via a prop and JSON.stringify. This works on the server rendering to HTML, but this doesn't work on the client side because JSON.stringify can't stringify a react component.
I though I might be able to do an API call and return it, but same problem as above.
Is there any way to dynamically require something, say based off a variable like require('components/' + this.props.foo) after the I've browserified/reactified?
Any suggestions/answers would be greatly appreciated
Browserify had always been too bulky for me, so I did my research and found RequireJS. It allowed me to require other files on the client just like how Node does it.
It was difficult for me to get started with Require, but once I got it working, everything just seemed easier. See this example I wrote in CoffeeScript.
Remember to have below code at the top of every isomorphic component so you don't stumble upon the problem I had with Node not understanding the keyword define.
if typeof define != 'function'
define = require('amdefine')(module)
define (require) ->
Above code is written in coffeescript.
Let me know if more information is needed.
Webpack allows you to do asynchronous bundle loading. This is intended for single page applications, where you don't want to have to include all of your javascript files until the user actually navigates to the "page" where they're needed. This allows you to fetch javascript with ajax dynamically. Check out the section titled 9. Async loading in this wonderful guide to Webpack
The implementation looks something like this...
if (window.location.pathname === '/feed') {
showLoadingState();
require.ensure([], function() { // this syntax is weird but it works
hideLoadingState();
require('./feed').show(); // when this function is called, the module is guaranteed to be synchronously available.
});
} else if (window.location.pathname === '/profile') {
showLoadingState();
require.ensure([], function() {
hideLoadingState();
require('./profile').show();
});
}
If you don't want to use Webpack, you could potentially just fetch the components with ajax as plain text and eval it upon arrival. This is essentially what the browser is doing with script tags under the hood.

meteor: split code into its own file

I started with a meteor project and I noticed that code is growing rapidly.
The stuff that goes inside
if (Meteor.isClient) { .... }
is getting big now. Its all Template.box...., Template.bar...., etc code, so I think it could be placed into its own file. Is this possible ?
Yes, they should be placed in their own files and you should put your isClient code under the client directory and your isServer code under the server directory. The examples each use a single .js file because it makes it easy to read when you are only dealing with a few lines of code. However, that isn't how you should build a large project.
Typically your client code would be broken out by view or url path into files where each is responsible for a single template or a collection of a few related templates. For more ideas see the unofficial-meteor-faq.

Trouble with script src attribute in Geddy application

I am new to Geddy and I am having trouble getting the HTML script tag to pull in external .js files. My file hierarchy looks like this:
Application
Models
Controllers
Views
ExternalJS
file.js
In one of my views, I would like to include file.js, so I have this in it's html file:
<script src='/ExternalJS/file.js'></script>
However, this doesn't actually work at pulling the file in. I suspect it has something to do with Geddy's router. As of now, going to
https://localhost/ExternalJS/file.js
results in a 404 because the router cannot match that route to a controller/action pair.
I would very much like to keep the ExternalJS folder where it is; I will need to add to it in the future. So what do I do to fix this issue? Is it a routing problem, some dumb mistake with src, or something else?
If you really want to keep that folder where it is, and not in the public directory, you'll need to write a few routes and a static file handler for it.
Your route should look something like this (this is off the top of my head, not tested)
router.get('ExternalJS/:file(.:format)').to('Main.externaljs')
Then in your main.js controller you'd need to do something like this:
this.externaljs = function (req, res, params) {
// serve up the file from disk or cache or something
}

Reference to ejs view files does not change after the build, although it combines it inside of production.js - Javascript MVC

In the code we use something like this:
$('#wrapper').html('//app/views/content.ejs', {foo:"bar"});
And when we build the app, this still stays the same, although the content.ejs file is built into production.js.
So my question is, what should we do so that when we build the app, these references point to ejs files inside of production.js?
We are using JMVC 3.2.2
We've also tried using this way:
$('#wrapper').html( $.View('//app/views/content.ejs', {foo:"bar"}) );
Your views are not getting added to production.js; you need to steal each one of them:
steal('//app/views/content.ejs');
JMVC 3.1:
steal.views('//app/views/content.ejs');
Got the answer in JMVC forum: https://forum.javascriptmvc.com/topic/#Topic/32525000000958049
Credit to: Curtis Cummings
Answer:
The paths to the views do not need to change.
When the production.js file is created, your views are included and
get preloaded when the script runs. When you reference:
'//app/views/content.ejs', view first checks if the view file you are
requesting has been preloaded and if it has, will use that instead of
making a request for the .ejs file.

Categories