19
votes

I have an application that uses the node twit module that is available via

npm install twit

I deployed the node module locally from .meteor/local/build/server/

So, it is visible at .meteor/local/build/server/node_modules/twit

I tried installing it at project root but the project did not find the module. Which led me to the above solution which works.

My application now runs fine locally. I am able to run and do everything and can interact with Twitter from my Meteor server side or client side depending on what I want to do. No crashes.

When I deploy to meteor.com through the command

meteor deploy [appname] --password

The application deploys successfully.

When I attempt to access the (app at anonistream.meteor.com)[anonistream.meteor.com] from a browser it fails and the logs contain this error.

[Mon May 07 2012 01:59:53 GMT+0000 (UTC)] WARNING
node.js:201
   throw e; // process.nextTick error, or 'error' event on first tick
         ^
Error: Cannot find module 'twit'
at Function._resolveFilename (module.js:332:11)
at Function._load (module.js:279:25)
at Module.require (module.js:354:17)
at require (module.js:370:17)
at app/server/server.js:2:12
at /meteor/containers/84162a7c-24e8-bf26-6fd8-e4ec13b2a935/bundle/server/server.js:111:21
at Array.forEach (native)
at Function.<anonymous>
 (/meteor/containers/84162a7c-24e8-bf26-6fd8-     e4ec13b2a935/bundle/server/underscore.js:76:11)
at /meteor/containers/84162a7c-24e8-bf26-6fd8-e4ec13b2a935/bundle/server/server.js:97:7
[Mon May 07 2012 01:59:53 GMT+0000 (UTC)] INFO STATUS running -> waiting
[Mon May 07 2012 01:59:53 GMT+0000 (UTC)] ERROR Application crashed with code: 1
[Mon May 07 2012 02:29:55 GMT+0000 (UTC)] INFO HIT / 24.94.158.145
[Mon May 07 2012 02:29:59 GMT+0000 (UTC)] INFO HIT /favicon.ico 24.94.158.145
[Mon May 07 2012 02:30:46 GMT+0000 (UTC)] INFO HIT / 24.94.158.145
[Mon May 07 2012 02:30:50 GMT+0000 (UTC)] INFO HIT /favicon.ico 24.94.158.145

Does anyone have any suggestions on how this might be accomplished?

7
Just checking...but is twit included in your package.json file?rjz
I wasn't aware I had to build a meteor package to include twit in my deploy. I will have to look into that to see if that is the case. I assumed that anything in the node_modules directly was pushed on a deploy. I am going to dig through the source tomorrow to see what I can find! Unless someone else posts the answer that is!Steeve Cannon
Honestly, I'm not sure either...looking forward to hearing what others have to say.rjz
Personally, I have a package.json for all my meteor projects now. However I only deploy to Heroku now (for advanced apps with node dependencies). Here's how: github.com/matb33/heroku-meteor-npmmatb33

7 Answers

14
votes

As of Meteor 6.0, now we need to use Npm.require() instead. Additionally, we need to declare the module as global variables, since Meteor now has file-level scope.

  var path = Npm.require('path');
  var fs = Npm.require('fs');
  var base = path.resolve('.');
  var isBundle = fs.existsSync(base + '/bundle');
  var modulePath = base + (isBundle ? '/bundle/static' : '/public') + '/node_modules';
  MODULE_NAME = Npm.require(modulePath + '/MODULE_NAME'); // NOTE, this is going to be a global variable
8
votes

finally, I wrote like this. it works both in local and meteor sever. thx Ian :D

install npm module inside "app/public":

    app/public# npm install MODULE_NAME

inside app/server/server.js:

Meteor.startup(function () {
    var require = __meteor_bootstrap__.require;
    var path = require('path');
    var base = path.resolve('.');
    var isBundle = path.existsSync(base + '/bundle');
    var modulePath = base + (isBundle ? '/bundle/static' : '/public') + '/node_modules';

    var MODULE_NAME = require(modulePath + '/MODULE_NAME');
});
7
votes

Answer found from JonathanKingston on meteor irc. Referred to meteoric project

Put node modules in the projects public directory.

Use code like this to make sure it loads.

var require = __meteor_bootstrap__.require;
var path = require("path");
var fs = require('fs');
var Twit;
var twitPath = 'node_modules/twit';

var base = path.resolve('.');
if (base == '/'){
  base = path.dirname(global.require.main.filename);   
}

var publicPath = path.resolve(base+'/public/'+twitPath);
var staticPath = path.resolve(base+'/static/'+twitPath);

if (path.existsSync(publicPath)){
  Twit = require(publicPath);
}
else if (path.existsSync(staticPath)){
  Twit = require(staticPath);
}
else{
  console.log('node_modules not found');
}

meteor deploy should work find after that, sill me for putting my node modules in the server dirs

4
votes

Just spent a half hour figuring out the "install npm module inside app/public step and thought I'd save the next person some time. From your app's home directory:

cd public
mkdir node_modules
npm install foo

By default, npm install foo installs "locally," but if there's no node_modules folder in your current directory then it moves up the directory tree looking for one. I was ending up with the package installing in $HOME/node_modules/foo instead of the local project. Fine for localhost, but not so much for deployment.

(Thanks to npm install locally for solving my root problem.)

2
votes

This code worked for me with meteor 0.8.x and node_modules being installed in ./public of my app:

var path = Npm.require('path')
var fs = Npm.require('fs')
var base = path.resolve('.')
var isBundle = fs.existsSync(base + '/bundle')
var modulePath = base + (isBundle ? '/bundle/static' : '/../client/app') + '/node_modules/'

var twit  = Npm.require(modulePath+'rssparser')

It may also be a good idea to create packages.json file within ./public for easier updates/installs through npm.

Long live Meteor!

1
votes

Changed:

var modulePath = base + (isBundle ? '/bundle/static' : '/../client/app') + '/node_modules/'

to:

var modulePath = base + (isBundle ? '/bundle/static' : '/../web.browser/app') + '/node_modules/'
0
votes

You

base = base + "/bundle"

to get this to work.