Как mocha / babel переносит мой тестовый код на лету?

Мой вопрос не в том, почему что-то не работает, а в том, почему это не работает. да.

У меня есть небольшой инструмент командной строки nodeJS, который содержит функции, которые nodeJS еще не поддерживает из коробки, в частности:

  • import заявления
  • String.includes().

Таким образом, для доставки (сборки) я транспилирую + связываю свой исходный код (используя посылка, как и webpack).

Как положительное чудо, все (кроме одного) мои тесты мокко запускают напрямую для моих классов, а не для пакета. Тем не менее, они работают! Включая множество заявлений import. И включая «самопроверку ES6»:

it( 'String - include', () => {
    var s = 'Southern Bananas'
    assert( s.includes( 'anana' ) )
    assert( !s.includes( 'kiwi' ) )
} )

Таким образом:

У меня есть String.include в моем тестовый код, а не только в тестируемом источнике. И нет места, куда бы я перекомпилировал или связал свой тестовый код ... Приношу свои извинения за мой глупый вопрос:

Почему это работает? Есть ли где-нибудь секретная своевременная компиляция? (и если да, могу ли я использовать это для отладки моего тестируемого кода?)

мои mocha.opts довольно просты:

--require @babel/register
--require ./test/once.js  (nothing special here, either)
--reporter list
--recursive

у моего .babelrc есть это:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "Electron": "3.0",
                    "Node": "8.0"
                }
            }
        ]
    ],
    "plugins": [
        "@babel/plugin-transform-runtime"
    ],
    "retainLines": true,
    "comments": false,
    "sourceMaps": true
}

@babel/plugin-transform-runtime видимо не на похвалу обвинять, так как это прямо заявляет

NOTE: Instance methods such as "foobar".includes("foo") will not work since that would require modification of existing built-ins (you can use @babel/polyfill for that).

Содержится ли @babel/polyfill в минималистик-модерн afaik @babel/preset-env? Что еще я делаю правильно: +)? Есть ли способ использовать эту живую компиляцию и для моей (отладочной) сборки?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
2 018
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Короче говоря

String.prototype.includes поддерживается Node.js начиная с версии 6.5. @babel/register заставляет ваш код компилироваться на лету, поэтому ваши операторы import работают. Я сомневаюсь, что вам нужен плагин @babel/plugin-transform-runtime, если только я не упускаю то, чего вы пытаетесь достичь.

Что может вызвать эту путаницу?

Я думаю, что у этой (вполне понятной) загадки есть две основные причины:

  1. Авторы Babel сделали В самом деле простым в использовании инструмента; и иногда трудно понять, как и когда он вызывается (особенно в сочетании с другим инструментом, таким как Mocha).
  2. За тем, что изначально поддерживается / не поддерживается Node.js (с точки зрения ES2015, ES2016 и т. д.), Традиционно было трудно угнаться.

Итак, перейдем к двум загадкам.

Почему работает String.prototype.includes?

У этого есть более простое объяснение. String.prototype.includes изначально поддерживался еще в Node.js v6.5 (как вы видете, подавляющая часть поддержки ES2015 поддерживается с этой версии).

Итак, хотя вы правы, у вас нет настроенного @babel/polyfill (насколько я могу судить) и что он вам нужен было бы в среде, которая не поддерживает String.prototype.includes, ваша среда уже поддерживает это!

Из реплики Node.js v8.x:

> 'ES2015'.includes('2015')
true

Почему ваша инструкция import работает?

Как вы сказали, Node.js v8.x не поддерживает модули ECMAScript. Однако есть несколько хороших отзывов о том, как это было включено в качестве экспериментальной функции начиная с Node.js v9.x.

Итак, с собственным Node.js v8.x (через REPL) вы получаете следующее:

> import path from 'path';
import path from 'path';
^^^^^^

SyntaxError: Unexpected token import

Причина, по которой ваш импорт работает, заключается в том, что ваш код компилируется Babel с использованием предустановки @babel/preset-env. Более того, эта компиляция запускается вашей опцией --require @babel/register Mocha.

@babel/register работает, "привязывая себя к требованию узла и автоматически компилируя файлы на лету".

Вот базовый пример @babel/register в действии:

Из командной строки:

$ node main.js
You will see this, because there is no syntax error!

main.js

require('@babel/register');
// This next file is compiled on the fly
require('./file1.js');

file1.js

import path from 'path';
console.info('You will see this, because there is no syntax error!');

Хорошо, что именно так Mocha рекомендует интегрировать Babel в их документации. Параметр --require в основном выполняет то же действие, что и в приведенном выше примере: require('@babel/register'); вызывается до того, как Mocha использует require для импорта всех ваших тестовых файлов.

Надеюсь это поможет! Опять же, это совершенно понятная загадка в современную эпоху быстро развивающегося JavaScript.

Спасибо! Приводит ли эта компиляция на лету к временным файлам в какой-то «скрытой» папке? Или все это в памяти? - А можно ли запустить мой сам инструмент командной строки напрямую с компиляцией «на лету»? (не для «релиза», а для разработки, естественно ...)

Frank Nocke 03.01.2019 11:45

Насколько мне известно, @babel/register компилируется в памяти. Но он поддерживает кеш по умолчанию. Это кеш загружается в память при запуске. Интерфейс командной строки Babel, предназначенный только для разработки, - @babel/node. Он действует так же, как CLI узла, за исключением того, что он компилирует файл перед выполнением. Может, тебе это пригодится? Или интегрируйте @babel/register в точку входа вашего интерфейса командной строки.

Matt Kahl 04.01.2019 00:53

Ха! «Производственное предупреждение» babel/node на самом деле говорит мне именно то, о чем я спрашивал ?: «Вы не должны использовать babel-node в продакшене. Это неоправданно тяжело ... из-за того, что кеш хранится в памяти. Вы также всегда будете испытывать снижение производительности при запуске, поскольку все приложение необходимо компилировать «на лету». «- использовать (/ w + w / o npx) в этом ТАК ответе

Frank Nocke 06.01.2019 08:53

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