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

Angular CLI is modifying the paths to fonts set in @font-face to point to the root directory in a production build #6599

Closed
gitdisrupt opened this issue Jun 7, 2017 · 53 comments

Comments

@gitdisrupt
Copy link

gitdisrupt commented Jun 7, 2017

Bug Report or Feature Request (mark with an x)

- [ x] bug report -> found similar issue which i believe to have been closed in error: #3143 

Versions.

Output from: `ng --version`.
@angular/cli: 1.1.0
node: 8.0.0
os: darwin x64
@angular/animations: 4.1.3
@angular/common: 4.1.3
@angular/compiler: 4.1.3
@angular/core: 4.1.3
@angular/forms: 4.1.3
@angular/http: 4.1.3
@angular/platform-browser: 4.1.3
@angular/platform-browser-dynamic: 4.1.3
@angular/router: 4.1.3
@angular/cli: 1.1.0
@angular/compiler-cli: 4.1.3
@angular/language-service: 4.1.3

Repro steps.

ng new testapp --style scss

Then created new directory in ./src/assets/fonts/ which includes a set of custom font files like Gibson-Light-webfont.eot for example.

Then in my styles.scss file i reference those fonts like this:


@font-face {
    font-family: 'gibson_package';
    src: url('assets/fonts/Gibson-Light-webfont.eot');
...

Then i run ng build --prod

In my ./dist directory, the build process correctly copies my fonts to ./dist/assets/fonts/* as expected, but it also included duplicates of all of my fonts right in the root of my ./dist directory which i did not expect and the paths set in @font-face url's are changed to point to the root.

The log given by the failure.

No errors are output.

Desired functionality.

That the production build only copy my fonts to the ./dist/assets/fonts directory and not modify the paths in @font-face urls.

@gitdisrupt gitdisrupt changed the title Angular CLI is duplicating fonts twice into the dist directory for a production build Angular CLI is modifying the paths to fonts set in @font-face to point to the root directory in a production build Jun 7, 2017
@filipesilva
Copy link
Contributor

There are two pipelines happening:

  • anything in the assets array is copied wholesale, no questions asked.
  • assets referenced in CSS are processed and fingerprinted, outputted to base directory.

So in your case you don't need to put those fonts in assets. Put them anywhere and the build system will recognize them.

@TimoKorinth
Copy link

Thank you @filipesilva for the clarification but I wonder what the preferred way would be?! Should I put my fonts in another folder (like 'resources') which will not be copied by default or should I put my files in the assets folder and reference them in scss with '/assets/...' instead of '../assets/...'?

@filipesilva
Copy link
Contributor

Personally, I try to put images/fonts next to the components that use them and reference them from css. But if there's an image I need to load from html I put it in assets.

@ahirhasmukh
Copy link

@filipesilva I have some issue. I have put font directory in under src directory but it is doesn't resolved

@treolandix
Copy link

Same issue occurs. Any solution yet?

@GeorgeKnap
Copy link

same here. this should be reopened.

@Garima
Copy link

Garima commented Oct 6, 2017

yes this should be opened ,it clutters the root directory

@LaughingbirdSoftware
Copy link

Agree. I have a lot of embedded fonts and 3 versions of each, so the root directory is a mess. Please re-open the issue.

@ziemerz
Copy link

ziemerz commented Oct 13, 2017

We have the exact same issue. The problem is that when you build the app with multiple languages as AOT, the paths to the fonts are incorrect. Angular references the font files like so:

http://127.0.0.1/enrawline-100.woff

Which results in a 404. The correct path should be:

http://127.0.0.1/en/rawline-100.woff

That happens when we define a @font-face in a css file in: src/assets/styles like this:

@font-face {
  font-family: 'rawline';
  src: url('../fonts/rawline-100.woff') format('woff');
  src: url('../fonts/rawline-100.woff2') format('woff2');
  font-weight: 100;
  font-style: normal;
}

If we refer to them like this instead:

@font-face {
  font-family: 'rawline';
  src: url('/assets/fonts/rawline-100.woff') format('woff');
  src: url('/assets/fonts/rawline-100.woff2') format('woff2');
  font-weight: 100;
  font-style: normal;
}

The path it tries to load them from is:

http://127.0.0.1:8081/en/en/assets/fonts/rawline-200.woff2

This issue should either be reopened or clarified how to properly include local fonts.

@filipesilva The font we're using are used in every component, and that's why I really don't want to use your provided solution, as this seems to add quite a lot of duplicates.
I've read your comment on this issue #3143 (comment)

But I don't understand why it's expected behavior. How are you expected to import a local font then?

@axmad22
Copy link

axmad22 commented Dec 7, 2017

I am using SCSS and got it to work by placing 2 folders in the src directory one is a theme folder with my styles and a fonts folder with my fonts, then I added a styles.scss in the src directory and loaded in all my styles and for my @font-face I created a variable that point to my fonts that gets prepossessed at build time thus I get my fonts in the root dist directory and not duplicate in assets, also it works in dev time with ng serve.

here is my code in the styles.scss:

$droid-font-path: "./fonts/droidnaskh/DroidNaskh-Regular.woff";
@import "styles/fonts.scss";

and in my _fonts.scss

@font-face {
  font-family: 'Droid Arabic Naskh';
  src: local('Droid Arabic Naskh'), url($droid-font-path) format('woff');
  font-style: normal;
  font-weight: 400;
}

@walhow
Copy link

walhow commented Jan 12, 2018

Is there a way to tell angular where to look up the text/html files (like favicon.ico and staticRoboto...eot)? I'd like to not have them in root (of my Java project I am deploying Angular in). All of my Angular /dist contents is currently being built into my-java-proj/static. This works for loading all the .js files (like inline.bundle.js).

I'd like to be able to tell angular to look inside of my-java-proj/static for these files. I'm currently getting 404s. The site still loads and works, but I'd like to be able to clean up these 404s.
resources404_continued

@attrox
Copy link

attrox commented Jan 23, 2018

My problem is the URL to the font is rewritten incorrectly when there's a hashtag involves in the URL.
url('./assets/fonts/ProximaNova/Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix') becomes
url("Mark Simonson - Proxima Nova Alt Regular-webfont.e802340fb269d9d36021.eot”?#iefix).

The url becomes invalid.

@narendrasinghrathore
Copy link

narendrasinghrathore commented Feb 21, 2018

@filipesilva Is there any solution or any flag which can be use while building so that fonts are not added in root directory ?
Thanks
ng build --prod --something

@rafa-suagu
Copy link

Same here, any solution to prevent to have a lot of stuff inside root folder?

@juanpablof
Copy link

juanpablof commented Mar 20, 2018

@attrox One way to solve this issue, if you still face it is as follows:

1 - Create a new file fonts.scss in your local /fonts directory containing the path to the fonts:

$breuer-text-regular-font-path: "/fonts/breuer-text/opentype-ttf/BreuerText-Regular.ttf";
$breuer-text-bold-font-path: "/fonts/breuer-text/opentype-ttf/BreuerText-Bold.ttf";
$font-family-brand: 'Breuer-Text';

2 - Import your fonts.scss into your styles.scss and use the variables:

@import "../fonts/fonts.scss";

@font-face {
font-family: $font-family-brand;
font-style: normal;
font-weight: 400;
src: url($breuer-text-regular-font-path);
}

@font-face {
font-family: $font-family-brand;
font-style: normal;
font-weight: 700;
src: url($breuer-text-bold-font-path);
}

Otherwise, use a CDN and load your fonts from there.

@X3QTO
Copy link

X3QTO commented Apr 5, 2018

Why is this issue closed and ignored? Please kindly fix this. It is too messy of a solution right now.

@ogousa
Copy link

ogousa commented Apr 5, 2018

I had the same issue, but can fix it by using absolute path instead of relative one for fonts. Like this:

@font-face {
	font-family: 'Roboto';
	font-style: normal;
	src: local('Roboto'), local('Roboto-Regular'),
		url('/assets/fonts/roboto-v18-latin-ext_latin-regular.woff2') format('woff2'),
		url('/assets/fonts/roboto-v18-latin-ext_latin-regular.woff') format('woff');
}


It works for dev and production build now.
I had '../assets/fonts/...' before and fonts were copied to the root when I use ng build --prod.

@X3QTO
Copy link

X3QTO commented Apr 6, 2018

@ogousa Thanks. It works for images as well.

@rafa-suagu
Copy link

@ogousa @X3QTO what base href do you have? the absolute path solution doesn't works for me, because I have the language path like /en, /es, /it

@ogousa
Copy link

ogousa commented Apr 6, 2018

@rafa-as, I have href='/' for DEV and href='/ProjectName/' for production.
But it doesn't matter, for the code the roof is the same. The server will add href prefix to all paths - for DEV it will be '/' + '/assets/fonts/...' , for production it will be '/ProjectName/' + '/assets/fonts/...', like this:

http://10.23.6.221/ProjectName/assets/fonts/roboto-v18-latin-ext_latin-regular.woff2

I think it should work if you have

/assets/fonts/en/...
/assets/fonts/es/...
/assets/fonts/it/...

BTW, if you have only Latin languages, you can use one font for all of them, just use Latin-Ext charset.
You can also add additional charsets for Cyrillic, Greek, etc.
Good resource for fonts: https://google-webfonts-helper.herokuapp.com/fonts/

@tonysamperi
Copy link

@ogousa great job. 🥇
Absolute path in styles.scss did the job. 👍
That's ridicolous anyway 👎

@omegascorp
Copy link

👎 this solution doesn't work for me, since the CSS I'm using in on the other domain, in case I'm using absolute path it's trying to load the file from the main domain.

@OClement
Copy link

This is a problem indeed
We need to have custom rewrite rules in our NGINX servers and having the fonts stay in the assets folder would simplify this quite a bit.

We cannot use absolute paths either (as mentioned, while this may work for some, this "solution" s*cks a bit)

@danielkolesnik
Copy link

@filipesilva , please in next update try to give us a way to change default path of linked in css/less/sass asset(not into dist/) in angular.json or other configuration file..
Because dozens or even hundreds of files in root directory it's not very cool... 💯👎
thank you in advance 👍 🥇

@digeomel
Copy link

I am using several webfonts installed with npm. They are referenced directly in the node_modules folder in my angular.json file. Unless this is fixed in the CLI, I'd have to manually edit all these CSS files inside node_modules to use absolute paths, which is not a good idea of course, because I'd have to do it again in every npm install. Ideally, I should have a script that modifies these files automatically before they are compiled, but I have no clue how to do this. I assume it will require a custom webpack config with a plugin/loader to do it?

sardell pushed a commit to sardell/metron that referenced this issue Sep 24, 2018
link to issue and temporary workaround: angular/angular-cli#6599
@belachkar
Copy link

belachkar commented Nov 7, 2018

@QuipHop
In the file :
ngsw-config.json
Just add the extensions of the files. Like this :

"files": [
          "/favicon.ico",
          "/index.html",
          "/*.css",
          "/*.js",
          "/*.jpeg",   // added
          "/*.woff2", // added
          "/*.svg",   // added
          "/*.ttf",   // added
          "/*.eot"   // added
        ]

Because all the files referenced in the css or scss are imported from the source to the root.
That's why you should add them manually to the swConfig file.

@stephengardner
Copy link

Re-open this issue

@Nunuu
Copy link

Nunuu commented Mar 21, 2019

I had same issue got it fixed by creating fonts folder in assets and added font.css file with all fontface added in that new file and then imported font.css file into style.css file and it worked for me

font.css:
@font-face {
font-family: 'Tele-Bold';
src: url('../assets/fonts/Tele-Bold.ttf');
}
style.css:
@import ".assets/fonts/fonts.scss";

Since we are originally using .sass, I had to create _fonts.css in the fonts folder:
@font-face { font-family: 'Tele-Bold'; src: url('/assets/fonts/Tele-Bold.ttf'); }
then import it into styles.sass by adding:
@import "src/assets/fonts/_fonts"

Using _fonts.sass will throw an error

@turbolego
Copy link

turbolego commented Apr 24, 2019

When deploying as "Angular Elements" we have this issue where every custom angular element has their own "assets" folder with a "fonts" folder.

We have for example one element that is running on http://localhost:4004 and another "parent" that uses this custom element running on http://localhost:4200

This method works fine in the element that is running on http://localhost:4004:

styles.scss
$fontpath: "/assets/fonts/";
@font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; src: url($fontpath + 'MaterialIcons-Regular.eot'); /* For IE6-8 */ src: local('Material Icons'), local('MaterialIcons-Regular'), url($fontpath + 'MaterialIcons-Regular.woff2') format('woff2'), url($fontpath + 'MaterialIcons-Regular.woff') format('woff'), url($fontpath + 'MaterialIcons-Regular.ttf') format('truetype'); }
angular.json
"assets": [ "src/assets/fonts" ],
(Thanks @johanroug for this solution
From similar issue: #3143

But when using the custom element in the "parent" running on http://localhost:4200 i get these errors:

dialog.js:244 GET http://localhost:4200/assets/fonts/MaterialIcons-Regular.woff2 net::ERR_ABORTED 404 (Not Found) (anonymous) @ dialog.js:244 Promise.then (async) _savePreviouslyFocusedElement @ dialog.js:244 attachComponentPortal @ dialog.js:183 _attachDialogContent @ dialog.js:767 open @ dialog.js:645 openDialog @ contact-info.component.ts:101 (anonymous) @ contact-info.component.html:15 handleEvent @ core.js:29587 callWithDebugContext @ core.js:31148 debugHandleEvent @ core.js:30787 dispatchEvent @ core.js:25914 (anonymous) @ core.js:26581 (anonymous) @ platform-browser.js:1678 :4200/assets/fonts/MaterialIcons-Regular.woff:1 GET http://localhost:4200/assets/fonts/MaterialIcons-Regular.woff net::ERR_ABORTED 404 (Not Found) :4200/assets/fonts/MaterialIcons-Regular.ttf:1 GET http://localhost:4200/assets/fonts/MaterialIcons-Regular.ttf net::ERR_ABORTED 404 (Not Found)

It seems like when we package angular components as custom elements (angular elements) we have this issue.

Any suggestions for nifty hacks to get custom fonts working in angular elements? 😶

@arronlai
Copy link

This issue has been closed, but I still have problem:
What if I import some scss files from third-party libraries and there are rules like background-image: url() in these files? Do I have to modify these relative path to absolute path in my node_modules folder?

@tayambamwanza
Copy link

@filipesilva I'm having the same issue with this for images referenced using css url, it works fine until I try to run a universal build, a flag to prevent this kind of hashing would be much appreciated, would save hours of work :\

@filipesilva
Copy link
Contributor

Hi all, this is a pretty old issue that started with a simple report and then accumulated a lot of other reports. Some of these others reports are directly related to the original issue, and for others the only relation is that the problem also involves resources in CSS. I understand the distinction isn't obvious, and often it's not clear until it's investigated for a while.

But either way reporting things on an old closed issue isn't the best way of getting them addressed. It's better to open a new issue with all details necessary, like version numbers and a minimal reproduction. This way it's crystal clear what the issue is, and and anyone can try to fix it.

If you've commented on this issue and are still having problems with the way Angular CLI processes CSS resources, please open a new issue and fill in the details requested in the issue template.

@elron
Copy link

elron commented Aug 9, 2019

If your fonts are not working

use './assets/ instead of '/assets/

Worked for me

@font-face {
  font-family: 'FtMonopol';
  src: url('./assets/fonts/FtMonopol-0.21-Medium.woff') format('woff'), /* Pretty Modern Browsers */
       url('./assets/fonts/FtMonopol-0.21-Medium.ttf')  format('truetype'); /* Safari, Android, iOS */
  font-weight:700;
}

@dangrima90
Copy link

@elron I actually had to change from ./assets/ to /assets/ to not get the fonts in the root folder. I find it a strange behaviour from the CLI to copy certain files to the root folder.

Example:

@font-face {
	font-family: 'Montserrat';
	src: url('/assets/fonts/montserrat-regular.ttf') format('truetype'),
		url('/assets/fonts/montserrat-regular.woff') format('woff'),
		url('/assets/fonts/montserrat-regular.woff2') format('woff');
	font-weight: 400;
}

I'm running the following versions:

Angular: 8.2.0
Angular CLI: 8.2.1

@spock123
Copy link

@elron I actually had to change from ./assets/ to /assets/ to not get the fonts in the root folder. I find it a strange behaviour from the CLI to copy certain files to the root folder.

The issue with this is that it doesn't work when dealing with i18n, because you are using different base-href for each language. Absolute paths do not work when referenced from css files.

@laurentperroteau
Copy link

I found a temporal workaround for my Angular/Electron app:

If I use absolute import (/assets/fonts), in production mode, Chrome in Electron request the file at file:///assets/fonts..., at the root of the OS.

So I moved @font-face in index.html, the relative import (assets/fonts) work again in dev mode (http://localhost:4200) and in production mode (file://).

@shlomiassaf
Copy link

To make things worse, before version 8, /assets/fonts/... worked with deploy-url and the end result after post-processing was my-deploy-url/assets/fonts/... but now it just leaves it as is

@ErVishalM
Copy link

ErVishalM commented Oct 1, 2019

If your fonts are not working

use './assets/ instead of '/assets/

Worked for me

@font-face {
  font-family: 'FtMonopol';
  src: url('./assets/fonts/FtMonopol-0.21-Medium.woff') format('woff'), /* Pretty Modern Browsers */
       url('./assets/fonts/FtMonopol-0.21-Medium.ttf')  format('truetype'); /* Safari, Android, iOS */
  font-weight:700;
}

@ogousa I have given absolute patch in my project

@font-face {
    font-family: 'Open Sans';
    font-style: normal;
    font-weight: 300;
    src: url('/assets/fonts/open-sans-v15-latin-300.eot');
    /* IE9 Compat Modes */
    src: local('Open Sans Light'), local('OpenSans-Light'), 
    url('/assets/fonts/open-sans-v15-latin-300.woff2') format('woff2'),
}

It should work but it did not work now i am getting error at the time of deploy. Because lets say my production IP is 192.168.2.38 project name is AngularProject and fonts are in Assets/Fonts folder but when i build and deploy this then it is giving me error that "open-sans-v15-latin-300.woff2" is not found on this location 192.168.2.38/assets/Fonts/open-sans-v15-latin-300.woff2 but actually its on this location -
192.168.2.38/AngularProject/assets/Fonts/open-sans-v15-latin-300.woff2 so when i manually edit the prod style.css file and change the path to url('./assets/fonts/open-sans-v15-latin-300.woff2') format('woff2') then it works .
Can you please help me i am doing wrong something here?

@ErVishalM
Copy link

@ogousa can you please provide a solution?

@ogousa
Copy link

ogousa commented Oct 4, 2019

With Angular 8 we have the same problem again :(
To fix it you can add Node.js script which modifies assets url AFTER compilation.

For production build you can use this command:
npm run prod-build
The "prod-build" is defined in package.json:

"scripts": {
    "prod-build": "ng build --prod --base-href /aaa/ && node ./scripts/web.js",
    ...
}

where aaa is the base url.

You have to add new script "web.js" to scripts folder (scripts folder is on the same level as src).
Also you have to install "replace-in-file" package:

npm i replace-in-file

This is the content of web.js:

var replace = require('replace-in-file');

let fromList = [];
let toList = [];

// fix assets path for web production build
fromList.push(new RegExp('/assets/fonts', 'g'));
toList.push('./assets/fonts');

try {
	let options = {
		files: 'dist/aaa/styles.*.css',
		from: fromList,
		to: toList,
		allowEmptyPaths: false
	};
	replace.sync(options);
}

catch (error) {
	console.error('Error occurred:', error);
}

This code simply replaces all occurrence of absolute path /assets/fonts with relative path ./assets/fonts in resulting style file inside dist folder.

It should work until Angular team fix this issue :)

@ErVishalM
Copy link

Thank you @ogousa. Is there any reported issue so that I can follow that issue directly.

@Sathyaraj06
Copy link

Sathyaraj06 commented Oct 9, 2019

don't use dots for relative path here, just use as url('/assets/abc.woff2'). It doesn't point to that file when pressing "ctrl + click", but it removes the duplicate files created in the root dist folder.

eg : ('../fonts/abc') to ('/fonts/abc')
: ('./assets/abc.woff2') to ('/assets/abc.woff2')

@UsarodnaKuze
Copy link

on angular 8.0.2 adding

"production": {
              "deployUrl": "./path/to/prod/files/",

in angular.json solved the problem for me

@malua
Copy link

malua commented Nov 7, 2019

@UsarodnaKuze could you clarify this? thank you so much!

@Willyisback
Copy link

Willyisback commented Nov 15, 2019

@Sathyaraj06: If I take the dot away, it takes the wrong path.

src: url('/assets/fonts/Regular/OpenSans-Regular.woff');

then in production:

image

For info, base-href is \app\ and I bind the font over angular.json:

              {
                "glob": "**/*",
                "input": "./node_modules/npm-font-open-sans/fonts/",
                "output": "./assets/fonts/"
              }

Workaround for me is:

src: url('~/assets/fonts/Regular/OpenSans-Regular.woff');

Then it works.

@ogousa
Copy link

ogousa commented Nov 15, 2019

Yes, it really works!
I have Angular 8.12 and project name aaa:
ng build --prod --base-href /aaa/

for fonts:
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; src: url('~/assets/fonts/roboto-v18-latin-ext_latin-regular.woff2') format('woff2'); }

for images:
background: url('~/assets/images/br-header.svg');

Everything works fine for external server and for localhost.

Thank you, Willyisback!

@alxshell
Copy link

alxshell commented Dec 5, 2019

@Willyisback thank you very much. It works like a charm.

Would you mind to explain why the usage of the tilde is working here... I am really excited to understand it :)

@niccolofanton
Copy link

Yes, it really works!
I have Angular 8.12 and project name aaa:
ng build --prod --base-href /aaa/

for fonts:
@font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; src: url('~/assets/fonts/roboto-v18-latin-ext_latin-regular.woff2') format('woff2'); }

for images:
background: url('~/assets/images/br-header.svg');

Everything works fine for external server and for localhost.

Thank you, Willyisback!

This works! thanks man

@Willyisback
Copy link

@alxshell
The tilde will be replaced by the base-href during building. So it works for both development and production. :)

@denkerny
Copy link

denkerny commented Jan 9, 2020

why does this is still closed? Dist folder has duplicate of assets and it has bigger size. Is there a way to prevent copy to root folder files are already exist here into specific folders (like fonts, img, etc.)

here is explanation:

-dist
 --fonts
   --- *.ttf
 --img 
   --- cat.png
 cat.png
 *.ttf

@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 Feb 9, 2020
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