【问题标题】:The injectable 'PlatformLocation' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available可注入的 'PlatformLocation' 需要使用 JIT 编译器进行编译,但 '@angular/compiler' 不可用
【发布时间】:2022-01-04 17:22:12
【问题描述】:

我的 Angular 应用程序通过 Node 16.13.0 提供服务。更新到 Angular 13 后,我收到以下错误:

可注入 [class PlatformLocation] 的 JIT 编译失败 file:///Users/btaylor/work/angular-apps/dz-outages-ui/node_modules/@angular/core/fesm2015/core.mjs:4058 抛出新的错误(消息); ^

错误:需要使用 JIT 编译器编译可注入的“PlatformLocation”,但“@angular/compiler”不可用。

injectable 是已部分编译的库的一部分。 但是,Angular 链接器没有处理这个库,因此 JIT 编译被用作后备。

理想情况下,该库使用 Angular 链接器进行处理,以完全 AOT 编译。 或者,应使用“@angular/platform-b​​rowser-dynamic”或“@angular/platform-server”通过引导加载 JIT 编译器, 或手动为编译器提供'import "@angular/compiler";'在引导之前。 在 getCompilerFacade (file:///Users/btaylor/work/angular-apps/dz-outages-ui/node_modules/@angular/core/fesm2015/core.mjs:4058:15) 在 Module.ɵɵngDeclareFactory (file:///Users/btaylor/work/angular-apps/dz-outages-ui/node_modules/@angular/core/fesm2015/core.mjs:32999:22) 在 file:///Users/btaylor/work/angular-apps/dz-outages-ui/node_modules/@angular/common/fesm2015/common.mjs:90:28 在 ModuleJob.run (节点:内部/模块/esm/module_job:185:25) 在异步 Promise.all(索引 0) 在异步 ESMLoader.import (node:internal/modules/esm/loader:281:24) 在异步加载ESM(节点:内部/进程/esm_loader:88:5) at async handleMainPromise (node:internal/modules/run_main:65:12)

我尝试了很多解决方案,例如:Angular JIT compilation failed: '@angular/compiler' not loaded

目前,我的 package.json 中有 "type": "module"

我已将我的安装后命令更新为:ngcc --properties es2020 browser module main --first-only --create-ivy-entry-points

我还将import '@angular/compiler'; 添加到我的main.ts 文件中。

项目将编译,但不会通过 Node 运行。

【问题讨论】:

  • 我有同样的错误。对解决方案非常感兴趣。
  • @RushPL 我也是。我需要找一些时间进行最小限度的复制,以便向 Angular 团队提出错误。我有另一个使用 Universal 和 Angular 13 的应用程序,效果很好。
  • 这个问题一定是由于特定的依赖关系,因为我能够毫无问题地将另一个具有相同架构的 Angular 12 应用程序转换为 13。
  • Angular CLI 应该不会有这个问题,因为它自己配置了 webpack+babel。
  • 这里一样.....

标签: node.js angular typescript


【解决方案1】:

我相信我已经找到了解决方案(假设您使用 jest 作为测试运行器)。在test-setup.ts 文件中,我的项目仍然使用过时的 jest-preset-angular 导入。而不是import 'jest-preset-angular'; 尝试使用import 'jest-preset-angular/setup-jest';

这解决了我的问题。

【讨论】:

  • 我的场景不涉及测试。通过 Node 提供编译代码时出现运行时错误。
  • 它适用于玩笑。我最初没有使用test-setup.ts
  • 有人找到解决方案了吗? ://
  • 为此我必须做出的改变是在我的 jest.config.js 文件中。我在顶部有 require('jest-preset-angular/ngcc-jest-processor'),但将其切换为导出的 globalSetup 属性,如下所示:module.exports = { ..., globalSetup: 'jest-preset-angular/global-setup'`, ... };
【解决方案2】:

如果我理解正确,您也使用 Angular Universal。

我想分享我在将 Angular 从 v8 更新到 v13 后遇到的同样问题的经验。

首先,我想说主要问题是 SSR 的启动文件不正确。在我的项目中,它是server.js,现在是main.js。 所以,也许您的项目也尝试从不具有启动它的必要代码的错误文件开始。

更多细节:

我一步步更新项目,按照Angular团队的建议和https://update.angular.io/?l=3&v=8.2-13.0增加版本

不幸的是,在每一步,我只检查了没有 SSR 的 SPA 的版本,并且只编译了项目以检查一切正常,但没有使用 SSR 启动它。现在我不能说 JIT 编译器的问题是从什么时候开始的。

当我用 SPA 完成更新和修复错误,用 SSR 编译项目并尝试启动它时,我看到了这个问题:

错误:需要使用 JIT 编译器编译可注入的“PlatformLocation”,但“@angular/compiler”不可用。

我尝试了像您这样的不同解决方案,但没有任何帮助。之后,我使用 ng13 创建了一个新的干净项目并添加了 Angular Universal。并将我的项目与 Angular-CLI 生成的新项目进行比较。

我在项目中所做的更改(抱歉,我无法显示项目 - NDA):

  1. angular.json

"projects": {
  "projectName": {
    ...
    "architect": {
      ...
      "server": {
        ...
        "options": {
            "outputPath": "dist/server",
            //"main": "src/main.server.ts", //removed
            "main": "server.ts", //added
            ...
        }
      }
    }
  }
}
  1. package.json

"scripts": {
  ...
  //"serve:production:ssr":   "node dist/server --production" // removed. It was incorrect file server.js which gave the error from this case
  "serve:production:ssr":   "node dist/server/main --production", // added
  ...
  "postinstall": "ngcc --properties es5 browser module main --first-only" // added. In my case, actual version is es5
}

3.server.ts

import 'zone.js/node';

import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';

import { AppServerModule } from './src/main.server';
...
// after all imports I inserted previous code into function run()

...
export function run() {
  // previous code from project with some small changes
}

//and added next code from clean project:

// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
    run();
}

export * from '../src/main.server';
  1. src/main.server.ts

// was only:
export { AppServerModule } from './app/app.server.module';

// replaced by code from clean project:

/***************************************************************************************************
 * Initialize the server environment - for example, adding DOM built-in types to the global scope.
 *
 * NOTE:
 * This import must come before any imports (direct or transitive) that rely on DOM built-ins being
 * available, such as `@angular/elements`.
 */
import '@angular/platform-server/init';

import { enableProdMode } from '@angular/core';

import { environment } from './environments/environment';

if (environment.production) {
    enableProdMode();
}

export { AppServerModule } from './app/app.server.module';
export { renderModule, renderModuleFactory } from '@angular/platform-server';
  1. src/main.ts

...
//this part of code
document.addEventListener("DOMContentLoaded", () => {
    platformBrowserDynamic()
        .bootstrapModule(AppModule)
        .catch(err => console.log(err));
});

// replaced by

function bootstrap() {
    platformBrowserDynamic().bootstrapModule(AppModule)
        .catch(err => console.error(err));
};


if (document.readyState === 'complete') {
    bootstrap();
} else {
    document.addEventListener('DOMContentLoaded', bootstrap);
}

//but I don't think it plays a role in solving the JIT problem. Wrote just in case
  1. tsconfig.server.json

{
  "extends": "./tsconfig.app.json",
  "compilerOptions": {
    "outDir": "./out-tsc/app-server",
    "module": "commonjs",// it's only in my case, I don't have time for rewrote server.ts now
    "types": ["node"],
  },
  "files": [
    "src/main.server.ts",
    "server.ts"
  ],
  "include":["server/**/*.ts","node/*.ts"],
  
  "angularCompilerOptions": {
    "entryModule": "./src/app/app.server.module#AppServerModule"
  }
}

好的,我想就是这样。在所有这些编辑之后,我没有文件 /dist/server.js 并从 /dist/server/main.js 启动项目而不会出现这种情况下的错误。

注意:当我逐步更新项​​目时,我注意到通过 Angular-CLI 更新 nguniversal 的过程并没有改变项目中的任何内容。只有包的版本。这就是为什么我建议您手动将您的项目与实际的干净项目进行比较

【讨论】:

  • 谢谢维塔利。我将尝试将这些更改与我今天的项目进行比较。
  • 好吧,我现在得到一个不同的错误。运行 serve:ssr 时,我得到:SyntaxError: Strict mode code may not include a with statement
  • 我认为这可能是项目中的一些错误。也许这是一个原因:github.com/angular/angular/issues/34970#issuecomment-581838896.
  • 我在调查时看到了相同的链接,但我更新了我的代码无济于事。我想我可能不得不创建一个新项目并开始逐步添加我的代码,直到它中断。
【解决方案3】:

似乎 angular 13 使 babel-loader 成为链接 Ivy-native 包的强制性要求。 https://github.com/angular/angular/issues/44026#issuecomment-974137408 - 问题正在发生,因为核心 Angular 库已经使用 Ivy 包格式编译。

我还没有在自己的项目中进行更改,但是使用 babel 和特殊链接器处理 .mjs 文件就足够了。

import { dynamicImport } from 'tsimportlib';

/**
 * Webpack configuration
 *
 * See: http://webpack.github.io/docs/configuration.html#cli
 */
export default async (options: IWebpackOptions) => {
    const linkerPlugin = await dynamicImport('@angular/compiler-cli/linker/babel', module);
    
    const config: any = {
        module: {
            rules: [{
                test: /\.mjs$/,
                loader: 'babel-loader',
                options: {
                    compact: false,
                    plugins: [linkerPlugin.default],
                },
                resolve: {
                    fullySpecified: false
                }
            }
        }
    }
}

一旦我能够自己测试这篇文章,我将对其进行更多更新。

【讨论】:

  • 有趣。我没有在我的任何项目中使用自定义 webpack 插件。你有关于如何在现有项目中使用/配置它的参考吗?
  • 你为什么使用dynamicImport?我看到一个类似的 sn-p 没有它import linkerPlugin from '@angular/compiler-cli/linker/babel'; 然后` ... {options: {plugins: [linkerPlugin],}` @RushPL
  • 这应该会指导您如何在代码库中设置 custom-webpack https://www.npmjs.com/package/@angular-builders/custom-webpack
猜你喜欢
  • 2022-12-19
  • 1970-01-01
  • 2022-11-15
  • 2022-07-26
  • 2021-11-04
  • 2021-10-18
  • 2021-05-25
  • 2021-11-21
  • 2022-01-02
相关资源
最近更新 更多