ES6 import {} from '..'后缀名的问题
最近在看阮一峰的ES6入门。下图中圈出来的地方不太理解。
文中说到.js后缀不可省略。
但是下文中又出现了如下写法:
// lib.js
export let counter = 3;
export function incCounter() {
counter++;
}
// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4
这里import { counter, incCounter } from './lib';
不是省略了.js
后缀名吗。
对比了一些人家写的react代码:
import React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import App from "./containers/App.jsx";
import Store from "./store/Store";
import React from "react";
这里也省略了.js
后缀,但是import App from "./containers/App.jsx";
却又把后缀名完整写出来了。
请教一下各路大神,解答一下疑问:import..from的后面究竟在什么情况下要写.js
这类的后缀名,什么时候不需要写。还是因为别人用工具配置了什么东西所以才不需要写后缀名。
万分感谢!!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
请先区分浏览器原生解析还是打包工具预处理。
浏览器原生
浏览器在解析 import 语句时是需要后缀的,更确切地说,浏览器认 import 后面这个字符串为一个 URL 地址。这个和你在 CSS 文件里写
background-image: url(./path/to/a.jpg)
是一回事。浏览器会根据当前文件以及页面的 BaseURL 等相关信息,得出这个被依赖的资源的 URL 地址,进而向服务器发送 HTTP 请求。后缀在 HTTP 请求的 URL 地址中并不是那么重要,浏览器认的是 HTTP 响应头里的 Content-Type,只要托管你的 js 或图片的资源服务器能正确响应浏览器的 HTTP 请求,你可以随便定义后缀(当然,一般资源服务器会有一个从文件扩展名到 HTTP 响应头 MIMEType 的映射,你可以添加其他自定义后缀,使得服务器能正确响应,但是最好按约定的进行配置),甚至可以挂羊头卖狗肉,URL叫http://a.com/b.jpg 返回内容是响应头为application/javascript 的一段文本字符。
打包工具
打包工具的场景下,为了兼容性,js 中的 import 语句都会被翻译成用 ES5 实现的模块管理的导入语句,比如 webpack 的
__webpack_require__
, 浏览器最后加载的是打包后的 bundle 文件,并没有执行 import 语句(大部分浏览器至今尚未实现import)。 这个时候,我们写的 import 后面到底要不要后缀,全凭工具自己定义规则啊,只要工具在编译打包时能找到被依赖模块。比如webpack可以设定先找.ts
如果没有再找.es
再找.js
, 如果是一个文件夹,就看文件夹里有没有index.js
,甚至从node_modules
目录中去查找 ...总结:
转译打包工具:不用写
原生支持ES6的node:不用写
原生支持ES6的浏览器:能通过URL在服务器上找到就行,如果真到了HTTP2盛行,ES6完全被浏览器实现,文件不用打包的时候,打包工具会有办法轻松处理的。
总总结:别写
个人见解:
比如说:react、react-dom、vue等都是贡献者发布的
NPM package
(也就是打包好的模块),使用NPM安装后都会存放到node_modules目录下,这些都是上文所提到的module而JS文件并不是一个module,(这里说的不完全)
在ES6中提供了
模块化
,(使用import、export定义模块)在Node.js中,采用CommonJS规范定义模块
推荐一篇文章
.js
不能省略,主要是为了可读,以及区分。假设你目录下有个自己写的模块test
,还有一个自己写的js文件test.js
。模块是以文件夹形式存在的,然后你用import './test'
,你无法确定你加载的是模块还是test.js
(虽然,在ES6中,一个JS文件也算是一个模块)。你看到的这种代码
import React from "react"
,并不是省略了.js
,而是直接省略了/index.js
。这是一个由npm安装的包,在node_modules
文件夹下面,其实它导入的是\node_modules\react\index.js
,是整个包的入口文件,然后由index.js
再去加载react
需要用到的其他子js
文件注意,在node.js里,暂时还不支持ES6的
import
语法,所以需要通过require()
引入包,用module.exports
和exports
暴露包中的可引入部分。详细请看MDN文档
script type="module" 将默认启用跨域访问。
如果只是针对后缀问题,且不希望开 webpack 的 devServer ,则需要自己开服务进行访问,这里以 express 为例:
app.use(express.static("./", { extensions: ["js"], index: "index.js" }));
可以实现复用所有模块而 import 后的文件不需要后缀。
还存在一个问题是无法自动访问 node_modules 里的模块,因为 express 内好像没有对应的配置,因此需要手动引导。
有没有已经在用 deno 的同学,如果客户端可以直接 import 服务端静态目录下的 node_modules ,那就太棒了!