Search code examples
angularwebpackpdf.jsecmascript-2020

Angular 9 fails to load pdfjs (v. 2.8.335) module with optional chaining


I'm trying to update pdfjs module to the next version (2.8.335) in my Angular application and got following error:

ERROR in C:/project/node_modules/pdfjs-dist/build/pdf.js 2205:45
Module parse failed: Unexpected token (2205:45)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|         intent: renderingIntent,
|         renderInteractiveForms: renderInteractiveForms === true,
>         annotationStorage: annotationStorage?.serializable || null
|       });
|     }
ERROR in C:/project/node_modules/pdfjs-dist/web/pdf_viewer.js 613:31
Module parse failed: Unexpected token (613:31)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|   _cachedPageNumber(pageRef) {
|     const refStr = pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
>     return this._pagesRefCache?.[refStr] || null;
|   }

This problem is related to version of webpack used by @angular-devkit/[email protected], I use the latest version available for Angular 9. This version of build-angular uses [email protected] which triggers these errors. I found that optional chaining and null-coalescing are supported out of box in webpack higher than 5 ver, but I'm limited with Angular 9 and cannot update it to higher version to load build-angular and as dependency, webpack to higher version.

Is there a way to configure webpack to support optional chaining and null-coalescing features of js in order to load the module into my application?


Solution

  • With hint from Akxe I managed to solve the issue in following way:

    @angular-devkit/build-angular has builder @angular-builders/custom-webpack:dev-server described here. I added this builder to angular.json file at my project like this:

    ...
    "serve": {
      "builder": "@angular-builders/custom-webpack:dev-server",
      "options": {
        "browserTarget": "myApp:build",
        "proxyConfig": "apps/myApp/proxy.conf.js",
        "customWebpackConfig": {
          "path": "apps/myApp/webpack.config.js"
        }
      },
    ...
    

    if file webpack.config.js I added babel loader with filter to load only files from pdfjs-dist:

    module.exports = {
      module: {
        rules: [
          {
            test: /\.*pdfjs-dist.*$/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env']
              }
            }
          }
        ]
      }
    };
    

    This configuration allows to transpile es2020 module of pdfjs to earlier version of js which easily consumed by standard webpack configuration, defined by angular under the hood.