html-loader icon indicating copy to clipboard operation
html-loader copied to clipboard

Problem with migration from webpack 4 to 5. Html-loader strange behavior with @ngtools/webpack.

Open PabloDotcom opened this issue 3 years ago • 22 comments

Hi there, I do migration from webpack 4 to 5. For my development webpack configuration it works in the end, but for production one I have build issues. Looks like html goes out not as a string, but as a variable/module. I've got plenty of errors like following: Screen Shot 2021-03-12 at 8 20 59 PM

Here as a text: `src/app/layouts/support/SupportComponent.ts:21:18 21 templateUrl: 'support.html', ~~~~~~~~~~~~~~ Error occurs in the template of component SupportComponent. src/app/layouts/support/support.html:20:1784 - error NG5002: Unexpected closing tag "ng-container". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags

20 var code = "<div class="settings-panel support">\n <div class="support__statuses">\n <div class="support__env-info">\n <div class="support__env-info-item">\n {{ 'i18n.settings.version-number' | translate }}: {{ version }}\n \n \n <div class="support__systems">\n <div *ngFor="let s of (systems$ | async)" class="support__system">\n <div class="status-circle" [ngClass]="s.statusClass || ''">\n {{ s.name }}\n \n \n \n\n <ng-container *ngLet="supportEmail$ | async as orgSupportEmail">\n <ng-container *ngLet='supportNumber$ | async as supportNumber'>\n <ng-container *ngIf="orgSupportEmail || supportNumber">\n <a *ngIf="supportNumber" class="support__link" (click)="callSupport(supportNumber)">\n <i class="zmdi zmdi-phone"> {{ supportNumber }}\n \n\n <a *ngIf="orgSupportEmail" class="support__link" [href]="'mailto:' + orgSupportEmail">\n <i class="zmdi zmdi-email"> {{orgSupportEmail}}\n \n\n <div class="support__header">\n {{ 'i18n.settings.header' | translate }}\n \n\n <div class="support__org-logo">\n <img src="" + HTML_LOADER_REPLACEMENT_0 + "" alt="{{ 'i18n.short-app-name' | translate }}">\n \n <p class="support__description">\n {{ 'i18n.settings.our-dedicated-team' | translate }}\n

\n \n \n \n\n\n\n\n";`

Html-loader has for both config as following:

{ test: /\.html$/, use: [{ loader: 'html-loader', options: { esModule: false, } }], },

Why it's like var code =?

PabloDotcom avatar Mar 12 '21 19:03 PabloDotcom

ng-container is not HTML tag... so it is expected when parser failed with non standard markup

alexander-akait avatar Mar 13 '21 13:03 alexander-akait

hey @alexander-akait, thanks for trying to help. But with dev webpack it's totally fine. It's one and only loader for html files that I have in this project (webpack.dev works fine, webpack.prod for electron build fails). But failing build has target: 'electron-renderer' and MiniCssExtractPlugin.

PabloDotcom avatar Mar 13 '21 18:03 PabloDotcom

You can't use html-loader for non standard HTML, we just can't parse it, you need other loader/type, I recommend to use type: 'asset/source' https://webpack.js.org/guides/asset-modules/

alexander-akait avatar Mar 13 '21 18:03 alexander-akait

@alexander-akait it works like a charm! Thank you very much! This approach leads to another problem. When I have in my html markup: <img src="~shared/images/empty-avatar.png" /> of course doesn't resolve it anymore like html-loader. So the links are not resolved anymore. Do you have any advice for it?

PabloDotcom avatar Mar 14 '21 17:03 PabloDotcom

@PabloDotcom Unfortunately not, you need a loader for this, we can't parse non standard HTML (we use parse5 for parsing), so you need convert your code to html, maybe parse5 have options to suppress it, we need to look at possible options

alexander-akait avatar Mar 15 '21 11:03 alexander-akait

@alexander-akait sure. For now I will probably import them on *component.ts code level and pass them to html via property.

PabloDotcom avatar Mar 15 '21 12:03 PabloDotcom

Unfortunately parse5 doesn't have options to allow using non standard HTML code, I think in this case you need to using type: 'asset/source' and maybe you can do like

@Component({
  template: `
    <div>
      <!-- Hello, Padma -->
      <h1>Hello, {{customer}}</h1>
      <img src={{myImage}} alt='test'>
      <ul>
        <!-- Ebony and Chiho in a list-->
        <li *ngFor="let customer of customers">{{ customer.value }}</li>
      </ul>
    </div>
  `
})
class AppComponent {
  customers = [{value: 'Ebony'}, {value: 'Chiho'}];
  customer = 'Padma';
  // Or you can do `import myImage from './path/to/image.png'; ` on the top of file
  myImage = new URL('./image.png', import.url.meta);
}

So all URLs will be resolved

alexander-akait avatar Mar 15 '21 12:03 alexander-akait

I am not familiar with angular syntax, sorry, but I hope you understand my idea

alexander-akait avatar Mar 15 '21 12:03 alexander-akait

@alexander-akait yeah, this is approach that I mentioned in my previous comment :) If I will find another way to do it I will let you know.

PabloDotcom avatar Mar 15 '21 12:03 PabloDotcom

Hey guys .. this issue makes me feel confused and anxious about upgrading to latest html-loader in multiple projects.

So if I define a web component named <ng-container> would html-loader fail to parse it? This sounds like broken behavior. Custom tag names are a pretty standard thing these days. What difference does it make that it's a structural/internal tag name in Angular?

Sorry for my confusion. Maybe I am simply not understanding something.

Rush avatar Mar 15 '21 14:03 Rush

@Rush <ng-container> tag doesn't exist in HTML spec, so we don't know how to parse it

alexander-akait avatar Mar 15 '21 14:03 alexander-akait

It doesn't have to exist as it could be a custom element such as a Web Component.

https://developer.mozilla.org/en-US/docs/Web/Web_Components https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots

See this exmaple https://codesandbox.io/s/web-components-using-vanilla-js-forked-c9xsk where I defined a custom ng-container web component.

Rush avatar Mar 15 '21 15:03 Rush

https://github.com/WICG/webcomponents

Rush avatar Mar 15 '21 15:03 Rush

Somebody can provide simple case to reproduce, yep, looks it should be parser, maybe something wrong in markup, i.e. extra closing

alexander-akait avatar Mar 15 '21 15:03 alexander-akait

It seems img tag not being closed properly. Can it be a concern for the parser? Has neither end tag nor self closing by itself.

ManoharChennuru avatar May 15 '21 23:05 ManoharChennuru

Not closing some tags is legal in HTML5 https://stackoverflow.com/a/3558200/403571

Rush avatar May 15 '21 23:05 Rush

@Rush, that is TRUE.

My point is whether the parse5 is honoring them or not. Most modern browsers do, but I'm not sure if it is the case with parse5.

Sorry if my point makes no sense.

ManoharChennuru avatar May 16 '21 08:05 ManoharChennuru

Seems to work fine https://astexplorer.net/#/1CHlCXc4n4

Rush avatar May 16 '21 19:05 Rush

Without example of code I can't help :disappointed:

alexander-akait avatar May 17 '21 12:05 alexander-akait

My issue after installing html loader is it gives an error that this.getOptions() is not defined. which literally not defined in or called in the file it was written on. I found a cheap solution to that i copied the function from my loader-utilities library and past it there which works fine now but it wont work on automation deploys since the node modules gets reinstalled.

NEED A PERMANENT SOLUTION FOR THIS

ArishAzmat avatar Sep 28 '21 14:09 ArishAzmat

Maybe this will help someone. I got a similar error in my Angular project when running unit tests. I use html-loader in my webpack config. This error appeared after updating the version of Angular from 10 to 13. Analysis of the build revealed that the problem is in the loader, which was added in the commit https://github.com/angular/angular-cli/commit/f4cd6848555cd44b6a327aa936951282891a2b52. I fixed this error by adding html-loader resourceQuery: /(?<!?ngResource)$/.

wprogeye avatar Feb 09 '22 19:02 wprogeye

@wprogeye Could you please share some code? I can't make it work html-loader crashes with directTemplateLoading=false whatever I do It shows this https://ibb.co/KrST2dZ Thank you

vtulin avatar Jul 12 '22 14:07 vtulin

Closing due to inactivity. Please test with latest version and feel free to reopen if still regressions. Thanks!

alexander-akait avatar Jan 16 '24 15:01 alexander-akait