Bart Louwers
Bart Louwers

Reputation: 952

Connect Node.js and Meteor on same server

I want to create an API that makes a lot of HTTP requests and processes the data of those. I want to present the result using a Meteor app, but Node.js seems better suited for the former. Is it a wise thing to have a Node.js application and a Meteor application running concurrently, or will there be an inevitable performance penalty? If it is OK, what would be the best way to connect them?

Which of these is preferable, if this is at all, or are there other options?

Upvotes: 0

Views: 722

Answers (2)

user5084201
user5084201

Reputation:

Here is an example on how to use node.js and meteor together hopefully this is helpful

You should create a meteor package it will allow you to require npm modules, with Npm.require('name') and it's the meteor way to manage code something similar to npm package. http://docs.meteor.com/#/full/packagejs

here is a simple package:

/package_demo
/package_demo/package.js
/package_demo/server.js

package.js

// Standart package.js file with some of the options
Package.describe({
    name: 'username:packagename',
    summary: 'what this does',
    version: '0.0.1'
});

// if you need any global/core or anything from npmjs.com
// it will make it available for us to use like Npm.require 
// in the package files
Npm.depends({
    'request': '2.62.0'
})

Package.onUse(function (api) {
    // we are going to use mongo so we need to specify it
    api.use('mongo', 'server');

    // adding package files
    api.addFiles('server.js', 'server');

    // exporting the mongo collection to make it available to the meteor app
    api.export('github', 'server');
});

server.js:

// we can require any npm modules we specify at package.js
var request = Npm.require('request')

// meteor code
// new mongo collection not needed if you defined it elsewhere
github = new Mongo.Collection('github');

// we wrap this with startup to run after the meteor server process is finished starting
// this makes sure github collection exists, if you have external collection
// that you connect with DDP or you know is available you don't have to use it.
Meteor.startup(function () {
    console.log('server started');

    // node js code - you can use the full power of node async
    // query github api for "meteor" repo
    request({
        url: 'https://api.github.com/repos/meteor/meteor',
        headers: {
            'User-Agent': 'request'
        }
    },

    // regular node js request callback
    // but we made it compatible with meteor with Meteor.bindEnvironment(callback);
    // it makes sure we have access inside the callback to github mongo collection
    // always wrap callbacks to non-Meteor libraries with Meteor.bindEnvironment 
    // if you need access to meteor functions/objects etc... if we just wanted to
    // console.log the information it can work without Meteor.bindEnvironment()
    Meteor.bindEnvironment(function (error, response, body) {
        if (!error && response.statusCode === 200 || response.statusCode === 304) {
            var data = JSON.parse(body);
            console.log(data.stargazers_count + ' Stars');

            // meteor code
            // insert it to meteor collection
            github.insert({ id: data.id, fullName: data.full_name, stars: data.stargazers_count });
        }
    }));
});

I saw you also wanted to require local npm modules, I think you can probably hack you way and include it with Npm.require(GETPATHSOMEHOW'file.js') but I recommend against that because when you compile your project and go into production it's not reliable way to get the path and might break. So you don't really have to publish the npm module to require it you can also just install it on the machine globally

After you did npm init and created the npm package install globally the npm pacakge from your package root directory npm install . -g you can then verify if it exists globally npm ls -g after that you can include your own module inside meteor package same as above.

Also you might not need to create a node js package at all, You can also add more files to your meteor package api.addFiles(['server.js', 'server2.js'], 'server'); and the code inside can be node js code (no nodejs exports support), if you need to export an object or anything to be available globally on your meteor app you can use api.export();

Because package files are shared code for example:

server2.js

// code between the package files is shared
githubAPI.query();

and adding this to server.js

githubAPI = {
    query: function () {
        request({
            url: 'https://api.github.com/repos/meteor/meteor',
            headers: {
                'User-Agent': 'request'
            }
        }, Meteor.bindEnvironment(function (error, response, body) {
            if (!error && response.statusCode === 200 || response.statusCode === 304) {
                var data = JSON.parse(body);
                console.log(data.stargazers_count + ' Stars');
                github.insert({ id: data.id, fullName: data.full_name, stars: data.stargazers_count });
            }
        }));
    }
};

console output: 2 times logged + inserted to database. So it's like require you just add the files :)

28212 Stars
28212 Stars

Upvotes: 0

corvid
corvid

Reputation: 11207

There is an npm package to talk over DDP via a node application.

But, if you want to process HTTP requests, you can simply use meteor's WebApp package in order to handle the HTTP requests, and will react in a traditional "node-like" way. req is a Node request object, and res is a Node response object. Try something like this:

WebApp.connectHandlers.use('/api/v1/things', function (req, res, next) {
  if (req.method === 'GET') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.write(JSON.stringify(Things.find().fetch()));
    res.end()
  }
  next()
});

Upvotes: 1

Related Questions