I have an app like this
/app
/views
index.jade
/controllers
controllers1.js
controllers2.js
server.js
Inside server.js I use app.use(express.static(path.join(__dirname, 'app'))); and all requests render index.jade. Inside index.jade I call the controllers with regular <script> tags.
My Problem
I'm uncomfortable with exposing all my scripts to the front-end. e.g.: I don't want people to type www.myurl.com/controllers/controllers1.js and see the script, because I don't want to show all my business logic right away, especially to users who aren't logged in.
Question
Having deactivated express.static(), is it possible through express Middleware to get the contents a certain javascript files and include/send them to index.jade? Ideally I want to control which script files the front-end can receive/see.
There's probably many ways to do this. Should I be using some kind of library for this (maybe Requirejs, idk much about it)?
deactivating express.static is not required
use public folder for all the content which you want to expose to users
like
app
->controllers
public
->js
->->jQuery.js
->->abc.js
->css
->->bootstrap.css
htmls goes here
and use express.static(__dirname,'public') to expose public folder.
One strategy I've used is to separate the public and private node files. The public libraries implement dual purpose node/browser code. I use a folder structure that looks something like this:
/app
/lib
/public
public_library.js
private_library.js
Then it's simple to expose the public directory so that you can do both:
var mylib = require('public/public_library.js');
in your node files and
<script src="lib/public/public_library.js"></script>
in your browser facing code.
Put all libraries you want to expose in the public directory. Put all libraries you want to keep private outside of the public directory.
Related
I'm starting out with express.js and trying to serve lots of static files from the server (could be .css, .jpg, .svg, .js or other file types). Is there a way to do this without typing app.get() for each file? I know about express.Router() but then the clutter just goes over into another file.
You might want to use express.static middleware.
For example, use the following code to serve all the files from directory named public:
app.use(express.static('public'))
Now, you can load the files that are in the public directory:
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
More info here: https://expressjs.com/en/starter/static-files.html
Here's the file structure i am using
-----+root
----------+app
--------------+common
--------------+config
--------------+controllers
--------------------------+rootPage.js
----------+public
--------------+rootPage.jade
----------+server.js
Here's my jade file
doctype
html(lang = 'en')
head
title PlanUrNight
meta(charset = 'utf-8')
link(rel = 'stylesheet' href = '//maxcdn.bootstrapcdn.com/bootswatch/3.3.0/flatly/bootstrap.min.css')
link(src='//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js' rel = 'stylesheet')
link(rel = 'stylesheet' href = './css/rootPage.css')
body
nav.navbar.navbar-inverse(role= 'navigation')
.navbar-header
button.navbar-toggle.collapsed( type='button', data-toggle='collapse', data-target='#navbar-inverse', aria-expanded='false', aria-controls='navbar')
span.sr-only Toggle navigation
span.icon-bar
span.icon-bar
span.icon-bar
a.navbar-brand(href='#') PlanUrNight
.collapse.navbar-collapse#navbar-inverse
ul.nav.navbar-nav
li: a( href="#") Home
.collapse.navbar-collapse.navbar-right
.facebook-login-wrapper
a.btn.btn-primary(href='/auth/facebook') Facebook
span.fa.fa-facebook
.container-fluid
.row
.col-md-8.col-md-offset-2.main-container
.images-container
img.drink(src='img/drinking.png')
img.dance(src='img/couple_dancing.png')
img.club(src='img/club_ball.png')
.row
.col-md-2.col-md-offset-6.search-container
span.glyphicon.glyphicon-search
.input-group
input.form-control(type='text', placeholder='Search')
script( src='//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js' type='text/javascript')
script( src='./controllers/rootPage.js' type='text/javascript')
I have tried multiple variations of the source, but it just doesn't seem to be loading the JavaScript file. Each time I get an error log in my console, saying Error 404: rootPage.js not found
I am using express with node, and in my server.js file I have the following line for serving static files
app.use(express.static(__dirname+'/public'));
So what am I doing wrong here? Does the usage of the app.use line above change the root of my directory in some way so that I need to change the file path to access my JS files?
Or is there a different way to load JS files in Jade?
Your file organization is a bit wonky. Based on the one middleware you showed us, all files in the /public folder will be served as-is, but no static files elsewhere will be.
Generally, jade files that you're rendering with server logic are in a /views folder which is not served directly, but instead available to server side route handlers or controller logic to call res.render with.
So if you have clientside JS files you want to serve as static content you need them either under the /public folder or create more static middleware calls to point to whatever folder they are in.
/** Edit after first two comments **/
Sorry for not providing more examples, etc before, I was on my phone.
Wonky is perhaps a harsh term and I'm sorry. What I meant was it doesn't really match the standard layouts I've seen. There's a few ways to do it, but most small(ish) Express projects at least start out with the template generated by the express command line tool.
In that case, all the stuff in your ./root/app directory would be server-side code that doesn't get directly served to the client ever. Most of the sites I've seen (exception being the default template from the MEAN.js project) follow a pattern something like this:
app
- errors
- models
- controllers
- routes
- views
public
- css
- js
- img
package.json
server.js
Sometimes there's a lib folder that's a peer of app where you put utility stuff. 'views' is where all the jade templates live.
Everything in the public folder is exposed via a single middleware like you did:
app.use(express.static(__dirname+'/public'));
Everything else will not get served as static files. If you have a clientside JS structure that uses an MVC pattern, you'd then have model, view, and controller folders under ./public/js
The MEAN.js folks take a different approach, making each logical component of the app (e.g. user management, etc) into a module and then organizing each module as folders that look like ./<module name>/server and ./<module name>/client with structure for models, controllers, etc, under each of those depending on if it's server code or client code.
You're correct on how to add more more static middleware.
Try
script( src='./app/controllers/rootPage.js' type='text/javascript')
I have a simple node.js + express server.
var express = require('express'),
app = express();
app.use(express.static(__dirname + '/public'));
app.listen(8080);
That code is in a file called web on my linux home directory. All my files like photos or my index.html is in the public file. It looks like this:
[web]
↓
[public] , server.js , creatdb.js
↓
index.html, jquery.js, index.js, photo.jpeg, mydb.db
I'm wondering if this is the "correct" way to organize my files or if I should structure it differently.
I want to be able to have sql inserted when for example, something is triggered on my index.js.
Your public folder should contain only static content. I don't think you'll ever want to return your database as a response from the browser, so it really shouldn't be there. Place it in another folder (one named database, for example).
As for the pages, it's a convention to place them in a views folder that should be created on the same level as your public folder, but since your html is static, it should be fine the way it is
I'm using restify for node to create a simple API. I want to have a directory /public where people can simply browse to that directory and download the file they browse to.
To accomplish this, I have used in /routes/public.js:
server.get(/\/public\/?.*/, restify.serveStatic({
directory: __dirname + '/../'
}));
as my file structure is like:
index.js
/routes
public.js
/public
files
to
be
served
however, I have noticed a big security issue. By browsing to http://domain.com/public/../index.js the source code can be downloaded! Obviously, I do not want this to happen.
Is this a permissions job or is there something else I should be doing? Thanks
Restify does check to make sure that you're not serving files outside of the specified directory. You're specifying the root directory for static files as __dirname + '/../' which is the root of the application. That means all of the files in your application can be served via static. If you only want files in the ./public/ folder served by restify, you have to use that as the directory.
The problem stems from the confusing (and in my opinion poorly planned) way they handle mapping routes to static files. As you said, the full route is included in the path of the requested file. This leads to awkward situations like this one. You have a public folder, and also want the route to include public. That means you have to have a ./public/public folder for your resources. An alternative approach would be to not include public in your route. You can setup your static handler like this:
server.get(/.*/, restify.serveStatic({
directory: './public/'
}));
Then a request to /somefile.txt would route to `./public/somefile.txt'.
I am trying to learn Derby.js and I am having a lot of trouble. I know I can include packages such as jQuery through npm and add it to the node_modules folder, but this isn't quite what I want to do. I want to be able to include these files like I do in normal HTML.
So I want to do something like <Head:> <script src="js/jquery.js"></script>. This does not work though because it cannot find the js directory. I expect this has something to do with the way node.js runs an app and that the app itself will not hold the js directory.
Any help would be appreciated!
Derby offers the Script: tag:
<Scripts:>
<script type="text/javascript" src="/components/jquery/jquery.js"></script>
The components directory is because of the usage of bower. Put the components directory into the public directory. According to the express FAQ, the static routes search below the given directory (which is public in derby's example application). Configure bower to put the files under public/components (Choose bower install directory).
The public directory is configured at lib/server/index.js: .use(gzippo.staticGzip(publicPath, {maxAge: ONE_YEAR})), where publicPath is configured above to path.join(root, 'public').
Be aware that the "idea behind the inline script is that it runs immediately, before any of the external scripts are loaded. This should only be used in rare cases where the script should run before the page is displayed in the browser, such as sizing something to the window or autofuocusing an element in browsers that don't support the "autofocus" attribute." Nate Smith in the derby google group.
Inline scripts should be placed in inline.js, located in the same directory as the application's index.js.
If you require jQuery to do something on the loaded page, following code snipped worked at my side (Firefox, Chrome) in inline.js:
window.onload = function() {
alert($(this));
}