Рабочие пространства NPM с Expo и Typescript

Я пытаюсь использовать рабочие области NPM 7 в проекте Typescript Expo. На данный момент я хочу сохранить обычную структуру Expo (с корневым App.tsx файл), но я хочу изолировать некоторые части кода в рабочих областях.

У меня проблемы с компиляцией кода TS в рабочих областях. Я пробовал много всего, чтобы настроить конфигурации TS и / или Webpack, но безуспешно. Итак, вот минимальная файловая структура для ее воспроизведения:

      package.json
tsconfig.json
App.tsx
/packages
  /core
    index.ts
    package.json

Вот соответствующая часть корня ./package.json

      {
  "main": "node_modules/expo/AppEntry.js",
  "workspaces": [
    "packages/*"
  ],
  "scripts": {...},
  "dependencies": {...},
  "devDependencies": {...},
  "private": true
}

Это самый минимум

      {
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true
  }
}

В ./packages/core/package.json тоже очень просто

      {
  "name": "core",
  "private": true
}

И ./packages/core/index.ts просто экспортирует log() функция для этого примера

      export function log(s: string) {
  console.log(s)
}

Наконец, в ./App.tsx, просто импортирует функцию и пытается вызвать ее

      import { log } from 'core'
log('hello')
//...

Не компилируется

Когда я пытаюсь создать для Интернета (с expo build:web например) у меня следующая ошибка

      ✖ Expo Webpack
  Compiled with some errors in 1.62s

Failed to compile.

[path]/node_modules/core/index.ts 1:21
Module parse failed: Unexpected token (1:21)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export function log(s: string) {
|   console.log(s)
| }

Я не удивлен, потому что /node_modules каталог добровольно исключен.

Итак, мой вопрос: что мне нужно сделать, чтобы скомпилировать код рабочих пространств ? Я бы хотел, чтобы он работал "на лету" (т.е. не был предварительно скомпилирован), как если бы в моем проекте были какие-то обычные файлы. Это вообще выполнимо?

Некоторые неудачные попытки исправить это

В основном я пытался настроить tsconfig, чтобы он работал (хотя мне интересно, меняет ли это что-нибудь)

# 1

Я пробовал добавить "include": ["./node_modules/core"], в ./tsconfig.json. Это не повлияло (та же ошибка).

#2

Я попытался создать следующие /packages/core/tsconfig.json с составным вариантом:

      {
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true,
    "composite": true
  }
}

И сослался на него в корне tsconfig.json

      {
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true
  },
  "references": [{ "path": "./node_modules/core" }]
  // or even with:
  "references": [{ "path": "./packages/core" }]
}

Это не повлияло (та же ошибка).

Большое спасибо

1 ответ

Я придумал решение, которым я не очень доволен, но, по крайней мере, оно работает. На самом деле это довольно просто, я просто настроил Webpack для компиляции моего packages/* (как символические ссылки в node_modules.

Итак, сначала я установил:

      $ npm i -D ts-loader@8 webpack@4.430

Здесь важны версии, чтобы они соответствовали версии веб-пакета, используемой Expo 41.

Я также переименовал свое имя пакета (в /packages/core/package.json) на что-то вроде @workspace/core так что все мои пользовательские пакеты находятся внутри node_modules/@workspace каталог.

Это также упростит нашу конфигурацию.

Бег $ expo customize:webнеобходимо для настройки конфигурации webpack. Это произведет webpack.config.js.

Его можно настроить следующим образом:

      const createExpoWebpackConfigAsync = require('@expo/webpack-config')

module.exports = async function (env, argv) {
  const config = await createExpoWebpackConfigAsync(env, argv)

  config.module.rules = [
    {
      // this is why I renamed my packages with the @workspaces prefix.
      test: /node_modules\/@workspaces\/(.*)\.ts$/, 
      use: [
        {
          loader: 'ts-loader',
          // force ts-loader to compile in node_modules
          options: { allowTsInNodeModules: true },
        },
      ],
    },
    ...config.module.rules,
  ]

  return config
}

Не удивлюсь, если найдется более чистое решение. Но пока я буду придерживаться этого

Другие вопросы по тегам