Как разрешить Namespaces в CRA? - PullRequest
       34

Как разрешить Namespaces в CRA?

0 голосов
/ 16 апреля 2020

Я создал приложение TypeScript React, используя:

yarn create react-app my-app --template typescript

Таким образом, мой проект компилируется с Babel , а затем объединяется в webpack . Теперь я хочу использовать пространства имен TypeScript , которые по умолчанию не поддерживаются в Babel, но их можно включить . Я установил все необходимые пакеты:

В package.json я изменил react-scripts start на react-app-rewired start.

Наконец, я создал файл config-overrides.js:

const {
    override,
    addExternalBabelPlugin
  } = require("customize-cra");

module.exports = override(
    addExternalBabelPlugin([
        "@babel/plugin-transform-typescript",
        { allowNamespaces: true }
    ])
);

Однако при компиляции все равно выдается синтаксическая ошибка, как если бы плагин не был включен:

SyntaxError: /home/m93a/my-app/script.ts: Пространство имен не помечено только для объявления типа , Не декларативные пространства имен поддерживаются только в Babel экспериментально. Чтобы включить и просмотреть предупреждения, см .: https://babeljs.io/docs/en/babel-plugin-transform-typescript

Как правильно настроить мой проект, чтобы он компилировал даже не декларативные пространства имен?


EDIT : Причина, по которой мой проект не работал, на самом деле сильно отличалась от того, что я думал. Проверьте мой собственный ответ для более подробной информации.

Ответы [ 3 ]

2 голосов
/ 21 апреля 2020

Вы должны использовать addBabelPlugin вместо addExternalBabelPlugin.

tl; dr

Если мы проверяем документацию, мы см .:

addExternalBabelPlugin(plugin)

create-react-app фактически имеет два правила в конфигурации webpack для babel-loader: одно для кода в addSrc (src/ по умолчанию) и другой код external для этой папки (например, node_modules). Вы можете добавить плагины к загрузчику external, используя addExternalBabelPlugin, точно так же, как вы используете addBabelPlugin.

, и если мы проверим внутри react-scripts/config/webpack.config.js, мы можно увидеть эти две babel-loader записи:

  1. В webpack.config.js#L396 есть babel-loader для include: paths.appSrc и для \.(js|mjs|jsx|ts|tsx)$/, которые addBabelPlugin добавить плагины для, с комментарием:

    // Process application JS with Babel.
    // The preset includes JSX, Flow, TypeScript, and some ESnext features.
    
  2. При webpack.config.js#L452 является babel-loader для /\.(js|mjs)$/ который addExternalBabelPlugin добавить плагины для, с комментарием:

    // Process any JS outside of the app with Babel.
    // Unlike the application JS, we only compile the standard ES features.
    

Мы хотим @babel/plugin-transform-typescript для применения к первой babel-loader относительно папки src приложения, поэтому мы должны использовать addBabelPlugin, которая применяется к этой конфигурации babel-loader.

Последнее, но Не в последнюю очередь, убедитесь, что вы обновили package.json сценарии для запуска с react-app-rewired:

"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"

Вы можете проверить очень простой проект CRA Typescript, используя класс из пространства имен здесь: https://github.com/clytras/cra-ts-namespaces

0 голосов
/ 22 апреля 2020

В моем конкретном случае причина, по которой я не мог заставить его работать, даже когда я следовал советам других, заключалась в следующем: в Babel есть ошибка, препятствующая слиянию enum и namespace. Этот код, например, не будет работать:

export enum Foo
{
    a, b, c, d
}

export namespace Foo
{
  export function bar()
  {
    return "bar"
  }
}

Но по какой-то странной причине Бабель выдает очень вводящую в заблуждение ошибку при обнаружении этого кода:

SyntaxError: script .ts: Пространство имен не помечено только для объявления типа. Не декларативные пространства имен поддерживаются только в Babel экспериментально. Чтобы включить и просмотреть предупреждения, см .: https://babeljs.io/docs/en/babel-plugin-transform-typescript

Я подал вопрос , так что, надеюсь, эта ошибка будет исправлена ​​в ближайшее время или, по крайней мере, получит достойную сообщение об ошибке. В то же время, можно использовать обход:

export enum Foo_
{
    a, b, c, d
}

export type Foo = Foo_

export namespace Foo
{
  export const a = Foo_.a
  export const b = Foo_.b
  export const c = Foo_.c
  export const d = Foo_.d
  export function bar()
  {
    return "bar"
  }
}
0 голосов
/ 18 апреля 2020

Использование переписывания для перезаписи Babel config Итак, выполните следующие действия:

  1. Создайте новое приложение с create-react-app my-app --template=typescript или используйте существующее
  2. Установите rescripts с npm i -D @rescripts/cli
  3. Заменить реагирующие сценарии рескриптами в package.json как в rescripts docs
  4. Установить плагин rescript для конфигурации babel @rescripts/rescript-use-babel-config
  5. Добавьте этот сниппер в ваш package.json файл
"rescripts": [
    [
        "use-babel-config",
            {
                "presets": [
                    "react-app",
                    [
                        "@babel/preset-typescript",
                        {
                            "allowNamespaces": true
                        }
                    ]
                ]
            }
        ]
    ]

В рескриптах будет использоваться плагин, который расширит конфигурацию babel. Мы расширяем стандартную конфигурацию babe для приложения-ответчика, чтобы ничего не нарушать. Затем мы перезаписываем предустановки (уже установленные в программе activ-app), но устанавливаем флаг allowNamespaces.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...