Angular, Ember, Backbone, and React all share these issues.
And Angular 2 solves this with Angular Universal.
How do I use Angular Universal?
First, a quick check. Do you need it?
I took this screenshot from the talk given at Angular U in July 2015 which summarizes three main benefits from Angular Universal.
If you don't care about the initial page load speed, search engine optimization, or social links, then Angular Universal is not worth your time. For example, if you have a corporate application that lives behind a login screen, you may not care about SEO, and your app wouldn't ever show up in your friend's Facebook feed because your friend wouldn't be sharing it there.
However, I have been building social apps, and most of my traffic comes in via Google search results. For me, it's worth bringing in Angular Universal into my project.
So I headed over to Angular Universal page and clicked on the 'Get Started' button which took me to the quick start.
It's a little odd that they still suggest to use typings, since the new, preferred way of declaring types is to use npm's
@types. The Angular 2 Webpack Starter they reference does not use typings.
I already have an Angular 2 app, so I didn't use the Angular 2 Webpack Starter. I had some of the dependencies already, but I did need to install
I already had a
server.ts file that I created on day 10, but just to get something running, I copy + pasted the
server.js they listed on the quick start and tried to fire it up.
Okay, let's try
Okay, so that didn't work... After some Googling I'm not sure that their quick start would ever work.
Let's abort out of the quick start and head over to the GitHub repository. They have a link to the documentation and guide.
That takes me to a guide on installation.
They mention there's an Angular Universal Starter, but after cloning it and looking through it, there's a lot going on. Just opening up the package.json is overwhelming with the number of prebuild / build / clean steps, each with a bunch of different options.
It's also worth pointing out the
@types listed in the dev dependencies, which means they're not using typings so I am not sure why the official quickstart still has them listed.
Okay, to recap, the quickstart is outdated and doesn't work, and the universal starter is incredibly overwhelming. It assumes a lot about the architecture and it would take me a lot of work to fold my current project into the starter project.
So I'll try to use the starter project as a reference, and follow along with the NodeJS & Express Integration steps.
Node.js and Express
I already have an Angular 2 app, so the first step for me is to copy the
tsconfig.json files from the starter app into my app root directory.
I had no issues just replacing my
tsconfig.json file with the new one, but I already spent a lot of time setting up my webpack configuration.
Back on day 3 I spent time initially setting Webpack up, then splitting out dev and prod settings on day 4. I further modified my Webpack settings on day 5 to proxy requests to
api/ to my backend in my development environment. So I can't exactly just copy and replace the
webpack.config settings from the Angular Universal project into my own.
But looking at the
webpack.config.js from Angular Universal is... a bit overwhelming. I'm not a Webpack expert so it's not very clear to me what's relevant for Angular Universal and what is just relevant to how the starter project is architectured.
Then to add more confusion to the mix, there's a separate
webpack.prod.config.ts to understand.
Okay, maybe for now I should tuck all of my webpack settings (from days 3, 4 and 5) away for a moment and copy over
webpack.config.js from Angular Universal to try and get something working.
However, the Webpack starter assumes all code is located in
src/, but my project is not structured that way. So I need to modify the lines in the
webpack.config.js so it references my client code located at
client/ and server code located at
Next it says
Copy the scripts, dependencies and devDependencies from the Universal Starter package.json into your local package.json file
Oh no, this is what I was trying to avoid.
I can't possibly need all of these scripts right now. I'll copy over just a few of them:
"watch": "webpack --watch", "watch:dev": "npm run server & npm run watch", "clean:dist": "rimraf dist", "prebuild": "npm run clean:dist", "build": "webpack --progress", "prestart": "npm run build", "server": "nodemon dist/server/index.js", "start": "npm run server",
This should be enough to get Angular Universal working in a dev environment. I already have a
start and a
build script, so I'll comment mine out for now.
Wait, just kidding, you can't add
// to JSON like that. I'll need to rename them.
I have many of the dependencies and devDependencies already, but I'll add the ones that I'm missing.
I modified my
server.ts to reference my existing
AppModule and brought over the code listed on the documentation.
Because I am using Angular 2.2 (or if I was on 2.1), I need a special workaround, as described somewhere deep in the Angular Universal issues/pulls. You'll notice the same thing in the server.ts from the Angular Universal starter project.
Here's what I have so far:
I am not sure why I'm getting red squiggles for the modules, as they're listed in the
Anyways, the next step is to create my top level NgModule on the server side like this:
Err, wait, I don't know what they're trying to say. But I did add the
UniversalModule to my
app.module.ts and also my
Okay, all done following the steps in the documentation. What's next?
Fire it up
So it's not super clear in the documentation, but I think I need to run
npm start and
npm run watch to get the development environment started.
Let's begin with
So that's just peachy. Googling around wasn't very fruitful, but I started to gather it was a Webpack issue, as it seems Webpack can't understand the
I took a look at my
package.json and realized I am using webpack
1.13.2 whereas the Angular Universal Starter is using webpack
This is probably the cause of the error, but I'll need to investigate and troubleshoot on day 12 because I'm out of time today.