Я работаю над проектом, состоящим из трех частей: клиент, сервер и общий каталог, который содержит вещи, которые я хочу импортировать как с клиента, так и с сервера. Все может использовать как JS, так и TS. (Благодаря пресету babel-typescript
)
Структура каталогов
Вот как это выглядит:
root/
├── babel.config.js
├── Common/
│ ├── helper1.ts
│ ├── helper2.ts
│ ├── helper3.js
├── Client/
│ ├── src/
│ │ └── file1.js
│ └── .babelrc.js
└── Server/
├── src/
│ └── file1.js
└── .babelrc.js
Файлы конфигурации Babel
Вот как выглядит мой root/babel.config.js
:
module.exports = {
presets: ["@babel/preset-typescript"],
plugins: [
["@babel/plugin-transform-for-of", { assumeArray: true }],
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings",
["@babel/plugin-proposal-decorators", { legacy: true }],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions",
"@babel/plugin-proposal-export-default-from",
"@babel/plugin-proposal-logical-assignment-operators",
"@babel/plugin-proposal-optional-chaining",
["@babel/plugin-proposal-pipeline-operator", { proposal: "minimal" }],
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-do-expressions",
"@babel/plugin-proposal-function-bind",
],
};
А вот как выглядит мой Server/.babelrc.js
:
const moduleAlias = require("./tools/module-alias");
const rootConfig = require("../babel.config");
module.exports = {
presets: [
...rootConfig.presets,
[
"@babel/preset-env",
{
targets: {
node: "current",
},
exclude: ["transform-for-of"],
},
],
],
plugins: [
...rootConfig.plugins,
[
"babel-plugin-module-resolver",
{
root: ["."],
alias: moduleAlias.relativeAliases,
extensions: [".js", ".ts"],
},
],
],
};
Я пропущу Client/.babelrc.js
, так как он очень похож на серверный.
Базовые тестовые файлы
Вот пример файла Common/helper3.js
:
function doubleSay(str) {
return `${str}, ${str}`;
}
function capitalize(str) {
return str[0].toUpperCase() + str.substring(1);
}
function exclaim(str) {
return `${str}!`;
}
const result = "hello" |> doubleSay |> capitalize |> exclaim;
console.log(result);
А внутри Server/src/index.js
я просто импортирую файл Common/helper3.js
.
Ошибка
Затем внутри каталога Server
я делаю следующее:
npx babel-node src/index.js -x .ts,.js
Что печатает следующую ошибку:
const result = "hello" |> doubleSay |> capitalize |> exclaim;
^
SyntaxError: Unexpected token >
Я определенно уверен, что эта ошибка связана с моей «странной» структурой каталогов, поскольку это нормально, когда я помещаю именно этот файл под Server/src
.
Вопрос
Как я могу сохранить эту структуру каталогов и указать Babel использовать конфигурацию при обработке файлов в каталоге Common
?
Я не использую Lerna или что-то в этом роде. Я установил специальные псевдонимы, которые преобразуют $common
в ../Common
там, где это необходимо. Я знаю, что с этим нет проблем, так как файл правильно найден Babel (в противном случае я получил бы ошибку «Файл не найден»)
Примечание
Эта структура babel
— одна из моих попыток решить описанную выше проблему. Изначально у меня был только один babel.config.js
внутри Server
, а другой внутри Client
. Я думал, что наличие одного в корне решит эту проблему, но это ничего не изменило.
Изменить после поиска намного больше:
Взглянув на код Babel, чтобы найти синтаксический анализ конфигурации, я заметил, что эта строка: /config-chain.js#L456" rel="nofollow noreferrer">https://github.com/babel/babel/blob/8ca99b9f0938daa6a7d91df81e612a1a24b09d98/packages/babel-core/src/config/config-chain.js#L456< /a> (возвращается null
).
Я напечатал все в этой области и заметил, что babel автоматически генерирует параметр only
, содержащий cwd. (Эффективно говоря, что мой babel.config.js
не влияет на мой каталог common
, несмотря на то, что он находится «выше» в иерархии каталогов).
Я решил попробовать перегрузить его в командной строке и получил эту команду:
npx babel-node src/index.js --root-mode upward -x .ts,.js --only .,../Common/ --ignore node_modules
(Добавлены --only
и --ignore
)
Это помогло мне немного продвинуться вперед: вместо того, чтобы не разобрать расширенный синтаксис (оператор конвейера) в файлах js, он потерпел неудачу при сбое ts, говоря
export const accountStatus = Object.freeze({
^^^^^^
SyntaxError: Unexpected token export
Чего я не понимаю, так это того, как он может анализировать оператор конвейера, но не файл машинописного текста, хотя и плагин конвейера, и машинописный текст находятся внутри одного и того же babel.config.js
Изменить после решения этой последней проблемы:
Добавление --only
и --ignore
помогло. Другая проблема заключалась в том, что я забыл добавить плагин @babel/plugin-transform-modules-commonjs
, и он не смог разрешить импорт.
Небольшое изменение, которое я сделал, заключалось в добавлении ignore: ["**/node_modules"],
к моему корневому файлу babel.config.js
и изменении моей команды для использования этих аргументов: --root-mode upward -x .ts,.js --ignore __fake__
.
Добавления случайного --ignore
достаточно, чтобы babel
не угадывал сам по себе.
Это решение, которое я использую, и оно отлично работает, хотя и не очень элегантно.