Closed randallb closed 9 years ago
I might have screwed something up. waiting till i'm sure it's good.
Okay... feel free to open another issue if you find that there really is a bug.
By the way, rather than directly specifying the path to the angular
module, you might prefer to use require.resolve
to let node itself tell you where to find the angular module.
I had a really hard time getting this up. We use browserify, and I kept getting "not found" errors that didn't have a stack trace, or tell me what they couldn't find.
What does the "not found" error mean?
Here's an example of using AngularJS-server with browserify: https://gist.github.com/apparentlymart/6679a9d9d4f4cbdefa1f
With that said, I think the "Not Found" error you are seeing is what the built-in htmlGenerator
middleware returns when it can't find a route matching the request URL. That particular middleware is making a bunch of assumptions for quick setup in simple cases. Most notably:
$routeProvider
.static/
prefix.If either of these things are not true for your application, you can build your own "HTML generator" using the lower-level primitives. This is in fact what we do within our main app at Say Media, since that app has its own custom router that does all of the routing work on the server.
The makeHtmlGenerator
function in lib/main.js
shows how the built-in implementation works. As shown in the main readme, you can make your own middleware that has access to the AngularJS context using wrapMiddlewareWithAngular
:
app.use(
angularMiddlewares.wrapMiddlewareWithAngular(
function (req, res, next, injector) {
var $rootScope = injector.get('$rootScope');
var $interpolate = injector.get('$interpolate');
$rootScope.name = 'world';
var greeting = $interpolate('Hello, {{name}}')($rootScope);
res.end(greeting);
}
)
);
That is a very basic example, but you have access to the whole AngularJS API and any additional apps you've loaded from that injector
object, so in principle you can e.g. interact with the ui-router if that's what your app is using. The wrapMiddlewareWithAngular
function, as well as providing that injector
object, also ensures that the $location
service in that context is populated with the relevant data from the req
object, so any router building on $location
should be able to work as (close to) normal.
AngularJS-server is not able to provide a "perfect" browser-like environment to run your application in, so you should expect that some amount of tweaking will be required to make it work, depending on how far your application is from the assumptions of the built-in utility functions. AngularJS-server is a utility to help you port your AngularJS app to the server, not a drop-in solution for server-side rendering.
So I'd recommend making this the default setup. It's much simpler to understand and configure than the "normal" setup. I got this going within 5 minutes.
Maybe once you get that going, layer on routing and stuff gradually in the example.
Also it'd be great if I knew what this was trying to do on the server... specifically what "window-like" stuff is this trying to emulate? Is it building a full jsdom thing?
Also are the "clientscripts" injected via script tag or directly?
Lastly, is it possible to provide raw js for the serverscripts configuration option rather than a file path? Our stuff uses browserify, but uses it as middleware (for now). So I don't have a real file path yet per se. Trying to figure out how best to deal with that.
I'm guessing on my last question it'll just be up to me to do that in the lower level injector thingy. Working on it now.
Yes, you can supply a mixture of raw JS and paths, although I'm not finding that documented anywhere except in this comment in the underlying angularcontext
module:
https://github.com/apparentlymart/node-angularcontext/blob/master/lib/main.js#L29
So i tried to do that but still failed. I even tried angularcontext on its own and that was a fail. I couldn't figure out how to let it know it wasn't a file btu instead was a js string. :/
Sorry, I should have been more explicit... instead of a string, you use an array of [JS string, arbitrary "filename" for debugging]. So your serverScripts might look like:
[
'/some/where.js',
['console.log("foo");', 'myLogCode.js'],
'/else/where.js'
]
In my
serverScripts
i have:serverScripts: [dirname + "/../node-modules/angular/angular.js", dirname + '/permalink-app.js']
Which are the proper paths. I get this error:
I'm trying to use Angular from NPM (1.3.whatever). Is this unsupported for some reason? Does my angular version need to be 1.2?
My next step is to download angular and try to use it directly to see what happens.