在專案中自定義路徑放入element-ui並修改編譯原始碼

Runner發表於2019-03-04

起因

因為準備看element-ui的原始碼,會做一些筆記,在原始碼中寫一些註釋,甚至對原始碼進行一些自定義的修改來檢視執行效果。
所以element-ui的資料夾不能直接npm install放在node_modules資料夾下面,node_modules資料夾一般是不同步到svn上的,放在裡面的話在另一個電腦上可能重新安裝專案自己的修改就沒有了。
對引入的外部元件,如果要自定義修改,那麼都不能放在node_modules下。
過程中遇到的一些問題記錄一下。

element-ui貢獻指南:
github.com/ElemeFE/ele…

vue腳手架安裝

vue init webpack element-learn

cd element-learn

npm install

npm run dev

一步步來,建好初始的資料夾。

引入element-ui

github.com/ElemeFE/ele…
下載一個master分支。在src資料夾下建立一個element-ui資料夾,將下載的分支解壓到該資料夾下。

此時嘗試在main.js中引入element-ui:
import elementUI from `./element-ui`;
Vue.use(elementUI);

報錯:This relative module was not found:
./element-ui in ./src/main.js

這是因為我們直接下載過來的element-ui沒有經過編譯。
模組機制從element-ui包的package.json中的讀到的入口檔案不存在。所以首先要自己編譯element-ui原始碼。

到element-ui中的操作

cd E:vueelement-learnsrcelement-ui

npm install

npm run dev

然後訪問http://localhost:8085
可以看到示例。
跟官網element.eleme.io/#/zh-CN
基本是一樣的。我們也可以直接到這個示例中去修改元件,檢視效果。畢竟實時編譯。

然後是編譯,也就是生成我們專案中會使用到的檔案。

npm run dist

有可能會報錯package.json does not exist, have you run lerna init?
npm install lerna一下。
有時候還會有些別的錯誤,把node_modules刪除了重新npm install就好。

編譯完之後我們就看到多了一個lib資料夾。裡面就是編譯生成的檔案。

然後

cd E:vueelement-learn

npm run dev

報這個:
[BABEL] Note: The code generator has deoptimised the styling of “E:/vue/element-learn/src/element-ui/lib/element-ui.common.js” as it exceeds the max of “500KB”.
不過不用管它,這個不影響。
後面還有報錯

* element-ui/lib/button in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/button-group in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/checkbox in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/checkbox-group in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/input in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/input-number in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/locale in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/mixins/emitter in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/mixins/locale in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/mixins/migrating in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/option in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/progress in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/scrollbar in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/select in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/tag in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/tooltip in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/transitions/collapse-transition in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/clickoutside in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/date in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/dom in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/merge in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/popup in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/resize-event in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/scroll-into-view in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/scrollbar-width in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/shared in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/util in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/vdom in ./src/element-ui/lib/element-ui.common.js
* element-ui/lib/utils/vue-popper in ./src/element-ui/lib/element-ui.common.js複製程式碼

說明兩點:1.element-ui的入口檔案找到了。2.入口檔案中路徑配置可能有問題。

路徑問題分析

首先我們到入口檔案lib/element-ui.common.js,
發現裡面有很多類似這樣的模組引入:module.exports = require(“element-ui/lib/select”);
這個路徑比較奇怪的是element-ui這一段是哪裡來的,它怎麼就知道我的目錄是叫這個名字。於是我修改了目錄名重新編譯,發現這個檔案裡的路徑還是這樣。

然後我把名字改回來,把資料夾移動到node_moudule下,import elementUI from `element-ui`;
發現能正常執行。所以編譯的包應該是沒有問題的。問題在路徑上。

然後資料夾移回去,到element-ui的build資料夾搜尋一下element-ui。果然發現了不少element-ui。

關鍵在config.js中這裡

exports.alias = {
  main: path.resolve(__dirname, `../src`),
  packages: path.resolve(__dirname, `../packages`),
  examples: path.resolve(__dirname, `../examples`),
  `element-ui`: path.resolve(__dirname, `../`)
};複製程式碼

可以看到element-ui是這個路徑的別名。所以element-ui這裡的webpack是可以識別它的。而我們專案的的webpack是識別不了它的。

那麼放到node_modules資料夾下,為什麼可以正常識別這個路徑呢,根據nodejs的模組搜尋機制,npm install下來的它的資料夾名字也是element-ui,這個時候element-ui不是一個別名。直接引入node_modules中的模組,引入方式是import elementUI from `element-ui`,那麼lib/element-ui.common.js檔案中的那些`element-ui`就直接對應到element-ui的根目錄了。

所以在我們專案的webpack配置webpack.base.conf.js中增加別名配置element-ui,把`element-ui`指向我們專案中element-ui根目錄的位置src/element-ui:

    alias: {
      `vue$`: `vue/dist/vue.esm.js`,
      `@`: resolve(`src`),
      `element-ui`:resolve(`src`)+`/element-ui`
    }複製程式碼

然後重新執行 npm run dev。執行成功。
於是我們的webpack也能正常地識別lib資料夾裡檔案中`element-ui`的路徑了。

結尾

然後如果我們修改了element-ui的原始碼,只要編譯一下就可以正常在我們自己的專案中應用了。
不過還有一點不好的地方就是我們沒有對element-ui原始碼進行實時的編譯,我們專案引用的是它編譯過後的而不是真正的原始碼,也就是沒有把它自己的實時編譯過程寫到我們的專案webpack的配置中來。所以我們專案中npm run dev的時候並不能實時監測到我們對element-ui原始碼的修改。這一點後面再優化。

對於一些常見專案的腳手架,其實應該好好學習一下。以後再遇到檔案路徑問題,各種配置問題會得心應手很多。
記錄一下,順便推薦最近看的兩本書《深入淺出nodejs》《深入理解es6》。

最先發在github上:github.com/liusaint/el…

相關文章