Экспорт глобальных стилей с ресурсами шрифтов из TypeScript-> Модуль CommonJS

#node.js #reactjs #typescript #gatsby #yarnpkg

#node.js #reactjs #typescript #gatsby #yarnpkg

Вопрос:

У меня есть проект TypeScript React, организованный следующим образом:

 tsconfig.json
package.json
yarn.lock
lerna.json
node_modules/
packages/
  ui-library/
    package.json
    tsconfig.json
    typings.d.ts
    src/
      fonts/
        myfont.ttf
      components/
        GlobalStyle.tsx
    lib/ <-- `tsc` builds to here
  web-app/
   package.json
   src/
    components/
     
  

web-app Импортирует ui-library как модуль commonjs в свой package.json. Это управляется с помощью рабочих пространств Yarn, поэтому node_modules находится в корне, а не в каждой папке. В какой-то момент веб-приложение импортирует GlobalStyle из библиотеки пользовательского интерфейса, и именно здесь возникает проблема.

 Error: Cannot find module '../fonts/myfont.ttf'
Require stack:
 - /Users/me/sources/myproject/packages/ui-library/lib/styles/GlobalStyle.js...
  

Вот исходная инструкция import, из ui-library/src/GlobalStyle.tsx которой возникает проблема:

 import myFont from "../fonts/myfont.ttf";

const GlobalStyle = () => (
  <style global jsx>{`
    @font-face {
      font-family: "My font family";
      src: url(${myFont}) format("truetype");
    }
  ...</style>);
  

Проблема заключается в require утверждении в исходящем GlobalStyle.код js, созданный при запуске tsc в папке ui-lib:

const MYFONT_ttf_1 = __importDefault(require("./myfont.ttf"));

Я погуглил эту проблему в Интернете и обнаружил, что вам пришлось добавлять типизацию для компиляции .ttf и другого ненормального импорта. Итак, я создал typings.d.ts файл с этим объявлением:

 declare module "*.ttf" {
  const value: string;
  export default value;
}
  

И я включил его ui-library/tsconfig.json следующим образом:

 {
  "extends": "../../tsconfig.json",
  "exclude": ["lib"],
  "include": ["src"],
  "files": ["./typings.d.ts"],
  "compilerOptions": {
    "baseUrl": "src",
    "outDir": "lib",
    "declaration": true,
    "declarationMap": true,
    "noEmit": false
  }
}
  

Приведенный выше tsconfig расширяет корневой tsconfig:

 {
  "files": ["./typings.d.ts"],
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2019",
    "lib": ["dom", "es2019"],
    "strict": true,
    "jsx": "react",
    "moduleResolution": "node",
    "isolatedModules": true,
    "esModuleInterop": true,
    "noUnusedLocals": false,
    "forceConsistentCasingInFileNames": true,
    "strictNullChecks": true,
    "sourceMap": true,
    "noEmit": true,
    "declaration": false
  },
  "exclude": ["node_modules"]
}
  

Мы используем TypeScript 3.8. Дайте мне знать, если потребуется предоставить какую-либо дополнительную информацию. Я подозреваю, что я либо использую неправильный модуль / цель, либо фундаментально не понимаю какой-то аспект этого.

Подробнее Я должен отметить, что причина, по которой мы используем модули CommonJS, заключается в том, что ts-node может работать только с этим. Мы подключаем ts-node, когда выполняем сборку gatsby, следуя сути здесь в gatsby-config.js :

 require("ts-node").register();

// Use a TypeScript version of gatsby-config.js.
module.exports = require("./gatsby-config.ts");
  

Может быть, это невыполнимая проблема, которую невозможно решить, чтобы импортировать шрифты через ts-node, который является серверной средой? Запутался в том, какой правильный подход заключается в экспорте модуля со шрифтами. Хочу избавиться от ts-node и оставить файлы конфигурации Gatsby как js .. но в основном просто хочу иметь возможность импортировать мои шрифты.

Комментарии:

1. TTF / OTF / … импорт в клиентских приложениях обрабатывается сборщиком пакетов, который преобразует их, например, в URL-адреса данных. Это недостающая часть в вашем уравнении на стороне сервера.

2. @AKX Если я правильно понимаю, в выводе .js есть require(myfontasset), но это преобразуется в URL-адреса данных на более позднем этапе? Проблема в том, что я не переношу require() в данные или что require существует в первую очередь?

3. Рекомендую эти статьи всем, кто разбирается в этом, мне многое объяснили zachleat.com/web/comprehensive-webfonts

Ответ №1:

Я решил это, просто скопировав шрифты как часть шагов сборки. В принципе, шрифты имеют свой собственный конвейер. Могут быть способы получше, но это работает достаточно хорошо.