Короткий ответ:
Настоятельно рекомендуется использовать явный импорт везде, где вам нужно, потому что такие инструменты, как webpack
, выполняют интеллектуальную оптимизацию размера пакета, удаляя неиспользуемые функции. Имея это в виду, самый короткий ответ таков: то, как вы используете webpack + babel + React, невозможно избежать определения imports
для каждого файла.
Более длинный ответ:
Да, вы можете это сделать, но это не так просто. В отличие от Ruby, поиск константы/переменной не работает так же, как в JavaScript. В Ruby отлично работает следующее:
# a.rb
A = 10
# b.rb
require "./a.rb"
puts a # => 10
Это связано с тем, что когда файл a.rb
анализируется и включается в b.rb
, в Ruby не создается дополнительного подпространства имен. Все единицы верхнего уровня существуют так, как если бы они были определены внутри b.rb
. Подробнее об этом< /а>
Чтобы сравнить это с JS, мне нужно немного прояснить, как работает включение модулей. На данный момент довольно сложная ситуация. Давайте сначала рассмотрим NodeJS. В этой небраузерной среде еще не реализована функциональность import
, за исключением самых передовых версий с дополнительными флагами (v 9 на сегодняшний день). Поэтому, когда вы используете что-то вроде webpack
и import
, внутри происходит то, что они преобразуются в собственную прокладку require
webpack. И способ преобразования import
и require
немного отличается, потому что первый является "статическим" загрузчиком стиля, а второй - динамическим загрузчиком стиля. На самом базовом уровне это означает, что операторы import
должны быть вверху файла, а операторы require
могут быть где угодно, и разрешение файла происходит, когда интерпретатор встречает эту строку. Это имеет странные эффекты, как вы увидите ниже.
Способ работы NodeJS require
заключается в идентификации объекта module.exports
из включенного файла. Этот объект указывает, какие функции/объекты доступны снаружи. Следовательно, в отличие от Ruby, уже существует неявное локальное пространство имен (или группировка, если хотите) module.exports
вместо глобального $LOADED_FEATURES
:
// a.js
const a = 10;
module.exports = { a: a };
// b.js
const a = require('./a.js');
console.log(a); // { a: 10 };
Один из способов обойти это — глобальные переменные. Как и в Ruby, в JavaScript есть неявное глобальное пространство имен, особенно часто встречающееся в браузерах через window
и global
в NodeJS. Одна идея заключается в следующем:
// main.js
import React from 'react';
import ReactDOM from 'react-dom';
import Image from 'components/image.js';
import Gallery from 'components/gallery.js';
window.React = React;
window.ReactDOM = ReactDOM;
window.Image = Image;
window.Gallery = Gallery;
// gallery.js
export default class Gallery extends React.Component {
render() {
return <Image />;
}
}
Однако это не работает. Чтобы эмулировать реальную функциональность ES6 import
, которая представляет собой статически определенный набор файлов и функций, webpack пытается эмулировать их с помощью собственной функции require
webpack. И это не делает глобально присоединенные константы доступными к моменту выполнения импорта. Таким образом, чтобы заставить это работать, можно использовать более старую загрузку в стиле require
, которая изменяет способ работы собственной функции require
webpack. Изменив вышеуказанное на:
// main.js
const React = require('react');
const ReactDOM = require('react-dom');
window.React = React;
window.ReactDOM = ReactDOM;
const Image = require('components/image.js').default;
const Gallery = require('components/gallery.js').default;
window.Image = Image;
window.Gallery = Gallery;
// gallery.js
export default class Gallery extends React.Component {
render() {
return <Image />;
}
}
Как видите, это слишком много работы, чтобы запустить приложение JavaScript. Но основная проблема заключается в том, что веб-пакет не может выполнять интеллектуальную оптимизацию, потому что он не знает, какие функции вы не используете. Так что лучше всего этого не делать.
person
Kashyap
schedule
07.11.2017