#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:
Я решил это, просто скопировав шрифты как часть шагов сборки. В принципе, шрифты имеют свой собственный конвейер. Могут быть способы получше, но это работает достаточно хорошо.