mlaursen/react-md

Font mixins resolve relative paths relative to node_modules/react-md/src/scss

Closed this issue ยท 4 comments

Setup

Using react-md CRA2 install method.

Why do I want to use a relative path?

With this example:

@include host-google-font(Roboto, 400, '/fonts/roboto');
@include host-material-icons('/fonts/material-icons');

Using an absolute path outputs the same absolute path (e.g. /fonts/material-icons/MaterialIcons-Regular.woff2), which in CRA's dev server appears to match files in /public.

This seems to cause a problem when deploying the app to a relative path (e.g. https://mysite/myapp/), the app attempts to download fonts from https://mysite/fonts/... I have <base href="."> in my index page which I thought would fix this, but the /fonts urls are still resolved to https://mysite/fonts.

Using Relative Paths

@include host-google-font(Roboto, 400, 'fonts/roboto');
@include host-material-icons('fonts/material-icons');

Fails to compile with:

./src/index.scss (./node_modules/css-loader/dist/cjs.js??ref--6-oneOf-5-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--6-oneOf-5-3!./node_modules/sass-loader/lib/loader.js??ref--6-oneOf-5-4!./src/index.scss)
Module not found: Can't resolve '../node_modules/react-md/src/scss/fonts/material-icons/MaterialIcons-Regular.eot' in 'C:\projects\myapp\cra\src' 

It took me far to long to figure out I can just go up several directories to the actual location of my fonts ๐Ÿ˜…

Solution

@include host-google-font(Roboto, 400, '../../../../src/fonts/roboto'); 
@include host-material-icons('../../../../src/fonts/material-icons');

This outputs url's like
Dev server: /static/media/Roboto-Regular.3e1af3ef.ttf ๐Ÿ‘
build: ../../static/media/Roboto-Regular.3e1af3ef.ttf ๐Ÿ‘
Which I guess means the files and urls are being processed by Webpack

This works because the local dev server always runs on / and for build, the css file is in ./static/css.

Conclusion

There isn't a big issue here. This did however take enough of my time to figure out that I thought someone else might find this valuable. This could also be good to mention in the documentation. I thought about a PR but I'm not sure if this is the same when not using Create React App v2.

The react-md documentation is great! It made me realise another solution, which is just to copy out the Basic Usage CSS Output from sassdoc into my scss file and substitute my font paths. But I'd rather use the mixin with crazy relative path!

Thanks for writing this up! I hadn't thought about the webpack usage for these hosting mixins and forgot that the css-loader does some custom resolutions for the url. Looking at the css-loader resolution examples, would this code work?

@include host-google-font(Roboto, 400, '~fonts/roboto');
@include host-material-icons('~fonts/material-icons');

Might be a bit nicer than needing all the ../, but it does assume aliasing the src directory.

I think I'll update the SassDoc for these mixins though to help differentiate between webpack loaded vs normal sass compilations.

Aliasing is a nice idea, I didn't even know that was possible!
I had a read about Webpack aliases and using them in CRA. It looks like they're not supported. However, similar to how NODE_PATH is mentioned in that issue, in tsconfig.js I set compilerOptions.baseUrl = "src" and that made the above lines work.

For this small project I won't be making a config change just to make these two lines shorter, but that is a great suggestion :D

Just an update -- While writing documentation for v2, I figured out that at least with react-scripts@3.3.1 you can use the alias paths without any additional configuration by using ~./fonts instead of ~fonts:

@include rmd-typography-host-google-font(Roboto, $rmd-typography-default-font-weights, '~./fonts/roboto');
@include rmd-icon-material-icons-font-face('~./fonts/material-icons');
$ tree build/static/media
build/static/media
โ”œโ”€โ”€ Roboto-Bold.e07df86c.ttf
โ”œโ”€โ”€ Roboto-Light.88823c20.ttf
โ”œโ”€โ”€ Roboto-Medium.58aef543.ttf
โ””โ”€โ”€ Roboto-Regular.11eabca2.ttf

Since the code for v1 is almost identical to v2, it might be possible to also do it in v1 if anyone else is checking in on this:

@include host-google-font(Roboto, 400, '~./fonts/roboto');
@include host-material-icons('~./fonts/material-icons');

I'll be going with this example with v2, but keep v1 as-is with the relative paths (../../) to be safe.