平時開發中,經常會用到這樣一個語句:
import Vue from 'vue';
由於瀏覽器兼容性問題,通常這個語法是在 webpack 的構建流搭建的項目中執行的,那么這個語句到底做了什么呢?
其實在 nodejs 中,執行 import
就相當於執行了 require
,而 require
被調用,其實會用到 require.resolve
這個函數來查找包的路徑,而這個函數在 nodejs 中會有一個關於優先級的算法。先看一下 import Vue from 'vue'
這一句做了什么:
import Vue from 'vue'
解析為const Vue = require('vue')
。require
判斷 vue 是否未 nodejs 核心包,如我們常用的:path,fs 等,是則直接導入,否則繼續往下走。- vue 非 nodejs 核心包,判斷 vue 是否未 '/' 根目錄開頭,顯然不是,繼續往下走。
- vue 是否為 './'、'/' 或者 '../' 開頭,顯然不是,繼續往下走。
- 以上條件都不符合,讀取項目目錄下 node_modules 包里的包。
到了第五步,import Vue from 'vue'
就找到了 vue 所在的實際位置了,那么問題來了,node_modules 下的 vue 是一個文件夾,而引入的 Vue 是一個 javascript 對象,那它是怎么取到這個對象呢?
其實對於一個 npm 包,內部還有一個文件輸出的規則,先看下 node_modules/vue 下的文件結構是怎么樣的:
├── LICENSE
├── README.md
├── dist
├── package.json
├── src
└── types
是不是看起來很籠統,其實對於 npm 包,require
的規則是這樣的:
- 查找 package.json 下是否定義了 main 字段,是則讀取 main 字段下定義的入口。
- 如果沒有 package.json 文件,則讀取文件夾下的 index.js 或者 index.node。
- 如果都 package.json、index.js、index.node 都找不到,拋出錯誤
Error: Cannot find module 'some-library'
。
那么看一下 vue 的 package.json 文件有這么一句:
{ ... "main": "dist/vue.runtime.common.js", ... }
到這里就很清晰了:
import vue from 'vue'; // 最后轉換為 const vue = require('./node_modules/vue/dist/vue.runtime.common.js');
而 vue.runtime.common.js 文件的最后一行是:module.exports = Vue;
,就正好跟我們平時使用時的 new Vue({})
是一致的,這就是 import vue from 'vue'
的過程了。
當然,這個是我們平時使用得最多的導入方式,還有其他一些導入規則,都可以在 nodejs 的文檔中找到。