英文:
Browser and Node import statement incompatibility
问题
在Node中,可以以多种方式对require()
语句进行条件化处理,例如将它们放在if
或其他条件语句中,使用?:
来指定需要引用的目标,或者将它们放在在条件情况下调用的函数中。相比之下,import
语句没有这种灵活性。因此,如果我有一个模块,当在Node上运行时将引用一个文件,但在浏览器中以不同的方式运行时,我不能执行类似于const fs = inBrowser ? null : require("fs");
的等效操作。
那么,当需要这种条件性时,如何在Node和浏览器中使用模块呢?
另外,在Node中,require()
和import
语句通常使用相对路径。在浏览器中,似乎是使用绝对URL的规范。那么,我是否可以在浏览器中使用类似于import { x } from "./specialPlace/mod2.mjs";
这样的方式来导入位于URL /assets/mod1.mjs
的模块,或者每个import
都必须是绝对路径?如果我们在浏览器中这样做,那么在Node中将无法正常工作,因为除了类似于/usr/person/...
之类的绝对路径之外,绝对路径在浏览器中无法使用。
英文:
In Node, one can conditionalize require()
statements in several ways -- put them inside if
or other conditional statements, use ?:
for the target to be required, put them in a function that is conditionally called. By contrast, import
statements have no such flexibility. So, if I have a module that will that will refer to a file when running on Node but will work in a different way when running in the browser, I cannot do anything equivalent to const fs = inBrowser ? null : require("fs");
So, how does one use a module in Node and also in the browser when such conditionality is needed?
Also, require()
and import
statements within Node commonly use relative paths. In the browser, it seems the norm (the requirement?) is to use absolute url's. So, can I have a module, say at the url /assets/mod1.mjs, import another module with something like import { x } from "./specialPlace/mod2.mjs";
and have that work in the browser, or must every import
be an absolute path? If we do that for the browser, it won't work in Node since there is not root from an absolute path other than something like /usr/person/...
and that won't work in the browser.
答案1
得分: 1
要像require
一样按需使用import
,可以将其作为一个函数调用。这被称为动态导入。返回导入模块的 Promise(模块实例)。通常与之一起使用await
。在模块的顶层也支持不带async
的await
。
现在我推荐在 Node.js 中也使用 ESM,并从require
迁移。许多 NPM 模块的最新版本已放弃对 CommonJS 的支持,转而支持 ESM。
<script type="module" src="main.js"></script>
main.js
const {default: myModule} = doINeedModule ? await import('myModule') : {default: null};
此外,管理、捆绑和解析裸模块和文件系统导入是由打包器完成的。如果目标是浏览器,不使用打包器就像还停留在石器时代一样。
我推荐使用 Vite。通过插件,甚至可以不用操心导入任何东西,这将自动完成。您可以编写自定义的裸模块和文件系统解析器,可能性是无限的。甚至可以按文件名模式导入模块:https://vitejs.dev/guide/features.html#glob-import
英文:
To use import
on demand like require
you can call it as a function. It's called dynamic import. Returns a promise of the imported module (Module instance). Usually you use await
with it. await
without async
is supported on the top-level of modules.
Nowadays I recommend using ESM in node.js too and migrate from require
. Recent version of many NPM modules dropped support for CommonJS in favor of ESM.
<script type="module" src="main.js"></script>
main.js
const {default: myModule} = doINeedModule ? await import('myModule') : {default: null};
Also managing, bundling and resolving bare and file-system imports is done by bundlers. Working without a bundler is like stone-aged currently if the target is the browser.
I recommend Vite. With plugins you could not bother even importing anything, that will be done for you automatically. You can write custom bare and file-system resolvers, possibilities are endless. You can even import modules by file name patterns: https://vitejs.dev/guide/features.html#glob-import
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论