1

我有这个有点旧的 Angular Web 应用程序,它从 Angular 6 更新到 Angular 12,但是,Angular CLI 没有用于构建它,而是依赖于 Webpack 5、它的加载器和来自 @ngtools/webpack 的 AngularWebpackPlugin。

最近,我需要升级到我正在使用的库的最新版本,并且在我的生产构建后收到以下警告:

Uncaught Error: The injectable 'j' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available.

The injectable is part of a library that has been partially compiled.
However, the Angular Linker has not processed the library such that JIT compilation is used as fallback.

Ideally, the library is processed using the Angular Linker to become fully AOT compiled.
Alternatively, the JIT compiler should be loaded by bootstrapping using '@angular/platform-browser-dynamic' or '@angular/platform-server',
or manually provide the compiler with 'import "@angular/compiler";' before bootstrapping.

在删除最小化程序并更详细地查看错误堆栈跟踪之后,这似乎是该新库的问题,特别是。

现在,我进行了一些挖掘,发现从 Angular 11.1 开始,现在可以为 Ivy 部分编译库并以这种方式运送到 NPM,而不需要 ngcc。而且,正如预期的那样,该库的源代码表明,事实上,我使用的旧版本和我尝试使用的新版本之间的主要区别在于,新版本是部分编译的。

现在,我的应用程序的 webpack 配置如下(我只留下我认为相关的设置,如果需要我可以提供整个配置文件):

module.exports = {
...
    module: {
        rules: [
            {
                test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
                loader: '@ngtools/webpack'
            }
        ],
    },
...
    plugins: [
        new CleanWebpackPlugin(),

        new AngularWebpackPlugin({
            tsconfig: './tsconfig-aot.json'
        }),

        new HtmlWebpackPlugin({
            ...
        }),

        new CopyWebpackPlugin({
            patterns: [...]
        })
    ]
};

我的问题是我在这里错过了一步吗?我需要使用某个插件来“链接”部分编译的库,以便避免这个问题吗?甚至可以以这种方式使用 Webpack 编译用于生产的 Angular 应用程序吗?我尝试了很多东西,但一切都表明我在整个过程中错过了一步。此外,我使用 Angular CLI 创建了一个测试应用程序,并使用它来安装库并使用生产模式编译它,这一切都像一个魅力,所以我可以排除它是库创建者的错的想法。

应用依赖如下:

"dependencies": {
    "@angular/animations": "12.2.0",
    "@angular/cdk": "^12.2.0",
    "@angular/common": "12.2.0",
    "@angular/compiler": "12.2.0",
    "@angular/core": "12.2.0",
    "@angular/forms": "12.2.0",
    "@angular/platform-browser": "12.2.0",
    "@angular/platform-browser-dynamic": "12.2.0",
    "@angular/platform-server": "12.2.0",
    "@angular/router": "12.2.0",
    "@angular/upgrade": "12.2.0",
    "@fullcalendar/core": "^5.9.0",
    "angular-auth-oidc-client": "^12.0.2",
    "angular-google-tag-manager": "^1.4.2",
    "angular2-ladda": "^2.0.0",
    "angular2-uuid": "1.1.1",
    "core-js": "^3.16.1",
    "headroom.js": "^0.12.0",
    "ngx-google-places-autocomplete": "^2.0.5",
    "ngx-headroom": "^1.0.6",
    "primeicons": "^4.1.0",
    "primeng": "^11.4.5",
    "protractor": "^7.0.0",
    "rxjs": "^6.6.7",
    "tslib": "^2.3.0",
    "zone.js": "0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^12.2.0",
    "@angular/cli": "12.2.0",
    "@angular/compiler-cli": "^12.2.2",
    "@ngtools/webpack": "^12.2.2",
    "@types/core-js": "^2.5.5",
    "@types/google.maps": "^3.45.6",
    "@types/jasmine": "^3.8.2",
    "@types/node": "10.11.7",
    "angular-router-loader": "0.8.5",
    "angular2-template-loader": "0.6.2",
    "autoprefixer": "^9.8.6",
    "clean-webpack-plugin": "^3.0.0",
    "copy-webpack-plugin": "^6.4.1",
    "css-loader": "^1.0.0",
    "file-loader": "2.0.0",
    "html-webpack-plugin": "^5.3.2",
    "istanbul-instrumenter-loader": "^3.0.1",
    "jasmine": "^3.8.0",
    "jasmine-spec-reporter": "^5.0.2",
    "jasmine-ts": "^0.4.0",
    "karma": "^6.3.4",
    "karma-chrome-launcher": "^3.1.0",
    "karma-coverage": "^2.0.3",
    "karma-coverage-istanbul-reporter": "^3.0.3",
    "karma-jasmine": "^4.0.1",
    "karma-jasmine-html-reporter": "^1.7.0",
    "karma-webpack": "^5.0.0",
    "postcss-loader": "3.0.0",
    "raw-loader": "0.5.1",
    "rxjs-tslint": "^0.1.8",
    "sass": "^1.37.5",
    "sass-loader": "^10.2.0",
    "source-map-loader": "^0.2.4",
    "style-loader": "0.23.1",
    "terser-webpack-plugin": "^4.2.3",
    "ts-loader": "^8.3.0",
    "ts-node": "^8.10.2",
    "tslint": "^6.1.3",
    "tslint-loader": "3.5.4",
    "typescript": "^4.3.5",
    "webpack": "^5.51.0",
    "webpack-cli": "^4.8.0",
    "webpack-dev-server": "^4.0.0"
  }
4

1 回答 1

4

我需要使用某个插件来“链接”部分编译的库,以便避免这个问题吗?

是的!您需要添加Angular Linker来处理有问题的插件。它目前仅作为 Babel 插件提供:@angular/compiler-cli/linker/babel

简而言之,将其添加到您的 Webpack 配置并替换ng-click-outside为您的插件:

rules: [
{
  // Explicit rule to run the linker over partial libraries
  test: /.*\.js$/,
  include: /node_modules\/ng-click-outside/,
  use: [
    {
      loader: 'babel-loader',
      options: {
        configFile: false,
        plugins: ['@angular/compiler-cli/linker/babel'], // Required!
      }
    }
  ]
},
{
  // Regular rule for all non-library files
  test: /\.[jt]sx?$/,
  exclude: /node_modules/,
  use: [
    {loader: 'babel-loader'}, // Optional
    {
      loader: '@ngtools/webpack', // Required
      options: {
        directTemplateLoading: false, // See https://www.npmjs.com/package/@ngtools/webpack
      }
    },
    {loader: '@angular-devkit/build-optimizer/webpack-loader'}, // Optional
  ]
},

此外,您应该删除旧@ngtools/webpack规则。您不再需要在 Angular 12 中处理“ngfactory”或“ngstyle”文件。

有关更多详细信息,请在此处查看我的其他 SO 答案。webpack 配置的功劳来自这个Github 问题的 Robert van Hoesel 。

于 2021-09-22T01:07:18.290 回答