Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose all or a portion of the node_modules projects in the public folder under the node_modules folder #330

Closed
Martii opened this issue Aug 26, 2014 · 63 comments · Fixed by #343 or #411
Labels
CODE Some other Code related issue and it should clearly describe what it is affecting in a comment. migration Use this to indicate that it may apply to an existing or announced migration.
Milestone

Comments

@Martii
Copy link
Member

Martii commented Aug 26, 2014

For the static projects that we use and copy in manually that have npm packages... expose at the very least those packages in entirety and at most all of them in entirety. The latter of course is easier.

I'd like a list of PROs vs CONS please. I've given this quite a bit of thought so be ready for responses. As usual since I'm only human I may have missed something... which is why this is team biz.

The primary reasoning behind this is to close #321 by using exact versions and is the only reasonable reason to use exact versions that I have found. Having a third party monitor our need to update is a perk. This would also enable npm to handle those updates and we could just debug/maintain JUST our code and those projects that aren't npm ready. e.g. lighten the load. This is the equivalent to using production as the CDN like we currently are with static copies but no need to copy related package bits. We can revisit alternate CDNs if it gets too slow. So far #324 is showing no change in existing speed stability... so this issue is the next progression chain.

Think about some and get back to this issue please. e.g. think deep. Assigning to self for the time being and should be a consideration for #262.

@Martii Martii added this to the #262 milestone Aug 26, 2014
@Martii Martii self-assigned this Aug 26, 2014
Martii pushed a commit to Martii/OpenUserJS.org that referenced this issue Aug 26, 2014
* Link in used npm package into the public directory. This is not the only way to do this but is just a sample.

Applies to OpenUserJS#330
@jerone
Copy link
Contributor

jerone commented Aug 27, 2014

@Martii commented on 27 aug. 2014 00:49 CEST:

For the static projects that we use and copy in manually that have npm packages... expose at the very least those packages in entirety and at most all of them in entirety. The latter of course is easier.

Can you elaborate what you mean with this issue a little more, I don't understand (probably the language difference).

@cletusc
Copy link
Contributor

cletusc commented Aug 27, 2014

I'll look this over later today. I've done something similar at gamerpolls (for moment.js) which is basically just using the express.static middleware:

// GET /javascripts/jquery.js
// GET /style.css
// GET /favicon.ico
app.use(express.static(__dirname + '/public'));

or more specifically, to namespace each module:

// GET /static/javascripts/jquery.js
// GET /static/style.css
// GET /static/favicon.ico
app.use('/static', express.static(__dirname + '/public'));

So you could do something like this to expose a specific module really easy:

app.use('/node_modules/select2', express.static(__dirname + '/node_modules/select2'));

@Martii
Copy link
Member Author

Martii commented Aug 27, 2014

Can you elaborate what you mean with this issue a little more, I don't understand

Look at this line of code and see how the select2 package is available on npmjs.org, and potentially referenced, is resolved here and the whole project is linked in here. Currently we "cherry pick" a few files and place them in our public folder for use in our client side JavaScript that we generate. This has a disadvantage of needing to do this "cherry picking" every dependency update time. select2 isn't the only package. Pretty much all the static copies of these projects are used with client side generation of some stuff we do. select2, for example, is currently used for selecting the "Groups" that a script belongs to with a dropdown list that parses our current group lists.

The advantage is that since it's already on npmjs.org we just link it in instead of having it as part of a build/exec/deploy system and let npm handle the updating of the actual package. Some packages have a dist folder, but not all, which could be a "smaller" link in than the whole project.

Alternatively we could build a dictionary list of what needs to be linked in a json file for mapping from the npm package to our public directory. So when updating dependencies we would need to figure out exactly what is needed to make sure select2 is fully functional.

There are multiple ways to do this for the packages that are on npmjs.org already but we manually copy them currently. Referencing them instead would be an improvement I think since they would already be on there in the first place... e.g. select2 right now is available on nodejitsu, we just don't include it in the package.json... conversely marked is copied in and we already reference it the package.json. The package.json allows us to use it directly in our server side code and the file copying is for the client side code.


Does this help more?

@Martii
Copy link
Member Author

Martii commented Aug 27, 2014

So you could do something like this to expose a specific module really easy:

app.use('/node_modules/select2', express.static(__dirname + '/node_modules/select2'));

Thanks for posting one of the options available for linking the whole dependency project in at once using the available express routines. :) There's usually quite a few ways to do this.

@jerone
Copy link
Contributor

jerone commented Aug 27, 2014

@Martii commented on 27 aug. 2014 20:16 CEST:

Does this help more?

Thnx. Seems like something that makes us life a little easier.


@cletusc commented on 27 aug. 2014 20:16 CEST:

So you could do something like this to expose a specific module really easy:

app.use('/node_modules/select2', express.static(__dirname + '/node_modules/select2'));

I've done something similar: https://github.com/jerone/CrystalMinesHTML5/blob/master/server.js#L24-26

@Zren
Copy link
Contributor

Zren commented Aug 27, 2014

There's also res.sendfile if you only want to expose a single file.

(Untested)

var staticfile = function(filepath) {
    return function(req, res, next) {
        res.sendfile(filepath);
    });
};

app_route(staticfile('/js/select2.js').get(staticfile('./node_modules/select2/select2.js'));

But we'd probably need to use the express.static technique for the ace editor.

@Martii
Copy link
Member Author

Martii commented Aug 27, 2014

I really like the static type referenced and extended from express that everyone has exampled. We can possibly abstract that... but... even in the other referenced projects of @cletusc and @jerone have no method presented to actually resolves the real path of node_modules which can vary from system to system, including any server.

If everyone takes a look at their output with:

console.log(module);

Mine looks a little like this currently:

{ id: '.',
  exports: {},
  parent: null,
  filename: '/home/user/repo/git/oujs/martii/OpenUserJS.org/app.js',
  loaded: false,
  children: [],
  paths: 
   [ '/home/user/repo/git/oujs/martii/OpenUserJS.org/node_modules',
     '/home/user/repo/git/oujs/martii/node_modules',
     '/home/user/repo/git/oujs/node_modules',
     '/home/user/repo/git/node_modules',
     '/home/user/repo/node_modules',
     '/home/user/node_modules',
     '/home/node_modules',
     '/node_modules' ] }

you might see multiple paths... e.g. Is it a guarantee that all development and all production environments will always have a globally installed package symbolic linked into any project folder such as ours with $ npm install creating the node_modules at our project home (usually)?

Secondly __dirname is the folder path for the current JavaScript module we are in... so there might need to be a project home reference if we only assign (link in with whatever) these when they are needed... and is also related to the prior question. Which leads to this question... Since app_route is an emulation routine of express 4x can this be made to be globally available and executed locally in any module?... e.g. not just app.js.

We can probably "mash up" all these methodologies to get the right values so on a deploy to any server, locally or remotely, it doesn't bomb.

@cletusc
Copy link
Contributor

cletusc commented Aug 28, 2014

have no method presented to actually resolves the real path of node_modules which can vary from system to system, including any server

When we specify a package in the package.json and run npm install, it will always install in to root/node_modules where root is the same directory as the package.json, so relative paths relating to what you see as root/node_modules will work just fine regardless of server.

The paths array that you see is where npm looks for a require file, in order from most specific to least specific. If we specify something in our package.json, say Express, it will always be found in (using your path as an example) /home/user/repo/git/oujs/martii/OpenUserJS.org/node_modules/express and the code will work.

Node doesn't do any special linking of files or folders.

can this be made to be globally available and executed locally in any module

Anything can be made global for all files, though we should avoid it if at all possible (for the same reasons as browser globals), as it is a nightmare for maintenance.

// globals.js
global.foo = function () { return 'bar'; };

// someotherfile.js
// Must be done only once somewhere in the chain before anything is called.
require('./globals');

foo();
// 'bar'

IMO, we should explicitly expose all modules in a single location for maintainability:

Q: A script I linked on the browser isn't working, what do I do!?
A: Go to somefile and add it to the list of modules to expose.

...as well as be as specific as possible, e.g. down to the folder containing the file (dist or other), rather than exposing the whole (or all) modules.

@Martii
Copy link
Member Author

Martii commented Aug 28, 2014

IMO, we should explicitly expose all modules in a single location for maintainability:

If you mean in the app.js that would allow anyone to use us as a CDN so the answer is a resounding -1 for that... link on demand is a safer option and we can global static link anything that we want to expose all the time and/or limited areas... like script pages could have access to Ace, etc. Going to need to ponder on this a bit more now that I think about it from this aspect but I need mega sleep first.

@cletusc
Copy link
Contributor

cletusc commented Aug 28, 2014

If you mean in the app.js that would allow anyone to use us as a CDN so the answer is a resounding -1 for that...

Although I agree that this could potentially allow others to use our files on their own servers, I think that is a separate issue as all of our public files can be used remotely. Protecting public files from third party use shouldn't be the concern for this issue.

I don't see why a module can't be served everywhere, then only actually link (via script tag) when needed. If it becomes an issue later on, we could always change it, but I think for now it would be best to keep the configuration on which module to expose in a single file (and exposed to all pages), rather than peppered among the controllers that need it which could be a maintenance nightmare if a template uses a file that isn't exposed and you have to track down where it is exposed (e.g. script works on this page, but not that page, why not?).

@Martii
Copy link
Member Author

Martii commented Aug 28, 2014

I think that is a separate issue as all of our public files can be used remotely.

You are correct in that all public files can be used remotely even before this issue and even before entry into this project... however the staticfile method Zren mention can easily be referer checked, cache checked and perhaps minified when necessary on the fly and probably your methodology as well. This is part of exposing them dynamically versus staticly and is included in this issue. We're listing PROs and CONs of each methodology. Obviously the Proof of Concept (POC) of sym linking isn't going to work which is why it is a POC not a de facto commit/pr to be merged but it is one time dynamic symbolic link in just to illustrate the issue... so this is one of those CONs.

a maintenance nightmare

As Zrens already done with app.js he has made a routes.js for all internal routes... it would be easy enough to refer back to the project home either in app.js or a separate project.routes.js (or the like) to handle dynamic routing (for content scope). The "nightmare" as you call it is currently ~2 hours to update dependencies with the always there option... I did it in #325. Now that it's been done for the first time the timing will be shorter as well since no one will need to verify everything we did for the entire project.

You're issue at #321 definitely opened up Pandora's box. ;) :)

@Martii
Copy link
Member Author

Martii commented Aug 29, 2014

So thinking "always there" for the moment...

@Zren
You want to use app_route because it is POST and/or other available method ready right? e.g. chainable

The following sample tested and corrected code above of yours works as:

var path = require('path');

var staticfile = function (aFilepath) {
  return function (aReq, aRes, aNext) {
    aRes.sendfile(aFilepath);
  };
};

[
  'select2.js',
  'select2.css',
  'select2.png',
  'select2x2.png',
  'select2-spinner.gif'

].forEach(function (aElement, aIndex, aArray) {
  app_route(path.join('/node_modules/select2', aElement)).get(staticfile(path.join('./node_modules/select2', aElement)));
});

but you say that for the Ace editor we should use the method presented by @cletusc since it's rather large.


@cletusc
Your tested method works with this code:

var path = require('path');

[
  'select2.js',
  'select2.css',
  'select2.png',
  'select2x2.png',
  'select2-spinner.gif'

].forEach(function (aElement, aIndex, aArray) {
  aApp.use(path.join('/node_modules/select2', aElement), express.static(path.join(__dirname, '/node_modules/select2', aElement)));
});

but also works with just the folder of select2 itself. e.g. if we wanted to do any whole package.

I see the Zren method has the advantage of chainability and I see the Cletusc method has the advantage of no intermediate function (yet) but not chainable.

Did I get this visualization/wording for a summary correct?

So what I think it "boils down to" for "always there" is do we really need those chainable or not? Preference anyone?

@Zren
Copy link
Contributor

Zren commented Aug 29, 2014

Didn't realized express.static worked with files. I was only using app_route to be consistent, but if we're going to be using nested code then it doesn't matter.

@Martii
Copy link
Member Author

Martii commented Aug 29, 2014

Remember I'd like to add caching and minifying when necessary (EDIT: and the referer header check too at least for the FQDN). I know how to do this in Apache/PHP and I'm in the process of translating my knowledge base to Node/express. I'd rather not cut us short accidentally before we get started with that.

@Martii
Copy link
Member Author

Martii commented Aug 29, 2014

@Zren
I think I'm more inclined to go with the sendfile approach since it appears we will be able to set the referer header by having access to req. Caching can also be manually done there... unless there is a way to pass the request into app.use. Thoughts anyone?

Minificiation I found a package, that I still have to twiddle more with, that alleges binding the output of .js and .css files.

I believe using sendfile means that Ace will need to be "pruned" a bit of the useless bits on exposing... which isn't too hard since our editor should primarily be for JavaScript and the search functions... however highlighting would be nice for some other common user.js languages so perhaps include those as well. In an early alpha version of oujs - Meta View I only needed a few files to simulate the editor for the metadata instead of all currently 179 references (we definitely don't need to link in the snippets subfolder) ... so it probably would not look too incredibly fugly in our code routes.

@cletusc
Copy link
Contributor

cletusc commented Aug 30, 2014

Caching can also be manually done there... unless there is a way to pass the request into app.use. Thoughts anyone?

express.static just returns a middleware function. You can intercept it with something like this (mind the ducks):

// Accepts exact same params as `express.static`.
function duckPunchedStatic() {
    // Punch that duck in the face.
    var punched = express.static.apply(this, arguments);

    // Return same signature as the duck you punched.
    return function (req, res, next) {
        // Do stuff here with req and res.
        // ...

        // Let the duck do its thing now, no more punching.
        return punched(req, res, next);
    };
};

app.use('/mountpath', duckPunchedStatic('/node_modules/ducks/'));

which serves these headers on a test file of mine:

Accept-Ranges   bytes
Cache-Control   public, max-age=0
Connection  keep-alive
Content-Length  189563
Content-Type    application/javascript
Date    Sat, 30 Aug 2014 01:02:27 GMT
Etag    "189563-1387433617000"
Last-Modified   Thu, 19 Dec 2013 06:13:37 GMT
x-powered-by    Express

and even setting your own headers (and a max age through express.static):

// Accepts exact same params as `express.static`.
function duckPunchedStatic() {
    // Punch that duck in the face.
    var punched = express.static.apply(this, arguments);

    // Return same signature as the duck you punched.
    return function (req, res, next) {
        // Do stuff here with req and res.
        // ...

        // Status of the duck head(er)?
        res.set({
            'X-Duck-Status': 'Officially PUNCHED'
        });

        // Let the duck do its thing now, no more punching.
        return punched(req, res, next);
    };
};

app.use('/mountpath', duckPunchedStatic('/node_modules/ducks/', {
    // Only allow it to be cached for an hour.
    maxAge: 1000 * 60 * 60
}));

which serves these headers (success!):

Accept-Ranges   bytes
Cache-Control   public, max-age=3600
Connection  keep-alive
Content-Length  189563
Content-Type    application/javascript
Date    Sat, 30 Aug 2014 01:09:36 GMT
Etag    "189563-1387433617000"
Last-Modified   Thu, 19 Dec 2013 06:13:37 GMT
X-Duck-Status   Officially PUNCHED
x-powered-by    Express

express.static is probably the easiest method, and we can hook into each response using the above method. Thoughts?

@Martii
Copy link
Member Author

Martii commented Sep 2, 2014

Thoughts?

Besides being the most unusual nomenclature I have seen in a while (ducks and punches) that methodology appears to work so far:

EDIT:

function serve() {
  var fn = express.static.apply(this, arguments);

  var maxAge = 1000 * 60 * 60; // Default
  var minify = false;          // Default

  if (arguments && arguments[1]) {
    maxAge = arguments[1].maxAge ? arguments[1].maxAge : maxAge;
    minify = arguments[1].minify ? arguments[1].minify : minify;
  }

  return function (aReq, aRes, aNext) {
    if (process.env.NODE_ENV === 'production') {
      if (!/^https:\/\/openuserjs\.org\//.test(aReq.headers.referer)) {
        return aNext();
      }
    }

    aRes.set({
      'Cache-Control': 'public, max-age=' + maxAge
    });

    return fn(aReq, aRes, aNext);
  };
};
[
  'select2.js',
  'select2.css',
  'select2.png',
  'select2x2.png',
  'select2-spinner.gif'

].forEach(function (aElement, aIndex, aArray) {
  aApp.use(
    path.join('/redist/npm/select2', aElement),
    serve(path.join(__dirname, '/node_modules/select2', aElement), { maxAge: 5000 })
  );
});

Remembering that I'm more PHP aware than express a few questions come to mind:

  1. Do we want this intermediate function inline with the routes.js or in /libs perhaps and under what naming schema?
  2. Any mistakes present with redirection of next() or in this STYLEGUIDEd example aNext()?
  3. Are user.js scripts going to be able to send the referer header correctly for the FQDN check... I haven't had a chance to reverify if that is working in and out of the Sandbox.
  4. Will we have to read the file in and send that if we minify or is that in either the req or res object floating in huge object bliss?
  5. Do we want to max-age through proxies?
  6. Revalidation required?

I still have to test this with static served Ace but it is what I have at the moment for select2.... EDIT: please keep in mind this is just a test.

@Martii
Copy link
Member Author

Martii commented Sep 3, 2014

Some miscellaneous notes "out loud":

Syntax wise I'm having to return undefined or null to the express.static second parameter with minification and that doesn't seem like the "right" thing to do but doesn't bomb. This intermediate function is getting a little large too so it may need to be required in. (probable answer to list item 1)

Testing these packages for minification at the moment:

Besides res.write does anyone know an express method to output what processed text we want to output to the client? (Partial answer to list item 4 but looking for alternatives... yes with certain minifiers and sending using res.write at the moment)

app_route may be more syntactically wise to use but then we lose whole package predefined capability... conundrum... pondering some more.

Piler is nice but it requires us to use drone memory just to load any package into server side memory... that is trying to be avoided.

@cletusc
Copy link
Contributor

cletusc commented Sep 3, 2014

I'm working on a separate response shortly. In short, minification shouldn't be part of this middleware. Serving files and minifying should be two separate middleware operations.

@cletusc
Copy link
Contributor

cletusc commented Sep 3, 2014

I hope most of this makes sense--my headset broke so I became a bit preoccupied while writing this. :(

I've marked up your code with some comments (// CletusC [point#]:):

function serve() {
  var fn = express.static.apply(this, arguments);

  var maxAge = 1000 * 60 * 60; // Default
  var minify = false;          // Default

  // CletusC [1]: This needs to happen before `express.static.apply`.
  if (arguments && arguments[1]) {
    maxAge = arguments[1].maxAge ? arguments[1].maxAge : maxAge;
    minify = arguments[1].minify ? arguments[1].minify : minify;
  }

  return function (aReq, aRes, aNext) {
    // CletusC [2]: Be careful with this, it will run on all paths unless filtered further with a mount path.
    if (process.env.NODE_ENV === 'production') {
      if (!/^https:\/\/openuserjs\.org\//.test(aReq.headers.referer)) {
        return aNext();
      }
    }

    // CletusC [3]: Not needed, `express.static` handles this with the `maxAge` arg.
    aRes.set({
      'Cache-Control': 'public, max-age=' + maxAge
    });

    return fn(aReq, aRes, aNext);
  };
};

[
  'select2.js',
  'select2.css',
  'select2.png',
  'select2x2.png',
  'select2-spinner.gif'
// CletusC [4]: aIndex and aArray are not needed unless we actually use them.
].forEach(function (aElement, aIndex, aArray) {
  aApp.use(
    // CletusC [5]: IMO should be marked as /node_modules/select2/--keep it the same as whatever the actual folder is.
    path.join('/redist/npm/select2', aElement),
    serve(path.join(__dirname, '/node_modules/select2', aElement), { maxAge: 5000 })
  );
});
  • [1]: The maxAge and minify stuff should be done beforehand, not after. Also be careful of passing values in to that argument, they may collide with an express.static handled argument.
  • [2]: Runs on all paths. Unless you mount to a specific path, this could cause issues.
  • [3]: express.static is based on serve-static, which handles maxAge (see the headers on the test code I posted earlier).
  • [4]: We shouldn't specify an argument unless it is actually needed, IMO. That can safely be ].forEach(function (aElement) {. Consider this an offtopic point that may be best discussed elsewhere.
  • [5]: We should probably keep the paths exactly as they are, e.g. mounted path node_modules/select2/somefile.js can be found at node_modules/select2/somefile.js. Wouldn't it be easier to track where a file may be if we kept the mount path the same?

Now, I would recommend we separate as much logic as possible from what should just be serving files. Here is a tested (although not super thorough) solution that would serve up a particular module's folder.

function serveModule(aApp, aExpress, aModuleName, aOptions) {
  var path = require('path');
  var modulePath = null;
  var separator = path.sep + path.sep;
  var rBaseModulePath = new RegExp('(node_modules' + separator + '[^' + separator + ']+?' + separator + ').*$');

  // Check required args.
  if (!(aApp && aApp.use) || !(aExpress && aExpress.static) || !aModuleName) {
    throw new Error('invalid arguments');
  }
  // Make sure options is an object.
  if (typeof aOptions !== 'object') {
    aOptions = {};
  }
  // Make sure files has at least one element.
  if (!Array.isArray(aOptions.files) || aOptions.files.length < 1) {
    aOptions.files = [''];
  }

  // Get module path.
  modulePath = require.resolve(aModuleName);
  // Get base folder path.
  modulePath = modulePath.replace(rBaseModulePath, '$1');

  // Loop through each file.
  aOptions.files.forEach(function (aFile) {
    var fullPath = null;
    var mountPath = null;
    if (typeof aFile !== 'string') {
      return;
    }
    // Get paths.
    fullPath = path.join(modulePath, aFile);
    mountPath = '/node_modules/' + aModuleName + '/' + aFile;
    // Serve the files.
    aApp.use(mountPath, aExpress.static(fullPath, aOptions.staticOptions || {}));
  });
}

// Usage.
serveModule(app, express, 'select2', {
  files: [
    'select2.js', // node_modules/select2/select2.js is accessible.
    'select2.css',
    'select2.png',
    'select2x2.png',
    'select2-spinner.gif'
  ],
  staticOptions: {
    maxAge: 1000 * 60 * 60 // 1 hour
  }
});

serveModule(app, express, 'select2'); // node_modules/select2/ is accessible.

As for minification of files and checking referers, we should handle it separately like this (not tested, just for concept):

// Handle minification during production.
var minify = require('express-minify');
if (process.env.NODE_ENV === 'production') {
  app.use(minify());
}

// Check referer.
app.use(function (aReq, aRes, aNext) {
  // ...
});

// Handle the served modules.
serveModule(...);

// Handle all the express.static stuff.
app.use(express.static(...));

// Handle any other app.* stuff.
// ...

Logic is thus separated and more maintainable. Need something to do with minifying? Go to the minifying middleware. Need to serve something? Use one of the serving middlewares. Need to allow a referer, or whitelist a particular file? Go to the referer middleware.

@Martii
Copy link
Member Author

Martii commented Sep 3, 2014

This will take me some time to digest in full but I noticed that you are doing way more error checking than what I've posted... that is a later thing.

  1. Can do however I'm not passing only referencing the current argument list to local variables. (did wonder why you initially chose arguments instead of full parms)
  2. mmm yah... will need a little more detail on this one. My console logs only indicated it ran the specified number of times and of course whenver the site url was referenced.
  3. Thanks for the link. It's always nice to know just how bad the actual express documentation really is. ;)
  4. Needs to be present at all times. This is part of the problem with our controllers not specifying aRes and aNext constantly... and I know that they aren't used but it's not good practice with coding when parms are omitted... part of bad documentation as well... think .static and your referenced maxAge. ;)
  5. I spent all weekend debating this and some with colleagues. It is less/easier/human readable typing, more adaptable to other package managers and definitely not dependent upon a change down the line with npm (e.g. don't have to hunt in the mvc's to change lots of lines)... so this is the preferred path that should be done publicly. We know npm creates node_modules and the "concept" behind this is redistributing, preferably to our pages only, and the newer current trend out there for "library" type modules is to use "dist"... so this is along the parallel lines as everybody else.

express-minify isn't going to cut it... not enough options... we need to be able to control it down to the exact minification for applicable files. Using a car reference here... seems more like an "idiot light" instead of a real gauge.

Need something to do with minifying? Go to the minifying middleware. Need to serve something? Use one of the serving middlewares. Need to allow a referer, or whitelist a particular file? Go to the referer middleware.

So you are basically saying that we should have another abstraction layer on top of the already abstracted middlewares we require then... right? The problem there is minifying and caching... both of those have to be done before the file is served client side... so somewhere in app.use(...express.static... all of the abstractions have to be called at will.

Anyhow thanks for the reply and I'll look it over in massive detail in the next day or so.

@Martii
Copy link
Member Author

Martii commented Sep 3, 2014

btw the:

[
    'select2.js',
    'select2.css',
    'select2.png',
    'select2x2.png',
    'select2-spinner.gif'
  ]

bit is most likely going to need to include single file options for cache time value, whether or not to minify in our current routes.js (some files are already minified in some packages and not others) and optional release of the referer check... how we proceed from there is of course adaptable. This is in line with your absence of "peppering" across the abstractions (controllers, functions, you name it)... but I'll dive into this after my errands tomorrow and see if we can come up with a compromise hopefully in between. :)

Martii pushed a commit to Martii/OpenUserJS.org that referenced this issue Sep 7, 2014
@Martii Martii removed their assignment Sep 7, 2014
@jerone
Copy link
Contributor

jerone commented Nov 6, 2014

I don't want to open another issue, because it is maybe me, but I'm getting 404 with this redist part.

I understand what is happing and how it should work, but every file going through the routesStatic is returning 404.
This is from the developer log on the index:

GET http://localhost:8080/redist/npm/font-awesome/css/font-awesome.min.css 
GET http://localhost:8080/redist/npm/octicons/octicons/octicons.css 
GET http://localhost:8080/redist/npm/jquery/dist/jquery.js 
GET http://localhost:8080/redist/npm/bootstrap/dist/js/bootstrap.js

I have confirmed that the files exists.
The app is running in Windows.
I tried node-inspector, which shows nothing weird when debugging.
After updating the latest code, I did a complete clean up of all modules (deleted the node_modules folder and ran npm install).
Oh and I did change the port on purpose (will send a PR soon to make it consistent again). Still not workiing on 8080.

Anyone ( @Martii ) have any idea... did I miss something?

@Martii
Copy link
Member Author

Martii commented Nov 6, 2014

Anyone ( @Martii ) have any idea... did I miss something?

@jerone

It's most likely the express package update in #373... I get it every great once in a while and a page refresh does the trick. The solution is to walk the version back one version at a time and see where it doesn't show up at all on production (this is a pro test only since dev never has this issue here much like the aws-sdk package was in #395) ...

...however it would be great to understand why we aren't using express 4.x... sizzle already stated that he wants it at express 3.x... but I don't know why.

@jerone
Copy link
Contributor

jerone commented Nov 6, 2014

Updating express 3.18.2 did not solve my issue.
Going back to version 3.16.x did not do the trick either.

Anyone else on Windows having this issue?

@Martii
Copy link
Member Author

Martii commented Nov 6, 2014

You redid a $npm install, with optional (but preferable) deletion of ./node_modules, right?... otherwise you are using the older versions.

@jerone
Copy link
Contributor

jerone commented Nov 6, 2014

@Martii commented on 6 nov. 2014 22:31 CET:

You redid a $npm install, with optional (but preferable) deletion of ./node_modules, right?... otherwise you are using the older versions.

Yes. I confirmed having another version the before.

@jerone
Copy link
Contributor

jerone commented Nov 6, 2014

I also have tried the following without success, to be sure it's not a path on Windows issue:

  aApp.use(express.static(path.join('redist', 'npm', 'dist', 'js', 'bootstrap.js'), path.join('node_modules', 'bootstrap', 'dist', 'js', 'bootstrap.js')));

@Martii
Copy link
Member Author

Martii commented Nov 6, 2014

Hmmm

Well again in Linux dev it works peachy here using:

$ node -v
v0.10.32

$ npm --version
2.1.5

$ rm -Rf node_modules

$ npm install

...
  26 passing (29ms)
...

$ node app.js

and visiting http://localhost:8080/redist/npm/font-awesome/css/font-awesome.min.css and even on pro with http://openuserjs.org/redist/npm/font-awesome/css/font-awesome.min.css.

$ node app.js
connect deprecated methodOverride: use method-override npm module instead app.js:53:17
GitHub client authenticated
GET /redist/npm/font-awesome/css/font-awesome.min.css 200 8561.558 ms - -

Have you cleared your cache recently? e.g. maybe you are getting hung up in the browser?


I do see that npm is up to 2.1.6 now... perhaps time for me to go recompile that.

@Martii Martii self-assigned this Nov 6, 2014
@Martii
Copy link
Member Author

Martii commented Nov 6, 2014

I also have tried the following without success, to be sure it's not a path on Windows issue:

I can add the path.sep in if it is needed... or path.normalize... is it for your platform?

@jerone
Copy link
Contributor

jerone commented Nov 6, 2014

The following code seems to work:

  aApp.use('/redist/npm/bootstrap/dist/js/bootstrap.js', function (req, res, next) {
    var dir = path.join('.', 'node_modules', 'bootstrap', 'dist', 'js', 'bootstrap.js');
    return express.static(dir).apply(this, arguments);
  });

Trying to debug the serveModule function...

@jerone
Copy link
Contributor

jerone commented Nov 6, 2014

Oh finally found the solution; change https://github.com/OpenUserJs/OpenUserJS.org/blob/master/routesStatic.js#L25 to the following:

          aRoot + '/' + aModuleName + '/' + moduleFile,

Can someone confirm that this works for them too...


I haven't found the reason behind it yet...

@jerone jerone mentioned this issue Nov 6, 2014
3 tasks
@Martii
Copy link
Member Author

Martii commented Nov 6, 2014

Reopening since there appears to be an issue on Windows dev.

@Martii Martii reopened this Nov 6, 2014
@Martii Martii removed the team biz This is similar to a meta discussion. label Nov 6, 2014
@jerone
Copy link
Contributor

jerone commented Nov 6, 2014

The first argument of app.use requires an url in this usecase. And urls aren't filesystem paths. The use of path.join is invalid here, as it will convert all forward slashes backwards. It only works because Mac & Unix accept it and Windows is more strict.

Martii pushed a commit to Martii/OpenUserJS.org that referenced this issue Nov 7, 2014
* Fix Windows dev from not serving module/module components
* Use some standard node nomenclature for identifier naming
* Use **native** node [url](http://nodejs.org/api/url.html)
* Reorder `require`s to have natives first then third party packages after
* Stray comma removed

Re - Closes OpenUserJS#330
@Martii Martii removed their assignment Nov 7, 2014
@Martii
Copy link
Member Author

Martii commented Nov 7, 2014

Please remember https://github.com/OpenUserJs/OpenUserJS.org/blob/master/CONTRIBUTING.md#pull-request-process Item 1 subitem 1 ... I'm still actively watching this for discussion (and now I get to restart watching for a boog that intermittently shows up but I suspect it's express) hence the needs discussion label still on here. Obviously if it has been a very lengthy period of time assign yourself but that doesn't mean hours more like at least 4ish days... and reopen of course.

@Martii Martii removed the needs discussion Blah, blah, blah, wahh, wahh, wahh, etc. label Jan 12, 2015
Martii pushed a commit to Martii/OpenUserJS.org that referenced this issue Dec 3, 2015
* Link in hljs css for GitHub styling ... missed from OpenUserJS#330 ... glad to whittle the CSS down a bit more :)
* Remove our dated static copy of GH highlight rules from OpenUserJS#22
* Delete ops retested

See their changelogs for exacts... mostly bug fixes, some doc fixes, some refactoring
@Martii Martii mentioned this issue Dec 3, 2015
@OpenUserJS OpenUserJS locked as resolved and limited conversation to collaborators Apr 12, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
CODE Some other Code related issue and it should clearly describe what it is affecting in a comment. migration Use this to indicate that it may apply to an existing or announced migration.
4 participants