Angular 5 app with server rendering with Angular Universal on App Engine

I am newbie to node.js & angular and I have simple Angular app build Angular 5 with some simple routes.

I also want to support server side rendering in my app with Angular Universal and host my app on Google Cloud App Engine.

I tried to upload a starter kit of angular universal on App Engine it fails. (https://github.com/gdi2290/angular-starter).I have deployed it using docker. Although deploy is successful but it gives 502 Bad Gateway error for nginx. I have tried clearing cache and all other suggestion avaliable on net. But still same result.

I have also tried example from Google: https://codelabs.developers.google.com/codelabs/cloud-cardboard-viewer/index.html?index=..%2F..%2Findex worked but it is basic.

Please help me create a App Engine deploy-able version of code https://github.com/gdi2290/angular-starter.


Before I go into any detail, let me give you the Github link of my Angular Universal seed project with Dockerfile and Sass. I use it as a starting point for my projects. Since I am a fan of Vagrant, you will find the Vagranfile in the repository and use it to create the exact same environment for development as well as testing the Docker container. The Readme file provides all the details as to how to work with the project.

Here is the link.

Angular Universal Project Creation

The Angular Universal setup steps are detailed here in the official documentation.

However, I had a few wasted hours to find out the following point

  • Webpack 3 is not compatible with ts-loader versions higher than 3.5.0. At the time of developing this, the latest version of Angular CLI is 1.7.2 which uses Webpack 3.*. Hence, while setting up Angular Universal, install ts-config@3.5.0
  • Dockerfile

    My Dockerfile looks like below. So, as you can see, I am using the docker feature multi stage build to first build the project in a container, copying the distribution to a new container and discarding the old container used for build. This allows Google Cloud build trigger to build the source code and create the Docker image from the distribution.

    FROM node:8.10.0 AS ausbuilder
    RUN useradd --create-home --shell /bin/bash aus; 
        chown -R aus /home/aus
    USER aus
    WORKDIR /home/aus
    COPY aus/ /home/aus
    RUN mkdir /home/aus/.npm; 
        npm config set prefix /home/aus/.npm; 
        npm install --quiet --no-progress -g webpack@3.11.0; 
        npm install --quiet --no-progress -g @angular/cli@1.7.2; 
        npm install --quiet --no-progress;
    ENV PATH=/home/aus/.npm/bin:$PATH
    RUN npm run build; 
        webpack --config webpack.server.config.js --no-progress
    
    FROM keymetrics/pm2:8-alpine
    RUN adduser -h /home/aus -s /bin/bash aus; 
        chown -R aus /home/aus
    USER aus
    WORKDIR /home/aus
    COPY --from=ausbuilder /home/aus/dist /home/aus/dist
    EXPOSE 4000/tcp
    ENTRYPOINT ["pm2-runtime","start","/home/aus/dist/server.js"]
    

    Deployment in Kubernetes in Google Cloud

    We need to first create a build trigger in Google Cloud, so that as soon as we push the code in (let's say) the master branch, the code build and subsequent deployment is triggered. Your code may be hosted in Google Cloud source control, Bitbucket or Github. You need to integrate your source control with the build trigger.While creating the build trigger, you will have option to select either Dockerfile or cloudbuild.yaml , if you chose the first option, your code will be built and subsequently the Docker image will be stored in the Google Container Repository. I go for the second option as it allows me to do more like deployment in Kubernetes.

    Here is how my cloudbuild.yaml looks like.

    A few important points to note here:

  • While cloning the repository I cannot give any external URL. So, what happens here is when you create a build trigger, google creates another repository in the Google domain which basically points to the external source control like Bitbucket in my case. You can find this in the Google Source Control section.
  • Secondly, I am creating a tag latest for the container image so that I can refer it in the Kubernetes deployment descriptor which I named as kubedeployment.yaml . kubedeployment.yaml is referenced in the cloudbuild.yaml as you can see below

  • steps:
    - name: gcr.io/cloud-builders/git
      args: ['clone', 'https://source.developers.google.com/p/aus2018/r/bitbucket-saptarshibasu-aus']
    - name: 'gcr.io/cloud-builders/docker'
      args: ["build", "-t", "gcr.io/aus2018/aus:$REVISION_ID", "."]
    - name: 'gcr.io/cloud-builders/docker'
      args: ["tag", "gcr.io/aus2018/aus:$REVISION_ID", "gcr.io/aus2018/aus:latest"]
    - name: 'gcr.io/cloud-builders/docker'
      args: ["push", "gcr.io/aus2018/aus:$REVISION_ID"]
    - name: 'gcr.io/cloud-builders/docker'
      args: ["push", "gcr.io/aus2018/aus:latest"]
    - name: 'gcr.io/cloud-builders/kubectl'
      args:
      - 'create'
      - '-f'
      - 'kubedeployment.yaml'
      env:
      - 'CLOUDSDK_COMPUTE_ZONE=asia-south1-a'
      - 'CLOUDSDK_CONTAINER_CLUSTER=aus'
    

    Finally, here is how the kubedeployment.yaml looks:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: aus-deploy
    spec:
      replicas: 1
      selector: 
        matchLabels: 
          app: aus
      template:
        metadata:
          labels:
            app: aus
        spec:
          containers:
            - name: aus
              image: gcr.io/aus2018/aus:latest
              ports:
                - containerPort: 4000
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aus-svc
      labels: 
        app: aus
    spec:
      type: NodePort
      selector:
        app: aus
      ports:
      - protocol: TCP
        port: 80
        targetPort: 4000
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: aus-ing
    spec:
      backend:
        serviceName: aus-svc
        servicePort: 80
    

    Once deployment is complete after a few minutes, you'll get the Ingress URL. And then after a few minutes you app starts showing up at the URL.

    You are definitely going to customise this to fit your needs. However, I hope, this would probably give you a starting point.

    链接地址: http://www.djcxy.com/p/31400.html

    上一篇: 通用i18n服务器

    下一篇: 在App Engine上使用Angular Universal进行服务器渲染的Angular 5应用程序