Обнаружение разработки React / ReactDOM / производственной сборки

Сборка разработки React ведет себя не так, как производственная сборка, например обработка ошибок.

Определить, какой из них используется, можно из среды, но только в модульной среде из-за того, как process.env.NODE_ENV используется пакетом React:

if (process.env.NODE_ENV === 'production') {
  module.exports = require('./cjs/react.production.min.js');
} else {
  module.exports = require('./cjs/react.development.js');
}

Случай, когда process.env может быть неприменимым, - это React, используемый глобально как модуль UMD, window.React и window.ReactDOM:

<script src = "some-unknown-react-version.js"></script>

<script>
React // is it in production mode?
</script>

Возможные варианты использования:

  • компонент, который может работать в модульных и глобальных средах (опубликован как UMD) и по-разному отображается в производственной среде

  • расширение браузера или пользовательский скрипт, в котором режим сборки / производства определяется из объекта React или ReactDOM

Как можно точно определить сборку разработки / производства React во время выполнения, не обращаясь к среде?

Я ищу надежное и чистое решение, которое было бы применимо к React 15 и React 16, если это возможно.

Это не дубликат подобных вопросов, потому что существующие ответы решают проблему через process.env.

Как выглядит ваша установка развертывания? Не существует «правильного» способа делать то, что вы хотите. Я бы сосредоточился на различиях между производственной / развивающейся сборкой и создал свою собственную вспомогательную функцию. Посмотрите мой ответ о типах опор.

Michal 16.10.2018 19:57
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
20
1
7 759
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

React предоставляет как разрабатываемую, так и производственную версию ссылок на react.js:

Разработка:

<script crossorigin src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

Производство:

<script crossorigin src = "https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

источник


И чтобы узнать, находится ли он в режиме разработки или в рабочем режиме без переменной окружения, вам нужно прямо заявить некоторой переменной, назначив ее режим: (включите следующий сценарий вместе со сценарием реакции)

<script>
var devMode = 'development';
</script>

и при необходимости проверяйте devMode.


В качестве альтернативы вы можете проверить его режим, например: (вы должны добавить идентификатор в тег скрипта)

var script_id = document.getElementById('script-attached-id');
console.info(script_id.getAttribute('src').includes('development'));

Таким образом, вам нужно только обновить исходный путь и определить режим.


И последний вариант, я могу подумать о чтении самого файла и обнаружении его режима, поскольку в своем комментарии response упомянул, например:

Разработка:

/** @license React v16.5.2
 * react.development.js

Производство:

/** @license React v16.5.2
 * react.production.min.js

Итак, после прочтения файла просто проверьте его режим во второй строке. Или вы можете протестировать react.development.js без построчной проверки.

Это правда. Поэтому в вопросе я указал дополнительные условия. какой-то-реагировать-версия.js - по URL невозможно определить, какая это сборка (разработка, продакшн). компонент, который по-разному отображается в производственной среде, независимо от модульной или глобальной среды - компонент не должен знать конкретный тег <script>.

Estus Flask 08.10.2018 14:43

Чтобы пояснить, я спрашиваю с точки зрения разработчика, поскольку у меня нет переменной devMode для проверки и у меня есть доступ к объектам React и ReactDOM, ни к чему другому. Это может быть расширение для браузера, которое я пишу. Или библиотеку React, в которой мне нужно определить режим производства React, но я не хочу ограничивать использование библиотеки в модульных средах с помощью process.env. Вопрос в том, как определить сборку без использования process.env.

Estus Flask 08.10.2018 15:03

Здесь нет пути. Вы должны явно установить некоторую переменную.

Bhojendra Rauniyar 08.10.2018 15:04

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

Estus Flask 08.10.2018 15:06

Обнаружение сборки dev / production на клиенте с использованием сборки umd кажется долгим. Если такое требование существует, почему бы не создать свое приложение с create-react-app?

Я не должен судить о ваших решениях, так что вот вам кое-что полезное.

Плагин react-dev-tools, предоставляемый facebook, определяет тип сборки.

Вот соответствующая часть вышеупомянутого плагина:

https://github.com/facebook/react-devtools/blob/faa4b630a8c055d5ab4ff51536f1e92604d5c09c/backend/installGlobalHook.js#L23

Надеюсь, ты сможешь сделать это полезным.

Спасибо! Я не смотрел на DevTools, потому что не ожидал, что они сделают что-то подобное; они просто зависали в случае производственной сборки без полезного сообщения. Пожалуйста, подумайте о том, чтобы разместить соответствующий код из ссылки на ответ, чтобы его можно было понять, не посещая сторонние ресурсы. Да, решение кажется слишком хакерским, чтобы использовать его в обычных компонентах.

Estus Flask 13.10.2018 22:14

Код ReactDOM содержит перехватчик для React Dev Tools, поэтому этот хак недоступен. Лучшее решение - добавить соответствующие типы пакетов в сам React / ReactDOM.

Dolf Barr 16.10.2018 20:30

Основной целью вопроса было понимание типа сборки с использованием плагина Google Chrome, как помочь разработчику собирать данные?

AmerllicA 16.10.2018 23:03

Я говорю о решении в этом ответе: React Dev Tool содержит функцию, которая определяет тип сборки React, но она работает, потому что библиотека ReactDOM содержит перехватчик для React Dev Tool и запускается на ReactDOM init. Итак, если библиотека ReactDOM может содержать перехватчик для React Dev Tool, тогда она может содержать тип сборки, и лучшим решением является создание запроса на перенос с надлежащей функциональностью.

Dolf Barr 16.10.2018 23:40

@DolfBarr Я согласен с тем, что наличие этой функции в самом ReactDOM может быть полезно. Тем не менее, можно использовать тот же метод для подключения к REACT_DEVTOOLS_GLOBAL_HOOK в обычном скрипте, независимо от React Dev Tool. Я бы не стал использовать его в обычном компоненте, но может быть полезен для других целей (расширение браузера или пользовательский скрипт).

Estus Flask 17.10.2018 01:04

Есть небольшой «прием», с помощью которого можно проверить, какая версия React была загружена.

Объект React доступен в глобальных переменных, и производственная сборка React отличается от версии для разработки по крайней мере в одном: она обычно минифицирована. Таким образом, мы можем попытаться проверить, работаем ли мы с уменьшенной версией или нет.

Чтобы проверить, вы можете сравнить имя функции с именем свойства некоторого метода объекта React, например:

let func = 'Component'
if (React[func].name === func) {
  // non-minified -> development build
}

Этот метод предназначен не для проверки производства и разработки, а для проверки минификации, и, поскольку производственная сборка обычно минифицирована, это действительно может помочь.

К сожалению, это приведет к ложноотрицательным результатам из-за уменьшенного! == production. Что касается меня, я обычно использую минимизированный код в разработке. Я бы использовал это только как запасной вариант для проверки process.env.NODE_ENV.

Estus Flask 16.10.2018 19:47

Как выглядит ваша установка развертывания? Не существует «правильного» способа делать то, что вы хотите. Я бы сосредоточился на различиях между производственной / развивающейся сборкой и создал свою собственную вспомогательную функцию.

Обновлено: Похоже, что невозможно определить версию prod / dev из класса React.

Две идеи:

  1. Я не уверен, как создано приложение, но PropTypes должен быть хорошим идентификатором ENV.
  2. Если ваше производственное приложение React минимизировано, вы можете просто определить, минимизирован ли код реакции. (это будет взломано, но должно работать, сосредоточьтесь на количестве пробелов или длине строки, ...)

Я заметил в комментариях ниже, что вы говорите, что minified !== production, если вы можете сделать это таким образом, то это, вероятно, ваш лучший выбор. В любом случае вам не нужно минимизировать код реакции разработки.

Я ценю это предложение. Моя установка развертывания не имеет значения на данном этапе, потому что вопрос в первую очередь относится к моему коду, который будет работать вместе с чужим приложением. См. «Возможные применения».

Estus Flask 16.10.2018 20:05

@estus Я только что обновил свой ответ. Я как бы надеялся, что будет какой-то React.method, который будет отсутствовать в производственной сборке, но похоже, что это не так. Я бы сосредоточился на том, чтобы определить, минимизирован ли код реакции или нет.

Michal 16.10.2018 20:18

В «возможных вариантах использования» минимизация моего собственного кода не имеет значения. Для расширения браузера минификация ни на что не влияет. Для библиотеки компонентов важна настройка разработчика, который использует мою библиотеку, а не мою. Другой ответ уже предлагал минификацию, я прокомментировал это. Это можно использовать, но ненадежно, и это имеет смысл только в немодульной среде, где React является глобальным. Да, искал такой React.method, но последовательного пути нет. Код React devtools, связанный с другим ответом, показывает, что это возможно, но взломано.

Estus Flask 16.10.2018 20:23

@estus Не драться здесь, но не использовать переменные env - это хитрость. : D

Michal 16.10.2018 23:07

Как я уже сказал, компонент можно использовать в глобальной среде без process.env, потому что в базовых настройках разработчики могут пропустить этап сборки. Я хотел выяснить свои варианты, прежде чем жестко закодировать его для process.env. Похоже, демонстрация опоры productionMode была бы подходящим решением для таких случаев.

Estus Flask 16.10.2018 23:12

Ваш вопрос ясен, но вы не уточняете свою систему сборки, вы используете webpack или parcel? у тебя есть Server Side Rendering или нет? вы запускаете созданное вами приложение с помощью node или pm2? или вы просто создаете свое приложение, а затем помещаете на свою страницу встроенный связанный файл, созданный с помощью других технологий, таких как PHP или C#?

Собственно, ответы на приведенные выше вопросы могут определить ваш ответ, но вы наверняка используете сборщик модулей, поэтому я предлагаю использовать разрешение файла config в вашем проекте.

Если бы я был на вашем месте, я бы, несомненно, использовал webpack, два файла конфигурации webpack, один для разработки и один для производственного режима. затем я создаю папку, содержащую два файла с config.dev.js и config.prod.js. В веб-пакете разработки:

~~~
module.exports = {
        ~~~
        resolve: {
            extensions: ['.js', '.jsx'],
            alias: {
                ~~~
                Config: `${srcDir}/config/config.dev.js`,
                // srcDir is a defined variable for source directory
            }
        },
        ~~~

В производственном веб-паке:

~~~
module.exports = {
        ~~~
        resolve: {
            extensions: ['.js', '.jsx'],
            alias: {
                ~~~
                Config: `${srcDir}/config/config.prod.js`,
                // srcDir is a defined variable for source directory
            }
        },
        ~~~

И теперь вы можете поместить данные каждого dev и prod для ваших типов сборки. например в вашем config.dev.js можно написать:

module.exports = {
    buildType: "dev"
};

Наверняка в вашем config.prod.js можно написать:

module.exports = {
    buildType: "prod"
};

Абсолютно вы можете получить доступ к данным конфигурации с помощью кода ниже внутри ваших файлов react:

import config from 'Config';

И с помощью этого решения вы можете понять тип вашей сборки при выполнении вашего приложения в реальном времени.

Примечание: Для получения дополнительной информации вы можете увидеть мой средняя статья, и если вы не знакомы с длинными чтениями, посмотрите статью хранилищеТакже более новую версию примера моего ответа хранилище, который содержит конфиги.

Как я объяснил в комментариях, моя собственная настройка сборки не имеет значения. См. «Возможные варианты использования» в вопросе. Например. Компонент встроен в UMD и может использоваться третьей стороной. Я не отвечаю за создание всего приложения, только его часть, которая должна проверять, является ли это средой разработки или производственной средой.

Estus Flask 17.10.2018 00:06

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

AmerllicA 17.10.2018 05:33

Я не знаю, как мне это использовать. Мне нужно определить среду, в которой используется связанный компонент, а не мою собственную среду. Попробую объяснить. Решение не может быть принято в то время, когда я создаю компонент. Если я связываю компонент как UMD с настройкой «производство», а затем разработчик использует его в среде разработки, это считается средой разработка, и это то, что я пытаюсь обнаружить из объекта React.

Estus Flask 17.10.2018 17:05

Некоторые коснулись использования того факта, что производство всегда будет минимизировано, а разработка не будет минимизирована. Вот конкретное решение, в котором это используется:

<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>

<script>
const reactInfo = {
    version: React.version,
    development: (String((new React.Children.map()).constructor).length > 100)
};
console.info(reactInfo);
</script>

<div id = "content"></div>

Я тестировал это примерно на дюжине версий реакции от v14 до v16. Из здесь вы можете видеть, что этот код не был затронут с тех пор, как он был впервые написан, за исключением одного небольшого изменения, сделанного год назад (что не повлияет на этот ответ, потому что в нем слишком мало символов, хотя я тестировал версии до 11 мес. в любом случае назад и есть приличный разрыв).

Примечание

Dev - это 200 символов, а Prod - 70, поэтому соотношение символов Dev: Prod составляет 3: 1. Я выбрал 100, потому что добавление 90 символов кода добавит 30 строк к продукту, поэтому 100 - лучшее место с предоставленной информацией (технически ~ 105 или что-то в этом роде). Добавление 90 символов или удаление 100 символов крайне маловероятно для такой простой функции (функция, которая затрагивалась только один раз в 5 лет при редактировании 20 символов), поэтому я думаю, что это должно быть стабильно.

Для большей стабильности или, по крайней мере, знания, если он сломается, вы можете проверить, находится ли он в пределах 25 символов от 70 до 200, и выдать ошибку, если это не так. Это должно уловить любые большие изменения (я бы дал этому параметру почти 100% уверенность, что он никогда не скроет ошибку), но вы можете получить ложные срабатывания. Какой из них вам нужен, зависит от вашего варианта использования.

Обновлено:

Что касается минимизации, это регулярное выражение, которое определяет, была ли функция минимизирована, поэтому вы можете безопасно использовать его. Он также выйдет из строя, если React.Children.map не является функцией (почти наверняка никогда не произойдет), что вы можете либо поймать, либо не уловить в зависимости от того, насколько строго вы хотите обработать маловероятное событие ошибки (или просто проигнорируйте его, например, зачем им вообще это менять). Сигнатура функции остается, даже если она минифицирована в [native code], так что это скорее ориентировано на будущее, imo. Хотя для простоты я бы выбрал первый.

const reactInfo = {
    version: React.version,
    development: !/function\s?\w?\(\w(,\w)*\)/.test(String((new React.Children.map()).constructor).split("{")[0])
};

Спасибо. Очень хакерский и хрупкий, но может помочь при тщательном тестировании с будущими версиями.

Estus Flask 17.10.2018 00:48
Ответ принят как подходящий

Есть разница. В режиме разработки для элементов React определено свойство _self, тогда как в производственном режиме это свойство не определено.

Итак, решение состоит в том, чтобы проверить это свойство с помощью такого кода:

function ReactIsInDevelomentMode(){ 
    return '_self' in React.createElement('div');
}

не могли бы вы предоставить URL-адрес документации React, подтверждающий то, что вы утверждаете?

lmiguelvargasf 25.07.2020 07:11

@lmiguelvargasf Это поведение не задокументировано создателями React. Я заметил это.

Constantin Galbenu 04.09.2020 13:41

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