How to add fonts to create-react-app based projects?

前端 未结 7 1769
长情又很酷
长情又很酷 2020-11-29 15:19

I\'m using create-react-app and prefer not to eject.

It\'s not clear where fonts imported via @font-face and loaded locally should go.

Namely,

相关标签:
7条回答
  • 2020-11-29 16:10

    I spent the entire morning solving a similar problem after having landed on this stack question. I used Dan's first solution in the answer above as the jump off point.

    Problem

    I have a dev (this is on my local machine), staging, and production environment. My staging and production environments live on the same server.

    The app is deployed to staging via acmeserver/~staging/note-taking-app and the production version lives at acmeserver/note-taking-app (blame IT).

    All the media files such as fonts were loading perfectly fine on dev (i.e., react-scripts start).

    However, when I created and uploaded staging and production builds, while the .css and .js files were loading properly, fonts were not. The compiled .css file looked to have a correct path but the browser http request was getting some very wrong pathing (shown below).

    The compiled main.fc70b10f.chunk.css file:

    @font-face {
      font-family: SairaStencilOne-Regular;
      src: url(note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf) ("truetype");
    }
    

    The browser http request is shown below. Note how it is adding in /static/css/ when the font file just lives in /static/media/ as well as duplicating the destination folder. I ruled out the server config being the culprit.

    The Referer is partly at fault too.

    GET /~staging/note-taking-app/static/css/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf HTTP/1.1
    Host: acmeserver
    Origin: http://acmeserver
    Referer: http://acmeserver/~staging/note-taking-app/static/css/main.fc70b10f.chunk.css
    

    The package.json file had the homepage property set to ./note-taking-app. This was causing the problem.

    {
      "name": "note-taking-app",
      "version": "0.1.0",
      "private": true,
      "homepage": "./note-taking-app",
      "scripts": {
        "start": "env-cmd -e development react-scripts start",
        "build": "react-scripts build",
        "build:staging": "env-cmd -e staging npm run build",
        "build:production": "env-cmd -e production npm run build",
        "test": "react-scripts test",
        "eject": "react-scripts eject"
      }
      //...
    }
    

    Solution

    That was long winded — but the solution is to:

    1. change the PUBLIC_URL env variable depending on the environment
    2. remove the homepage property from the package.json file

    Below is my .env-cmdrc file. I use .env-cmdrc over regular .env because it keeps everything together in one file.

    {
      "development": {
        "PUBLIC_URL": "",
        "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
      },
      "staging": {
        "PUBLIC_URL": "/~staging/note-taking-app",
        "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
      },
      "production": {
        "PUBLIC_URL": "/note-taking-app",
        "REACT_APP_API": "http://acmeserver/note-taking-app/api"
      }
    }
    

    Routing via react-router-dom works fine too — simply use the PUBLIC_URL env variable as the basename property.

    import React from "react";
    import { BrowserRouter } from "react-router-dom";
    
    const createRouter = RootComponent => (
      <BrowserRouter basename={process.env.PUBLIC_URL}>
        <RootComponent />
      </BrowserRouter>
    );
    
    export { createRouter };
    

    The server config is set to route all requests to the ./index.html file.

    Finally, here is what the compiled main.fc70b10f.chunk.css file looks like after the discussed changes were implemented.

    @font-face {
      font-family: SairaStencilOne-Regular;
      src: url(/~staging/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf)
        format("truetype");
    }
    

    Reading material

    • https://create-react-app.dev/docs/adding-custom-environment-variables#adding-development-environment-variables-in-env

    • https://create-react-app.dev/docs/deployment#serving-apps-with-client-side-routing

    • https://create-react-app.dev/docs/advanced-configuration

      • this explains the PUBLIC_URL environment variable

        Create React App assumes your application is hosted at the serving web server's root or a subpath as specified in package.json (homepage). Normally, Create React App ignores the hostname. You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included). This may be particularly useful when using a CDN to host your application.

    0 讨论(0)
提交回复
热议问题