简短的回答:
强烈建议在您需要的任何地方使用显式导入,因为诸如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
实现任何功能,除了带有额外标志的前沿版本(截至今天为 9)。所以当你使用类似webpack
andimport
的东西时,内部发生的事情是这些被转换为 webpack 自己的require
shim。并且转换的方式略有不同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 />;
}
}
但是,这不起作用。为了模拟实际的 ES6import
功能——这是一组静态定义的文件和函数,webpack 尝试通过 webpack 自己的require
函数来模拟它们。这不会使全局附加的常量在导入完成时可用。因此,要实现这项工作,一种解决方法是使用旧require
样式加载,这会改变 webpack 自己的require
函数的工作方式。通过将上述更改为:
// 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 应用程序运行起来,工作量太大了。但是主要的问题是 webpack 不能做任何智能优化,因为它不知道你没有使用哪些函数。所以最好避免做这一切。