偶然一次发现,他们两个的引入模块的方式不一样,在好奇心的驱使下,便开始一探究竟。
1、vue.config方式
打开项目的package.json,找到 scripts位置。
找到 vue-cli-service 命令,通常命令都位于当前项目的node_modules下的 .bin文件夹中(全局命令不在此处)
在node_modules下找到 @vue/cli-service/bin/vue-cli-service.js
最重要是红色框内语句。继续往下找。
service.js文件比较长,重要的是下面这句。
打开 loadFileConfig
这个文件很短,只有38行,却非常重要。
大意是首先去找是否有自定义配置文件路径,如果有,就加载自定义配置文件;
如果没有,就用默认的 vue.config.xx。
找到配置文件后,通过 is-file-esm 模块来判断配置文件是用es模块方式,还是 commonjs模块方式加载。
而 is-file-esm判断没有别的。就是通过nodejs官方定义的文件 拓展名 和 package.json中的 type 去判断。这里感兴趣,可以阅读nodejs官方对于 commonjs 和 esm 的支持和定义。
is-file-esm模块会先通过文件扩展名判断,
.mjs 为esm ,
.js, .cjs为commonjs模块,
如果没有扩展名,则通过判断package.json的type判断
"type":"module", 为esm,
"type":"commonjs", 为esm,
如果扩展名和type同时出现,则扩展名优先级高。
所以,如果type没指定,vue.config.js以 js 结尾,那么加载的就是 commmonjs,vue.config.js是以 commonjs 方式启动,模块引入只能用 require,而不是import,如果改成import,就会报错.
我们可以将扩展名换成 .mjs试试 (同样可以在package.json中指定type,我们只是挑一种,你有兴趣,可以去试试)
启动后,发现import正常识别,但是 require没有被定义。说明 vue.config.mjs是以 es模块的方式启动的。
2、vite.config方式
打开项目的package.json,找到 scripts位置。
同样,找到 node_module下的 .bin 目录
找到 vite模块下的 bin.vite.js
再找到dist/node/cli
在cli.js这个文件中,找到 /chunks/dep-c9998dc6.js(名称可能版本不同会变,但肯定是位于 createServer 位置处)
在 dep-c9998dc6.js文件中,找到 loadConfigFromFile方法。
可以发现,这里的 isESM 变量,并不是通过模块去判断,而是直接在代码中通过 package.json的type或者 vite.config.xx 的扩展名判断的。只不过多了个额外的ts, 如果扩展名是ts,则也是es模块。
如果配置文件是 vite.config.js。那么isESM为false, userConfig 为undefined, 之后执行 bundleConfigFile 方法将 es模块转译为 commonjs模块(看注释)
// Bundle config file and transpile it to cjs using esbuild.
const bundled = await bundleConfigFile(resolvedPath);
这就是为什么,vite.config.js 即使不是 es 模块,也可以在里面使用import的原因。因为被转译了。
当然修改 vite.config.js 为 vite.config.mjs也是可以的。
最终结果和 vue.config.js大同小异,都是先判断模块类型后,再通过不同的加载器,将其加载进来。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。