asakasinsky
@asakasinsky

Почему в продакшн-версии react-приложения getElementById() может возращать null?

Почему в продакшн-версии react-приложения getElementById() может возращать null, в то время как querySelector отрабатывает корректно?

В простом примере всё ок. Внешний скрипт подгружается, getElementById и querySelector возвращают то, что нужно:
https://codepen.io/asakasinsky/pen/MEydXg

Но после сборки react-приложения я столкнулся со странным поведением:
getElementById начал возвращать null.

Появилась ошибка, проверив которую я и обнаружил что в ReactDOM.render передаётся null вместо элемента-контейнера приложения
ReactDOM.render(
        <AppContainer errorReporter={Redbox}>
            <Root store={store} history={history}/>
        </AppContainer>,
        document.getElementById('app')
    );


Для проверки в самом начале index.js, перед импортами, вызовом метода render() разместил следующий код:

document.addEventListener('DOMContentLoaded', function () {
    console.log('loaded');
    console.log('querySelector after load', document.querySelector('#app'));
    console.log('getElementById after load', document.getElementById('app'));
});

console.log('querySelector', document.querySelector('#app'));
console.log('getElementById', document.getElementById('app'));


Вывод консоли:
2a74e6457ea640f7a8fcdccce386f861.png

Как видно, поведение getElementById не зависит от события DOMContentLoaded
Ошибка «Cannot read property 'sidebarIsOpen' of undefined» возникает ровно по той же причине.

Думаю над этой интересной задачкой, и подозреваю, что виной тому какая-то из библиотек.
Может кто-то сталкивался с этим?
  • Вопрос задан
  • 433 просмотра
Решения вопроса 1
asakasinsky
@asakasinsky Автор вопроса
Всё оказалось прозаичнее. Причиной послужил используемый в сборщике плагин gulp-rev-all. Ниже кусок кода из сборщика:

gulp.task('build:revAssets', ['css', 'moveAssets'], function () {
    var rev = $.revAll;
    return gulp.src('./public/assets/**/*')
        .pipe(rev.revision({
            fileNameManifest: 'manifest.json'
        }))
        .pipe(gulp.dest('./public/assets'))
        .pipe(rev.manifestFile())
        .pipe(gulp.dest('./public/assets'))
})


Теперь, результат сборки тестового файла (результат отформатирован для удобства):
! function(modules) {
    function __webpack_require__(moduleId) {
        if (installedModules[moduleId]) return installedModules[moduleId].exports;
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: !1,
            exports: {}
        };
        return modules[moduleId].call(module.exports, module, module.exports, __webpack_require__), module.l = !0, module.exports
    }
    var installedModules = {};
    __webpack_require__.m = modules, __webpack_require__.c = installedModules, __webpack_require__.d = function(exports, name, getter) {
        __webpack_require__.o(exports, name) || Object.defineProperty(exports, name, {
            configurable: !1,
            enumerable: !0,
            get: getter
        })
    }, __webpack_require__.n = function(module) {
        var getter = module && module.__esModule ? function() {
            return module.default
        } : function() {
            return module
        };
        return __webpack_require__.d(getter, "a", getter), getter
    }, __webpack_require__.o = function(object, property) {
        return Object.prototype.hasOwnProperty.call(object, property)
    }, __webpack_require__.p = "/assets/", __webpack_require__(__webpack_require__.s = 0)
}


([function(module, exports, __webpack_require__) {
    module.exports = __webpack_require__(1)
}, function(module, exports, __webpack_require__) {
    "use strict";
    console.log("querySelector", document.querySelector("#app")), console.log("getElementById", document.getElementById("app.14b3524f"))
}]);


Обратите внимание на:
console.log("getElementById", document.getElementById("app.14b3524f"))


Как видно, «app» был сборщиком/плагином переименован в «app.14b3524f».

Вот и всё! Спасибо, тем, кто пытался помочь!

P.S. Поведение плагина описано тут
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
HalfBloodPrince
@HalfBloodPrince
Front-End Developer
В вашей ссылки JS кода нет, но я б предложил использовать ref (посмотрите документацию), а также поместить этот код в componentDidMount, один из lifecycle методов.
Ответ написан
victorzadorozhnyy
@victorzadorozhnyy
Вы точно JS подключаете после div?
Ответ написан
SPAHI4
@SPAHI4
реактовцы - это не девы, а прокидыватели пропсов
На скриншоте вижу аттрибут async. Поробуйте заменить на defer
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы