可注入的"平台位置"需要使用 JIT 编译器进行编译,但"@angular/编译器"不可用



My 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"不可用。

可注入是已部分编译的库的一部分。但是,Angular Linker尚未处理库,因此JIT编译被用作回退。

理想情况下,使用Angular Linker处理库,使其成为完全AOT编译。或者,JIT编译器应该使用"@angular/platform browser dynamic"或"@angle/platform server"通过引导加载,或者手动向编译器提供"import"@angular/编译器";"在引导之前。在getCompilerFacade(file:///Users/btaylor/work/angular-apps/dz-outages-ui/node_modules/@angular/core/fesm2015/core.mjs:4058:15)在模块上(file:///Users/btaylor/work/angular-apps/dz-outages-ui/node_modules/@angular/core/fesm2015/core.mjs:3299:22)在file:///Users/btaylor/work/angular-apps/dz-outages-ui/node_modules/@angular/common/fesm2015/common.mjs:90:28在ModuleJob.run(节点:internal/modules/esm/module_job:185:25)异步Promise.all(索引0)在异步ESMLoader.import(节点:internal/modules/esm/loader:281:24)异步加载esm(节点:internal/process/esm_loader:88:5)在async handleMainPromise(节点:internal/modules/run_main:65:12)

我尝试过许多解决方案,例如:Angular JIT编译失败:'@angular/编译器';未加载

目前,我的包中有"type": "module"。json

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

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

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

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

这为我解决了这个问题。

angular 13似乎使babel-loader成为链接Ivy原生包的强制性要求。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
}
}
}
}
}

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

如果我理解正确,您也可以使用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创建了一个新的clean项目,并添加了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.服务器.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启动项目,在这种情况下没有错误。

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

在我的案例中,这个问题的解决方案在jest.config.js文件中缺少以下配置:

setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts']

配置

最新更新