angular - dotnet core + Angular Universal + docker => 由于错误 : Error: Cannot find module,预渲染失败

标签 angular docker asp.net-core .net-core angular-universal

我们有一个使用 Dotnet 核心开发的项目,Angular Universal。我们使用 Asp.net Core SPA 服务的预渲染功能。在本地环境中,该应用程序可在 Windows、Linux 上运行。在使用 Visual Studio 自带的 docker 多阶段构建模板时会出现一些问题。在 microsoft/aspnetcore-build 镜像中构建后,我们将文件传输到 microsoft/aspnetcore 镜像。由于 Asp.net SPA 对 nodejs 的依赖,我们也将 nodejs 安装到 microsoft/aspnetcore 镜像中。

但是当我们运行应用程序时,我们在 main.bundle.js 的预渲染阶段收到错误“预渲染失败,因为错误:错误:找不到模块 'angular2-universal-polyfills'” )。我们确信该问题与“angular2-universal-polyfills”无关,因为我们也尝试了其他 polyfill 并遇到了类似的错误。

但是,当我们将 .net core 和 nodejs 安装到单个容器中而不是多阶段构建并在同一个容器中执行构建和发布操作时,我们的应用程序可以正常工作。但是容器大小为 2 GB。

理论上,我们构建的容器和我们运行的容器没有区别。两者都安装了 .net core 和 nodejs。唯一的区别是我们将发布输出复制到我们运行的容器中。

发布输出

root
    wwwroot (angular client-side dist)
        assets
        inline.bundle.js
        main.bundle.js
        polyfill.bundle.js
        vendor.bundle.js
    CodefictionApp/dist-server (angular server-side dist)
        assets
        main.bundle.js
    dlls

工作 Dockerfile

FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80

FROM buildpack-deps:jessie-scm

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libc6 \
        libcurl3 \
        libgcc1 \
        libgssapi-krb5-2 \
        libicu52 \
        liblttng-ust0 \
        libssl1.0.0 \
        libstdc++6 \
        libunwind8 \
        libuuid1 \
        zlib1g \
    && rm -rf /var/lib/apt/lists/*

ENV DOTNET_SDK_VERSION 2.1.200
ENV DOTNET_SDK_DOWNLOAD_URL https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz
ENV DOTNET_SDK_DOWNLOAD_SHA c1b07ce8849619ca505aafd2983bcdd7141536ccae243d4249b0c9665daf107e03a696ad5f1d95560142cd841a0888bbf5f1a8ff77d3bdc3696b5873481f0998

RUN curl -SL $DOTNET_SDK_DOWNLOAD_URL --output dotnet.tar.gz \
    && echo "$DOTNET_SDK_DOWNLOAD_SHA dotnet.tar.gz" | sha512sum -c - \
    && mkdir -p /usr/share/dotnet \
    && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \
    && rm dotnet.tar.gz \
    && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet

ENV DOTNET_RUNNING_IN_CONTAINER=true \
    DOTNET_USE_POLLING_FILE_WATCHER=true \
    NUGET_XMLDOC_MODE=skip

RUN mkdir warmup \
    && cd warmup \
    && dotnet new \
    && cd .. \
    && rm -rf warmup \
    && rm -rf /tmp/NuGetScratch

ENV RestoreUseSkipNonexistentTargets false

ENV NODE_VERSION="8.11.0"

RUN apt-get install wget -y

RUN set -ex \
    && for key in \
      94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
      0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \
      FD3A5288F042B6850C66B31F09FE44734EB7990E \
      71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
      DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
      B9AE9905FFD7803F25714661B63B535A4C206CA9 \
      C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
      77984A986EBC2AA786BC0F66B01FBB92821C587A \
      56730D5401028683275BD23C23EFEFE93C4CFFFE \
    ; do \
      gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
    done

RUN set -ex \
    && wget "https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -O node-v$NODE_VERSION-linux-x64.tar.gz \
    && wget "https://nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt.asc" -O SHASUMS256.txt.asc \
    && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
    && grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt | sha256sum -c - \
        && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 \
        && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc SHASUMS256.txt \
        && ln -s /usr/local/bin/node /usr/local/bin/nodejs \
        && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN npm config set user 0
RUN npm config set unsafe-perm true

RUN npm install -g @angular/cli@1.7.4
RUN node -v && npm -v && ng -v

RUN apt-get update && apt-get install bzip2 -y

ENV ASPNETCORE_URLS http://+:80

WORKDIR /app
EXPOSE 80
COPY . .
RUN dotnet restore ./CodefictionApi
RUN dotnet publish ./CodefictionApi -c Release

WORKDIR /app/CodefictionApi/bin/Release/netcoreapp2.0/publish

ENTRYPOINT ["dotnet", "CodefictionApi.dll"]

多阶段 docker 文件(运行时会出现预渲染错误)

FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80

FROM buildpack-deps:jessie-scm AS publisher

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libc6 \
        libcurl3 \
        libgcc1 \
        libgssapi-krb5-2 \
        libicu52 \
        liblttng-ust0 \
        libssl1.0.0 \
        libstdc++6 \
        libunwind8 \
        libuuid1 \
        zlib1g \
    && rm -rf /var/lib/apt/lists/*

ENV DOTNET_SDK_VERSION 2.1.200
ENV DOTNET_SDK_DOWNLOAD_URL https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz
ENV DOTNET_SDK_DOWNLOAD_SHA c1b07ce8849619ca505aafd2983bcdd7141536ccae243d4249b0c9665daf107e03a696ad5f1d95560142cd841a0888bbf5f1a8ff77d3bdc3696b5873481f0998

RUN curl -SL $DOTNET_SDK_DOWNLOAD_URL --output dotnet.tar.gz \
    && echo "$DOTNET_SDK_DOWNLOAD_SHA dotnet.tar.gz" | sha512sum -c - \
    && mkdir -p /usr/share/dotnet \
    && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \
    && rm dotnet.tar.gz \
    && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet

ENV DOTNET_RUNNING_IN_CONTAINER=true \
    DOTNET_USE_POLLING_FILE_WATCHER=true \
    NUGET_XMLDOC_MODE=skip

RUN mkdir warmup \
    && cd warmup \
    && dotnet new \
    && cd .. \
    && rm -rf warmup \
    && rm -rf /tmp/NuGetScratch

ENV RestoreUseSkipNonexistentTargets false

ENV NODE_VERSION="8.11.0"

RUN apt-get install wget -y

RUN set -ex \
    && for key in \
      94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
      0034A06D9D9B0064CE8ADF6BF1747F4AD2306D93 \
      FD3A5288F042B6850C66B31F09FE44734EB7990E \
      71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
      DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
      B9AE9905FFD7803F25714661B63B535A4C206CA9 \
      C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
      77984A986EBC2AA786BC0F66B01FBB92821C587A \
      56730D5401028683275BD23C23EFEFE93C4CFFFE \
    ; do \
      gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
    done

RUN set -ex \
    && wget "https://nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -O node-v$NODE_VERSION-linux-x64.tar.gz \
    && wget "https://nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt.asc" -O SHASUMS256.txt.asc \
    && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
    && grep " node-v$NODE_VERSION-linux-x64.tar.gz\$" SHASUMS256.txt | sha256sum -c - \
        && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 \
        && rm "node-v$NODE_VERSION-linux-x64.tar.gz" SHASUMS256.txt.asc SHASUMS256.txt \
        && ln -s /usr/local/bin/node /usr/local/bin/nodejs \
        && rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN npm config set user 0
RUN npm config set unsafe-perm true

RUN npm install -g @angular/cli@1.7.4
RUN node -v && npm -v && ng -v

RUN apt-get update && apt-get install bzip2 -y

ENV ASPNETCORE_URLS http://+:80

WORKDIR /app
COPY . .
RUN dotnet restore ./CodefictionApi
RUN dotnet publish ./CodefictionApi -c Release

FROM base AS final
ARG source
EXPOSE 5102
ENV ASPNETCORE_URLS http://*:80
RUN apt-get -qq update && apt-get -qqy --no-install-recommends install wget gnupg \
    git \
    unzip
RUN curl -sL https://deb.nodesource.com/setup_8.x |  bash -
RUN apt-get install -y nodejs
RUN npm config set user 0
RUN npm config set unsafe-perm true
RUN npm install -g npm

RUN npm install -g @angular/cli@1.7.4 --unsafe
RUN npm install -g @angular/compiler-cli@5.2.1
RUN node -v && npm -v && ng -v

ENV ASPNETCORE_ENVIRONMENT=Development

WORKDIR /app/CodefictionApi/bin/Release/netcoreapp2.0/publish
COPY --from=publisher /app/CodefictionApi/bin/Release/netcoreapp2.0/publish .
ENTRYPOINT ["dotnet", "CodefictionApi.dll"]

package.json

{
  "name": "codefiction-app",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/cli": "~1.7.4",
    "@angular/animations": "^5.0.0",
    "@angular/common": "^5.0.0",
    "@angular/compiler": "^5.0.0",
    "@angular/core": "^5.0.0",
    "@angular/forms": "^5.0.0",
    "@angular/http": "^5.0.0",
    "@angular/platform-browser": "^5.0.0",
    "@angular/platform-browser-dynamic": "^5.0.0",
    "@angular/platform-server": "^5.0.0",
    "@angular/router": "^5.2.1",
    "@nguniversal/aspnetcore-engine": "^5.0.0",
    "@nguniversal/common": "^5.0.0",
    "@types/node": "^7.0.12",
    "angular2-router-loader": "^0.3.5",
    "angular2-template-loader": "^0.6.2",
    "angular2-universal-polyfills": "2.0.11",
    "aspnet-prerendering": "3.0.1",
    "awesome-typescript-loader": "^3.0.0",
    "bootstrap": "^3.3.7",
    "bootstrap-sass": "^3.3.7",
    "core-js": "^2.5.1",
    "css": "^2.2.1",
    "css-loader": "^0.28.7",
    "event-source-polyfill": "^0.0.9",
    "file-loader": "^0.11.2",
    "html-loader": "^0.5.1",
    "isomorphic-fetch": "^2.2.1",
    "jquery": "^2.2.1",
    "json-loader": "^0.5.4",
    "moment": "2.18.1",
    "node-sass": "^4.5.2",
    "preboot": "6.0.0-beta.0",
    "raw-loader": "^0.5.1",
    "rimraf": "^2.6.2",
    "rxjs": "^5.5.6",
    "style-loader": "^0.18.2",
    "to-string-loader": "^1.1.5",
    "typescript": "~2.5.0",
    "url-loader": "^0.5.7",
    "zone.js": "^0.8.4"
  },
  "devDependencies": {
    "@angular/compiler-cli": "^5.2.1",
    "@types/chai": "^3.4.34",
    "@types/jasmine": "^2.5.37",
    "chalk": "^2.4.1",
    "chai": "^3.5.0",
    "codelyzer": "4.0.0",
    "jasmine-core": "^2.5.2",
    "karma": "^1.7.1",
    "karma-chai": "^0.1.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-coverage": "^1.1.1",
    "karma-jasmine": "^1.1.0",
    "karma-mocha-reporter": "^2.2.4",
    "karma-phantomjs-launcher": "^1.0.4",
    "karma-remap-coverage": "^0.1.4",
    "karma-sourcemap-loader": "^0.3.7",
    "protractor": "~5.1.2",
    "ts-node": "~4.1.0",
    "tslint": "~5.9.1"
  }
}

csproj 发布命令

  <Target Name="PublishProject" BeforeTargets="ComputeFilesToPublish">
    <Exec Command="npm install" />
    <Exec Command="./node_modules/.bin/ng -v" />
    <Exec Command="./node_modules/.bin/ng build --env=dev --app 0" />
    <Exec Command="./node_modules/.bin/ng build --env=dev --app 1" />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="wwwroot/**; CodefictionApp/dist-server/**" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>

可以从这里查看完整的源代码

https://github.com/Blind-Striker/codefiction-tech-new

可以从此分支检查不工作的版本

https://github.com/Blind-Striker/codefiction-tech-new/tree/docker-not-working-version

谢谢。

最佳答案

angular2-universal-polyfills 模块不再存在。这可能发生在您在本地运行它从本地缓存安装软件包但当您 正在容器中运行它,它在 npm 注册表中查找,但它失败了。 要升级您的项目,您可以按照 link github 上的文档。他们对如何迁移有很好的解释。

关于angular - dotnet core + Angular Universal + docker => 由于错误 : Error: Cannot find module,预渲染失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50257670/

相关文章:

php - NGX-Chart - 从服务获取图表数据时出现问题

angular - 引用错误 : "google is not defined"

angular - Angular,Nginx,Docker在页面刷新时导致404错误

asp.net-core - .NET 核心 Web api 向客户端发送错误请求

reactjs - react + ASP.Net 核心 3 : CORS Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header

c# - 如何读取HttpResponse Body?

angular - 提供 '@ionic-native/AppVersion'或 '.../ngx'调用AppVersion的任何方法时出现异常如何解决?

gitlab 服务器上的 git 存储库位置缺少数据

docker - Kubernetes中 secret 的用途是什么,它的目的是什么?

docker - 在 Ubuntu 16.04 系统启动时创建脉冲音频套接字