import './store' 可以默认引入`./store/index.js`,这个原因是怎么做到的?

import './store',默认会引入/store/index.js;

1.请问requere有没有这样的特性?
2.这个特性的实现是因为什么?是webpack吗?

阅读 4.2k
5 个回答

是js 模块默认的特性(也可以说是v8?),import/require 默认可以 导入 js,json文件,实现逻辑你可以简单想一下,当你不输入文件名的时候,引擎自动遍历目标文件夹下同名文件,当检测到store.js/json时就引入,这里说一下,[js,json] 如果有store.js,就不会引入store.json

node 默认就支持 commonjs 规范,使用的就是 require 进行导入,require 也有这样的特性。这个特性和 webpack 没有关系。 require 函数的查找规则就是这样,这属于 js 模块化内容。

纠正

它会涉及到模块查找算法,不同的环境下稍微不同,但是他们大同小异,并且大多数基于node的模块查找算法扩展。

1. node 原生

1.1 commonjs
不在此问题的提及范围,省略

1.2 esm
esm 默认要求模块直接明确到文件后缀名,不可省略,它将判定mjs/js 后缀对应采用esm/commonjs模块解析规则,不支持到模块目录的解析,它会抛出ERR_UNSUPPORTED_DIR_IMPORT 异常。不过你可以通过开启--experimental-specifier-resolution=node 使得他以node的模块查找算法以支持省略index 后缀等

2. webpack

webpack 下由 enhanced-resolve 包提供,它可配置,基于node的模块查找算法扩展,详见此包。

例:我们可以通过配置修改查找规则

module.exports = {
  //...
  resolve: {
    extensions: ['.mjs', '.js'], // 优先mjs后缀的文件
  },
};
module.exports = {
  //...
  resolve: {
    mainFields: ['browser', 'module', 'main'],
  },
};

https://webpack.docschina.org...

更多的 typescript解析器 rollup vscode等 ,也有自己的基于node模块查找算法扩展,不再赘述。

3. 浏览器

目前浏览器下 script type="module" 也支持
不过它就更加严格了,不支持省略后缀,不支持import map的情况下不支持别名等等

补充一个例子
当我们使用 import './store'

在node环境下,首先import 关键字标识你想要使用ES module,所以你需要做的第一件事,就是在当前的process.cwd() 下的package.json描述文件内添加

{
    ...
    "type":"module"
}

接下来,node已经启用ES module,但是它发现你的import的store没有后缀名,所以它可能是一个省略后缀的文件,也可能是一个目录,所以在这种情况下,如果它想当然的使用某一种规则,可能会做错事,所以它选择直接报错。你需要标识--experimental-specifier-resolution=node 即我想使用node的查找规则去解析模块引入,如果发现store是一个目录,它还会根据store下的描述文件(package.json)去加载文件,所以你可以在store下添加package.json以影响它的结果,例如

{
    "module":"./xxx.js" // store下的 xxx.js 而非index.js
}

webpack大体同上,根据你的配置走解析,它的扩展能力体现在它支持别名alias,支持webpack loader的解析,支持更多文件extensions,支持更多package.json的字段支持,例如export, 太多了,不想打字了😂

如果是webpack的话,与webpack模块解析的配置有关

  module.exports = {
    // ...
    resolve: {
      // 自动补全文件后缀来查询文件路径
      extensions: [".js"],
      // 解析时查询详细的文件路径
      mainFiles: ['index']
    }
  }

import "./store"如果存在名为store的文件,就去匹配后缀.jsextensions的配置),如果匹配上了,就会导入./store.js;如果不存在名为store的文件但存在名为store的目录,就继续向下找,看是否存在名为index的文件(mainFiles的配置),再继续匹配后缀.js,如果匹配上了,就导入./store/index.js

import './store',默认会引入/store/index.js;

1.请问requere有没有这样的特性?

首先是require ,这是个常用词汇,所以拼写要注意。其次require一样也可以这样写。

在编译或者执行中,会优先查找 ./store.js 如果没有这个文件,再就是查找./store.json,如果还没有的话,就会找./store/index.js,如果还没有的话就会报错。
import a from './store' 在打包后就会变成 const a = require('./store/index.js')

2.这个特性的实现是因为什么?是webpack吗?

是引擎支持的语法规范。并不受限于webpack

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题