Skip to content
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

feat(@angular-devkit/build-angular): allow configuring loaders for custom file extensions in application builder #26371

Merged
merged 1 commit into from
Nov 16, 2023

Conversation

clydin
Copy link
Member

@clydin clydin commented Nov 16, 2023

When using the application builder, a new loader option is now available for use. The option allows a project to define the type of loader to use with a specified file extension. A file with the defined extension can then be used within the application code via an import statement or dynamic import expression, for instance.
The available loaders that can be used are:

  • text - inlines the content as a string
  • binary - inlines the content as a Uint8Array
  • file - emits the file and provides the runtime location of the file
  • empty - considers the content to be empty and will not include it in bundles

The loader option is an object-based option with the keys used to define the file extension and the values used to define the loader type.

An example to inline the content of SVG files into the bundled application would be as follows:

loader: {
    ".svg": "text"
}

An SVG file can then be imported:

import contents from './some-file.svg';

Additionally, TypeScript needs to be aware of the module type for the import to prevent type-checking errors during the build. This can be accomplished with an additional type definition file within the application source code (src/types.d.ts, for example) with the following or similar content:

declare module "*.svg" {
  const content: string;
  export default content;
}

The default project configuration is already setup to use any type definition files present in the project source directories. If the TypeScript configuration for the project has been altered, the tsconfig may need to be adjusted to reference this newly added type definition file.

@angular-robot angular-robot bot added the detected: feature PR contains a feature commit label Nov 16, 2023
…stom file extensions in application builder

When using the `application` builder, a new `loader` option is now available for use.
The option allows a project to define the type of loader to use with a specified file extension.
A file with the defined extension can then used within the application code via an import statement
or dynamic import expression, for instance.
The available loaders that can be used are:
* `text` - inlines the content as a string
* `binary` - inlines the content as a Uint8Array
* `file` - emits the file and provides the runtime location of the file
* `empty` - considers the content to be empty and will not include it in bundles

The loader option is an object-based option with the keys used to define the file extension and the values used
to define the loader type.

An example to inline the content of SVG files into the bundled application would be as follows:
```
loader: {
    ".svg": "text"
}
```
An SVG file can then be imported:
```
import contents from './some-file.svg';
```
Additionally, TypeScript needs to be aware of the module type for the import to prevent type-checking
errors during the build. This can be accomplished with an additional type definition file within the
application source code (`src/types.d.ts`, for example) with the following or similar content:
```
declare module "*.svg" {
  const content: string;
  export default content;
}
```
The default project configuration is already setup to use any type definition files present in the project
source directories. If the TypeScript configuration for the project has been altered, the tsconfig may
need to be adjusted to reference this newly added type definition file.
@alan-agius4 alan-agius4 linked an issue Nov 16, 2023 that may be closed by this pull request
@clydin clydin marked this pull request as ready for review November 16, 2023 16:30
@clydin clydin added the target: minor This PR is targeted for the next minor release label Nov 16, 2023
@clydin clydin added the action: merge The PR is ready for merge by the caretaker label Nov 16, 2023
@clydin clydin merged commit 3b93df4 into angular:main Nov 16, 2023
35 checks passed
@clydin clydin deleted the esbuild/loader-build-option branch November 16, 2023 17:11
@santam85
Copy link

@clydin I'm trying to import one of the .ts files of my angular project as a raw text file, does this allow me to achieve that? If I configure a loader of ".ts": "text" and use import ts from './source-file.ts' it complains about a default export not being present (i guess the loader config gets overwritten).

How can I achieve that?

@clydin
Copy link
Member Author

clydin commented Nov 30, 2023

You currently cannot if it's a .ts extension since those files need to be compiled for the application to work. You would need to rename the file with a different extension. We are evaluating the potential use of import attributes to configure the loader on an individual basis but, while this is possible from a bundling perspective, TypeScript does not currently provide type definition support yet.

@ranitg
Copy link

ranitg commented Nov 30, 2023

where exactly do I add the loader?
loader: {
".svg": "text"
}

what are the configurations I need in the angular.json file?

this is what I have:
"build": {
"builder": "@angular-devkit/build-angular:browser-esbuild",
"options": {
"outputPath": "dist/atw-angular",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"allowedCommonJsDependencies": [
"ua-parser-js",
"file-saver"
],
"assets": [
"src/favicon.ico",
"src/assets"
]
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "3mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "400kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},

@clydin
Copy link
Member Author

clydin commented Nov 30, 2023

@ranitg It is a new build option for the @angular-devkit/build-angular:application builder that will be available in v17.1. There is a prerelease version available if you would like to try out the feature: https://github.com/angular/angular-cli/releases/tag/17.1.0-next.0

@ranitg
Copy link

ranitg commented Nov 30, 2023

Thanks! I got it to work

@santam85
Copy link

santam85 commented Dec 1, 2023

You currently cannot if it's a .ts extension since those files need to be compiled for the application to work. You would need to rename the file with a different extension. We are evaluating the potential use of import attributes to configure the loader on an individual basis but, while this is possible from a bundling perspective, TypeScript does not currently provide type definition support yet.

My use case requires me to import source files as text to showcase how to achieve the examples shown in the app. I'm really looking forward for such a feature, I'm keen to create a proposal for it in a PR but I'd need a little guidance.

@Laffery
Copy link

Laffery commented Dec 5, 2023

It is a new build option for the @angular-devkit/build-angular:application builder that will be available in v17.1.

Will this option be supported in @angular-devkit/build-angular:browser-esbuild as well? I think both the builders have the same issue.

@knackstedt
Copy link

You currently cannot if it's a .ts extension since those files need to be compiled for the application to work. You would need to rename the file with a different extension. We are evaluating the potential use of import attributes to configure the loader on an individual basis but, while this is possible from a bundling perspective, TypeScript does not currently provide type definition support yet.

My use case requires me to import source files as text to showcase how to achieve the examples shown in the app. I'm really looking forward for such a feature, I'm keen to create a proposal for it in a PR but I'd need a little guidance.

I have a similar use case

I have a web app that embeds the notorious monaco-editor, and I prefer to import type definitions during the build process as a string (they come from an npm package).
I could arguably import these definitions via fetch, but that would not be as simple as compiling it into one file

@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 Jan 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker detected: feature PR contains a feature commit target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No loader is configured for ".svg" (esbuild)
6 participants