上一篇文章,已經大致了解腳手架是什么以及腳手架是如何工作的。接下來,稍微深入一下腳手架的工作過程(以vue-cli為例)。首先拋出3個問題:
1.明明全局安裝的是@vue/cli,最后執行的命令卻是vue?
2.全局安裝@vue/cli時發生了什么?
3.執行vue命令時發生了什么,為什么vue指向某個文件,我們卻可以直接通過vue命令執行它?
弄清楚這3個問題,基本上對腳手架的原理已經有個大體的認識,文章最后會詳解自定義npm命令哦~
首先,第一個問題為什么安裝的是@vue/cli,執行的命令是vue,先找到npm文件夾:
這是vue命令的執行文件,打開會發現有這樣一行代碼:
1 endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\node_modules\vue-cli\bin\vue" %*
這行代碼的作用是,將當前命令指向\node_modules\vue-cli\bin\vue,所以即使我們用的命令是vue,最終還是指向@vue/cli內部的文件。
第二個問題,全局安裝@vue/cli時發生了什么:
1.下載node_modules
2.在package.json里面配置bin的軟鏈接:
第三個問題,vue命令最終會指向vue-cli內的某個文件,為什么可以執行它:
前面我們已經知道,vue命令執行的時候,會先找到vue文件(AppData\Roaming\npm\vue.cmd)並執行,執行這個vue文件的時候,會發現這是一個軟鏈接,實際指向的是:\node_modules\vue-cli\bin\vue 該路徑的vue文件,最后才會執行這個文件。那么問題來了,vue命令指向的這個文件,是如何執行的?前端的同學們都知道,node環境下執行js文件,需要加一個node命令前綴,才可以執行該js文件。那這個地方的文件,是如何執行的呢?我們找到vue-cli\bin\vue文件:
打開會是下面這幾行代碼:
1 #!/usr/bin/env node 2 3 const program = require('commander') 4 5 program 6 .version(require('../package').version) 7 .usage('<command> [options]') 8 .command('init', 'generate a new project from a template') 9 .command('list', 'list available official templates') 10 .command('build', 'prototype a new project') 11 .command('create', '(for v3 warning only)') 12 13 program.parse(process.argv)
沒錯,主要就是第一行代碼:
1 #!/usr/bin/env node
這行代碼的作用,它會在我們的環境變量中找到node命令,並用node命令執行該文件!致此,這三個問題都已經有了答案,現在再來看一下:vue create vue-test這條命令的執行過程:
1.在終端輸入:vue create vue-test
2.終端解析出vue命令
3.終端在環境變量中找到vue命令
4.終端根據vue命令鏈接到實際文件vue
5.終端利用node執行vue文件
6.vue解析command/options
7.vue執行command
8.執行完畢,退出
現在是不是對腳手架的工作原理理解更深刻一點了呢,其中的command將會在以后開發腳手架的時候會單獨拿出來討論。
下面介紹自定義npm指令以及其軟鏈接到其它文件:
首先在npm文件夾下新建一個wang.cmd:
1 @ECHO off 2 GOTO start 3 :find_dp0 4 SET dp0=%~dp0 5 EXIT /b 6 :start 7 SETLOCAL 8 CALL :find_dp0 9 10 IF EXIST "%dp0%\node.exe" ( 11 SET "_prog=%dp0%\node.exe" 12 ) ELSE ( 13 SET "_prog=node" 14 SET PATHEXT=%PATHEXT:;.JS;=;% 15 ) 16 17 endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\node_modules\vue-cli\bin\wang" %*
最終指向到vue-cli\bin\wang:
1 #!/usr/bin/env node 2 3 console.log('wang')
執行wang:
最后:腳踏實地行,海闊天空飛!