一次导入目录中的所有文件
一次导入目录中的所有文件
在ES6中,我可以像这样从一个文件中导入多个导出:\n
import {ThingA, ThingB, ThingC} from 'lib/things';
\n然而,我喜欢每个文件都有一个模块的组织方式。我最终会得到这样的导入:\n
import ThingA from 'lib/things/ThingA'; import ThingB from 'lib/things/ThingB'; import ThingC from 'lib/things/ThingC';
\n我希望能够这样做:\n
import {ThingA, ThingB, ThingC} from 'lib/things/*';
\n或者类似的方式,约定为每个文件包含一个默认导出,并且每个模块的名称与其文件相同。\n这种方式可行吗?
问题的原因是当前的解决方案只是一个变通方法,没有直接解决问题。因此,有人创建了一个babel
插件来解决这个问题。
解决方法是安装babel-plugin-wildcard
插件,并将其添加到.babelrc
文件中。这样做可以避免创建index.js
文件,并且在编译时进行,避免了在运行时进行readdir
操作。插件的详细安装信息可以在repo中找到。
使用这个插件可以实现以下功能:
import * as Things from './lib/things'; // Do whatever you want with these :D Things.ThingA; Things.ThingB; Things.ThingC;
使用新版本的插件,可以像下面的示例一样使用:
import { ThingsA, ThingsB, ThingsC } from './lib/things/*';
警告:这个插件可能会产生严重的问题。问题可能来自于它的内部缓存,当你将文件添加到./lib/things
中时,你的代码将是完美的,但你的脚本却无法正常工作。它会引起一些荒谬的问题。当我改变带有import *
的文件时,babel会选择添加的文件,但当我将它改回去时,问题又出现了,就像它重新使用了改变之前的缓存一样。请谨慎使用。
@ŁukaszZaroda 提到babel在~/.babel.json
中有一个内部缓存,这导致了这种奇怪的行为。此外,如果你正在使用观察器或热重载器,你必须保存新文件,以便它会被重新编译并生成新的目录列表。
还有其他人提到,如果遇到进一步的问题,可以使用bpwc clear-cache
命令来清除缓存,因为webpack和其他构建过程仍然会静默地缓存。
有人表示无法使其正常工作,可能是与他的flowtyped代码冲突,不确定。不管如何结构导入,他都会得到ReferenceError: Foo is not defined
的错误。他询问在哪里添加bpwc clear-cache
命令。
还有人表示这个插件对他来说工作得很好,babel-loader的版本是8.0.6。
问题:如何一次性导入目录中的所有文件?
原因:在使用ES6模块化语法时,想要一次性导入目录中的所有文件,但是直接导入目录无法解析到index.js文件。
解决方法:可以通过在目录中创建一个index.js文件,将所有文件的默认导出(使用export default)重新导出。然后在其他地方可以使用import * as 来一次性导入所有文件,或者使用import { }来选择性导入部分文件。以下是具体的操作步骤:
1. 在目录中的每个文件中,使用export default来默认导出内容。
2. 在目录下创建一个index.js文件,使用export {default as}来重新导出所有文件的默认导出。
3. 在其他地方,使用import * as 来一次性导入所有文件,例如import * as things from './things'。
4. 如果只需要选择性地导入部分文件,可以使用import { }来选择性导入,例如import {ThingA,ThingB} from './things'。
该方法可以解决一次性导入目录中所有文件的需求,并且在使用正确的语法和工具(如Babel)的情况下,可以实现树摇优化,只导入需要的文件,减少打包体积。但是需要注意的是,有些工具或环境可能无法正确解析这种语法,导致出现语法错误或打包结果不符合预期。在这种情况下,可能需要针对具体的工具或环境进行调整或寻找其他解决方案。
问题:如何一次导入目录中的所有文件?
原因:目前没有直接支持一次导入目录中所有文件的方法。
解决方法:可以创建一个中间的"module file",比如在`lib/things/index.js`中,文件内容如下:
export * from 'ThingA'; export * from 'ThingB'; export * from 'ThingC';
然后可以使用以下方式导入:
import {ThingA, ThingB, ThingC} from 'lib/things';
其他方法的尝试没有效果。
可以尝试使用`export * from`语法,比如使用`…from './ThingA'`或`export ThingA from …`。具体是否能够成功取决于所使用的模块加载器。
如果使用默认导出而不是从`ThingA`中导出`ThingA`,那么是否会导致问题?
当前使用的是每个`lib/things/ThingX.js`文件中的默认导出。这似乎是一种约定。当前使用的是iojs 1.7.1上的webpack。
如果每个`ThingA.js`、`ThingB.js`都导出了具名导出,那么原始的解决方案应该是有效的。
是否有现有的工具可以生成`index.js`文件?
可以使用GULP或作为NPM工具来实现。
是否需要指定`index.js`文件,还是只需要指定文件夹即可加载`index.js`?
这取决于所使用的模块加载器,但通常只需要指定文件夹路径即可。
在浏览器中是否可以正常运行?
目前浏览器还没有标准的模块支持。
ES6模块是否是ES6标准的一部分?
只有声明语法是ES6标准的一部分,加载和命名的方式不是。
如果使用`export * from 'ThingA'; export * from 'ThingB';`,如何从`lib/things/index.js`文件中导入`ThingA`和`ThingB`的默认导出?
如果它们是默认导出,需要给它们明确命名,因为星号导出不包括`default`,否则会导致`ThingA`和`ThingB`模块之间的冲突。如果同时有命名和默认导出,需要同时使用两种语法。
使用这种方法除了可读性之外还有其他好处吗?
这取决于与其他方法的对比。如果需要重命名特定的导出或者一次导入多个依赖项,使用中间模块文件会有帮助,但没有其他额外的好处。
在一个Svelte应用中,可以使用`{default as foo}`来清晰地解决问题。
这是一个清晰的问题,并且有一个与之匹配的清晰的答案。