大家都知道(如果暫時還不清楚的可以戳這裡>>),umd
格式是跨平臺的模組解決方案,node和瀏覽器的相容寫法,但直接在node中使用還是存在問題的:
問題復現
最近在引用自己寫的一個外掛的時候,偶然發現webpack下引用 node_modules
下的檔案與直接引用資料夾中的檔案表現不一致。檔案內容都是由webpack打包出的同一個檔案 umd.js
,從node_modules
引入的可以直接使用,但是從普通資料夾中
引入的檔案在瀏覽器中會報錯,到底是什麼原因??是人性的扭曲還是道德的淪喪??
問題詳細描述
// vue.config.js
let config = {
baseUrl: process.env.NODE_ENV === "production" ? "/ele-multi-cascader/" : "/",
configureWebpack: {
output: {
libraryExport: "default"
}
}
};
module.exports = config;
// babel.config.js
module.exports = {
presets: [
["@vue/app", {
useBuiltIns: "usage"
}]
]
};
// cli3 構建命令 --target lib 構建符合umd規範產出
// vue-cli-service build --name cascader --entry ./src/index.js --target lib --mode production
複製程式碼
構建截圖:
為了排除cli3
外掛的干擾,我使用cli2
的vue
專案也進行了嘗試,表現都是一致的!
// 成功
import Vue from 'vue'
import eleMultiCascader from "../node_modules/ele-multi-cascader/dist/cascader.umd";
import eleMultiCascader from "ele-multi-cascader/dist/cascader.umd";
import eleMultiCascader from "ele-multi-cascader";
let eleMultiCascader = require("../node_modules/ele-multi-cascader/dist/cascader.common");
let eleMultiCascader = require("ele-multi-cascader/dist/cascader.umd");
let eleMultiCascader = require("ele-multi-cascader");
// 失敗
import eleMultiCascader from "../dist/cascader.common";
let eleMultiCascader = require("../dist/cascader.umd")
// 在頁面直接引用
// <script src="./cascader.umd.js"></script>
複製程式碼
初步表現為,只要是從node_modules
中引入的檔案,都可以正常使用。
- 引用成功的都順利列印出了外掛物件,看起來是這麼美好…
- 引用失敗車禍現場
點進去發現是Vue
是undefined
,WTF?
How to resolve?
最開始一直認為是node的模組引用機制
導致的問題,後來再次仔細瞭解了相關規範,node
支援的是commonJs
,而umd
是相容commonJs
的所以跟node的模組機制
沒有關係。
睡午覺的時候還在想這個問題,經過以上的種種表現可以推測,只能是webpack
打包導致的問題。umd
這種相容語法在node
環境中直接require
是不能直接使用的,如果要正常使用,必須要通過轉碼。嗯,轉碼!!
是誰負責轉碼呢?肯定是Babel
了,只是不知道具體用的哪個外掛。到這裡問題已經解決了 90% 了。
plugin-transform-modules
開啟node_modules
的@babel
資料夾可以看到關於模組轉換的幾個外掛!
真相已經很明確了,就是這個 plugin-transform-modules-umd ,babel
會預設對node_modules
中引入的檔案做相應規範的轉碼,而別的資料夾不會,除非你手動配置。
開啟官網可以看到一系列的介紹,就不做文件搬運了,粗暴的在專案中配置了一下。
// babel.config.js
module.exports = {
presets: [
[
"@vue/app",
{
useBuiltIns: "usage"
}
]
],
// here
plugins: ["@babel/plugin-transform-modules-umd"]
}
// main.js
import eleMultiCascader from "../dist/cascader.common";
console.log("TCL: eleMultiCascader", eleMultiCascader)
複製程式碼
懷著激動的心情執行了下 yarn serve
,終於在控制檯看見了清爽的一幕!問題成功解決。
結語
平時在繁忙的搬磚中可能都沒遇到這個問題,關心的最多的可能也只是babelrc
的配置方法。熟練的使用著cli工具,安靜地當著配置工程師
。cli固然是提升效率的法寶,但是在使用他們的時候應該去想想它背後都有些工具在默默地支援,不要求深入地瞭解每個細節,但是大致的架構,執行原理的瞭解是很有必要的。有了這些架構和原理的指引,以後遇到任何問題也不會像一個無頭蒼蠅,無從下手…。至少有個方向,方向對了也就意味著離真相不遠了!
好了,這次踩坑與大家共勉!如果發現說的不對的地方,歡迎指正!
最後再無恥地打個廣告,主角就是上面引出問題的那個外掛,一個基於ElementUI
的多選級聯選擇器
。歡迎使用,歡迎 Start
連結在此>>,逃~