angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.77k stars 11.97k forks source link

The way to different path mapping between server and browser when using application builder #27764

Closed leo6104 closed 5 months ago

leo6104 commented 5 months ago

Command

build, serve

Description

When i upgrade webpack builder to application builder, There is limits for server side rendering.

I use pdfjs-dist which include canvas.node binding dependencies. In browser serving & build process, pdfjs-dist can be bundled without errors. However, in server side, there is no .node extension loader so it raise No loader is configured for ".node" files: node_modules/canvas/build/Release/canvas.node.

Previously, to avoid this problem with webpack builder, i just add path mapping rule in tsconfig.server.json only.

 "paths": {
    "pdfjs-dist": [ "../../mock/pdfjs.ts" ],
    ... 
 },

In @angular-devkit webpack or browser-esbuild, it is available to setup tsconfig for server side. In @angular-devkit/build-angular:application, it is not available to add tsconfig.server.json so cannot use this kind of path mapping.

Describe the solution you'd like

I saw 'webWorkerTsConfig' in angular.json schema.

Can we add 'serverTsConfig' option like webWorkerTsConfig?

Describe alternatives you've considered

No response

alan-agius4 commented 5 months ago

Hi @leo6104, I am unable to replicate the reported problem. Can you setup a minimal repro please?

You can read here why this is needed. A good way to make a minimal repro is to create a new app via ng new repro-app and adding the minimum possible code to show the problem. Then you can push this repository to github and link it here.

This might be related to your directory structure so its really important to get an accurate repro to diagnose this.

leo6104 commented 5 months ago

@alan-agius4 Thanks for comment 😊

Here is repro repository. https://github.com/leo6104/ng-app-builder-error

Here is 3 commands i made in package.json

npm run app:serve  -> it will raise error (canvas node binding) 
npm run webpack:serve -> correctly serving `pdf-viewer` component
npm run webpack:serve-ssr -> correctly serving `pdf-viewer.ssr` component with path mapping
alan-agius4 commented 5 months ago

Hi @leo6104, thanks for the reproduction. In this case it is recommanded to set canvas as external dependency and instead of replacing the component file you only trigger the pdfjs-dist import when running on the client side.

  "architect": {
    "build": {
      "builder": "@angular-devkit/build-angular:application",
      "options": {
        "outputPath": "dist/repro-app",
        "index": "src/index.html",
        "browser": "src/main.ts",
        "polyfills": [
          "zone.js"
        ],
        "externalDependencies": ["canvas"],
import { Component, afterNextRender } from '@angular/core';

@Component({
  selector: 'pdf-viewer',
  template: `pdfjs-dist bundle loaded`,
  standalone: true,
})
export class PdfViewer {
  constructor() {
    afterNextRender(() => {
      import('pdfjs-dist').then((js) => {
        // do something;
      });
    });
  }
}

or

import { isPlatformServer } from '@angular/common';
import { Component, PLATFORM_ID, inject } from '@angular/core';

@Component({
  selector: 'pdf-viewer',
  template: `pdfjs-dist bundle loaded`,
  standalone: true,
})
export class PdfViewer {
  constructor() {
    const platformId = inject(PLATFORM_ID);
    if (isPlatformServer(platformId)) {
      return;
    }

    import('pdfjs-dist').then((js) => {
      // do something;
    });
  }
}
angular-automatic-lock-bot[bot] commented 4 months ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.