Skip to content

Allow directTemplateLoading to be set from angular.json #15861

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
reduckted opened this issue Oct 17, 2019 · 5 comments
Closed

Allow directTemplateLoading to be set from angular.json #15861

reduckted opened this issue Oct 17, 2019 · 5 comments

Comments

@reduckted
Copy link

🚀 Feature request

Command (mark with an x)

- [ ] new
- [x] build
- [x] serve
- [ ] test
- [ ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] xi18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc

Description

The AngularCompilerPlugin allows templates to be loaded directly, bypassing any loaders configured in the webpack config. The default value of this option is false.

The Angular CLI creates an instance of the AngularCompilerPlugin and sets this option to true, with no way of overriding this behavior.

Setting this to true made sense when there was no way to customize the webpack config. However, now that CLI Builders are officially supported, it will become more common for builders like @angular-builders/custom-webpack to be used to customize the webpack configuration. But with directTemplateLoading being hard-coded to true, there is no way to customize the webpack configuration to allow a loader to manipulate a component's template.

Describe the solution you'd like

Let the directTemplateLoading option be set in the angular.json file. For example:

"architect": {
  "build": {
    "builder": "@angular-builders/custom-webpack:browser",
    "options": {
      "directTemplateLoading": false,
      "customWebpackConfig": {
        "path": "./webpack.config.js"
      },
      "etc": "etc"

Describe alternatives you've considered

This idea has been raised before in a couple of issues, but both were closed with workarounds or hacks. Since CLI Builders are now officially supported, I feel that a proper solution is required.

Use template and inline loaders

#14855 (comment) suggests using template and specifying the loaders in the require statement instead of using templateUrl.

Hi all, we had a chat around this, and we think that if you want to use webpack specific stuff you can use ngx-build-plus or otherwise you can update the require statements to include the raw-loader import syntax ie: require('!raw-loader!./path-to-template.html') as suggested above.

Manually specifying the same loaders for every component template is not maintainable.

Hack the webpack config

#14534 (comment) states that a hack is required to set directTemplateLoading:

Closing as the above method is a necessary step to augment an existing plugin within a webpack configuration.

The "above method" is to search through the plugins in the webpack config and find the AngularCompilerPlugin, get it's options, change the directTemplateLoading value to false, create a new instance of the plugin with the modified options and replace the original plugin in the webpack config. Very hacky.

Use template with loaders in the webpack config

Similar to the outcome of #14855, you can:

  1. Install @types/node.
  2. Add "node" to the types property of the tsconfig file.
  3. Change templateUrl: './foo.component.html to template: require('./foo.component.html')

and the custom loaders specified in the webpack config will be used. But this requires you to make changes to the way the component's template is specified by default, which is easy to forget to do. That's just asking for problems because forgetting to change templateUrl to template means it won't be passed through the custom loaders.

In addition to that, the Angular Language Service complains that "Component 'FooComponent' must have a template or templateUrl".

Given the choice between this and hacking the webpack config to recreate the AngularCompilerPlugin, I'd choose hacking the webpack config. 😁

@alan-agius4 alan-agius4 added the needs: discussion On the agenda for team meeting to determine next steps label Oct 17, 2019
@vikerman
Copy link
Contributor

This should be an option in the custom webpack builder and not the CLI.

@clydin clydin removed the needs: discussion On the agenda for team meeting to determine next steps label Oct 17, 2019
@clydin
Copy link
Member

clydin commented Oct 17, 2019

The @ngtools/webpack plugin is part of the default webpack configuration. This allows any custom builder to modify the options of the plugin if using the webpack configuration generated by the official builder. If a custom builder is generating a webpack configuration from scratch it would also have the opportunity to modify the plugin settings. In either case, this would allow a custom builder to provide the suggested higher level boolean option to the user of the custom builder.

@clydin clydin closed this as completed Oct 17, 2019
@reduckted
Copy link
Author

@vikerman This should be an option in the custom webpack builder and not the CLI.

That's a good point. If you're not using a custom builder, then setting it to false would only cause the build to fail. 👍

@clydin This allows any custom builder to modify the options of the plugin if using the webpack configuration generated by the official builder.

I'm having a hard time working out how that's currently possible.

In angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/typescript.js, the _createAotPlugin() function sets directTemplateLoading to a hard-coded value of true.

directTemplateLoading: true,
...options,
compilerOptions,
};
pluginOptions = _pluginOptionsOverrides(buildOptions, pluginOptions);

It also adds the options that were passed to that function, so that's a potential way of overriding the value of true. But, the two callers of _createAotPlugin() both pass in hard-coded options (the options are the second parameter).

getNonAotConfig:

plugins: [_createAotPlugin(wco, { tsConfigPath, skipCodeGeneration: true })]

getAotConfig:

plugins: [_createAotPlugin(wco, { tsConfigPath }, i18nExtract)]

_pluginOptionsOverrides() is another potential place where the plugin's options could be customized, but it only changes hostReplacementPaths and compilerOptions.

I'm not too familiar with the codebase, so perhaps I've missed something. Would you be able to show an example of how to modify the options for AngularCompilerPlugin before the plugin is created?

@reduckted
Copy link
Author

@clydin Are you able to provide an example of how to modify the options for AngularCompilerPlugin before the plugin is created?

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Dec 5, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants