angular-cli
angular-cli copied to clipboard
Wildcard imports without an extension are not supported in application builder
Which @angular/* package(s) are the source of the bug?
Don't known / other
Is this a regression?
Yes
Description
We have a set of auto-generated files that contain locale information for countries that's based off of CLDR information.
Example File
Filename: src/app/auto-generated/countries/XX.ts` where XX is the locale id (e.g. `en-us`).
export const data: [string, string][] = [['US', 'United States'], ['CA', 'Canada'], ...];
We used a Resolver class to retrieve this information.
export class CountryResolver implements Resolver<CountriesProperties[]> {
constructor(@Inject(LOCALE_ID) private readonly localeId: string) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Countries> {
return this.getCountries(this.localeId);
}
getCountries(localeId: string): Promise<CountryProperties[]> {
const locale = toLower(localeId);
// Attempt to import locales, otherwise import default locale 'en'
return import(`../../../auto-generated/countries/${locale}`)
.then(({ data } => resolve(data))
.catch(() => import(`../../../auto-generated/countries/en`))
.then(({ data } => resolve(data)));
}
This has worked, even in Angular 15.
I have just upgraded to Angular 17, this no longer works. I now get the following error:
[ERROR] File 'src/app/auto-generated/countries/en.d.ts' is missing from the TypeScript compilation. [plugin angular-compiler]
src/app/pages/input/input.resolve.ts:4:16:
4 │ ...urn import(`../../auto-generated/countries/${locale}...
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ensure the file is part of the TypeScript program via the 'files' or 'include' property.
It outputs that error for every file name in that directory.
I have tried adding the following to tsconfig.app.json
as well as tsconfig.json
but it doesn't do anything:
include: ['src/app/auto-generated/**/*.ts']
Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/stackblitz-starters-gzddrv?file=package.json
Please provide the exception or error you saw
[ERROR] File 'src/app/auto-generated/countries/zh-hant.d.ts' is missing from the TypeScript compilation. [plugin angular-compiler]
src/app/pages/input/input.resolve.ts:4:16:
4 │ ...urn import(`../../auto-generated/countries/${locale}...
╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ensure the file is part of the TypeScript program via the 'files' or 'include' property.
Please provide the environment you discovered this bug in (run ng version
)
Angular CLI: 17.0.2
Node: 18.16.0
Package Manager: npm 9.5.1
OS: linux x64
Angular: 17.0.4
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1700.2
@angular-devkit/build-angular 17.0.2
@angular-devkit/core 17.0.2
@angular-devkit/schematics 17.0.2
@angular/cli 17.0.2
@angular/ssr 17.0.2
@schematics/angular 17.0.2
ng-packagr 17.0.2
rxjs 7.8.1
typescript 5.2.2
zone.js 0.14.2
Anything else?
I have also tried just converting the files to JSON, placing them in the assets
folder and importing those via
import(`../../assets/path/to/${localeId}.json?raw`)
Btut I always get a console error saying that ../../assets/path/to/file/en.json
doesn't exist.
I ended up just using fetch
with the files in the assets
folder, however, it looks like this might not work with SSR.
This doesn't solve the dynamic import issue you are having but that information is available directly from the browser via the Intl
API. For display names: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames
As to the import errors, it appears to be resolving to .d.ts
files but if there are .ts
files then .d.ts
files shouldn't exist. Can you provide a sample of the filenames in the directory for some locales?
A minimal reproduction would, however, be ideal to further investigate the issue.
I think this is because of switch to ESBUILD. As far as i know, ESBUILD is not so good in code splittig as webpack.
We have 1 ICON file (svg in ts) per file... ANd in WEBPACK it code splits the icons SO GREAT..but in ESBUILD powered angulae (in NG17) it packs ALL icons to 1 200kB CHUNK
This is why we have migrated back to Webpack build system...
ESBUILD:
Webpack:
i have read, that Code-splitting in ESBuild is VERY limited and WIP.. https://esbuild.github.io/api/#splitting
I dont know why angular has switched to ESBUild by default as far as they know the importance of code splitting..
More info:
https://makandracards.com/makandra/595482-code-splitting-in-esbuild-caveats-and-setup
Also...We had to create Sencodary entry points for components used inside @defer() to make them really lazy loaded...
@montella1507, I'm a bit uncertain about the problem you've shared since the first image is too small for me to make out. Nonetheless, esbuild's approach to code splitting surpasses that of Webpack even though it is still marked as WIP in their docs as it performs code splitting and code motion based on usage, a capability Webpack lacks.
Regarding the highlighted point, it seems more like a powerful code motion feature than a drawback. This feature consolidates components used across multiple entry points into a shared chunk. If a component isn't used in one entry point, a separate chunk is created solely for that unshared component.
Since the original issue is unrelated to code splitting and code motion. I suggest that you file a new issue with a reproduction if you are experiencing any problem.
@alan-agius4 willing to elaborate? I can provide stats for big project - both esbuild and webpack.
Project is well designed in terms of code splitting..
@montella1507, again this is not the right issue to discuss your issue about code splitting, as the original issue being reported here is completely unrelated to code splitting.
Please file a new issue with a minimal reproduction that demonstrates the problem that you are experiencing.
@clydin , here you go: https://stackblitz.com/edit/stackblitz-starters-gzddrv?file=package.json
Interestingly in Stackblitz, the console shows an error saying "Files not registered with SystemJS dynamic imports". I don't get that when I run it locally as you can see from the error messages above. I'm also using SSR so maybe that's why. But you can see it can't load the files regardless.
Thank you for the reproduction. That "Files not registered..." error seems to be StackBlitz related.
If you add "files/*.ts"
to the include
option in the tsconfig.app.json
, that code should build successfully.
I also tried locally and with that change, I got the following output:
Initial Chunk Files | Names | Raw Size | Estimated Transfer Size
main.js | main | 199.26 kB | 55.58 kB
chunk-RIKMN4LX.js | - | 547 bytes | 547 bytes
styles.css | styles | 0 bytes | 0 bytes
| Initial Total | 199.79 kB | 56.11 kB
Lazy Chunk Files | Names | Raw Size | Estimated Transfer Size
chunk-BH3KKJBR.js | en-us | 68 bytes | 68 bytes
chunk-DNIW2XDY.js | ca | 65 bytes | 65 bytes
chunk-6Z25HHN7.js | en | 65 bytes | 65 bytes
I would definitely recommend considering a switch to using the Intl
API directly. This would avoid the need for the code autogeneration as well as the import/cache logic.
@clydin , Thanks for taking a look. I also see the various chunks being generated for each file, but the issue is the errors that show up in the angular cli and in the browser saying it can't find them when trying to use them.
I've switched to the Intl for now, but this may be an issue where the data can't come from Intl :(
When I get time, I'll try to come up with a github repo reproducing the error. I wonder if this only happens when using SSR becuase my repo does use SSR.
Upon further investigation, I believe i have tracked down what you are encountering. The lack of an extension within the import expression appears to be the problem. The dynamic import is assuming ESM browser behavior where a file extension is required. Changing the specifier text to ./files/${id}.ts
allows it to work as intended in the browser.
We will investigate a solution that potentially allows for the extensionless behavior.