Webpack模組引用中還有什麼坑?

imJarvan發表於2019-04-19

大家都知道(如果暫時還不清楚的可以戳這裡>>),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
複製程式碼

構建截圖:

Webpack模組引用中還有什麼坑?

為了排除cli3外掛的干擾,我使用cli2vue專案也進行了嘗試,表現都是一致的!

// 成功
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中引入的檔案,都可以正常使用。

  • 引用成功的都順利列印出了外掛物件,看起來是這麼美好…

Webpack模組引用中還有什麼坑?

  • 引用失敗車禍現場

Webpack模組引用中還有什麼坑?

點進去發現是Vueundefined,WTF?

Webpack模組引用中還有什麼坑?

Webpack模組引用中還有什麼坑?

How to resolve?

最開始一直認為是node的模組引用機制導致的問題,後來再次仔細瞭解了相關規範,node支援的是commonJs,而umd是相容commonJs的所以跟node的模組機制沒有關係。

睡午覺的時候還在想這個問題,經過以上的種種表現可以推測,只能是webpack打包導致的問題。umd這種相容語法在node環境中直接require是不能直接使用的,如果要正常使用,必須要通過轉碼。嗯,轉碼!!

是誰負責轉碼呢?肯定是Babel了,只是不知道具體用的哪個外掛。到這裡問題已經解決了 90% 了。

plugin-transform-modules

開啟node_modules@babel資料夾可以看到關於模組轉換的幾個外掛!

Webpack模組引用中還有什麼坑?

真相已經很明確了,就是這個 plugin-transform-modules-umdbabel 會預設對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,終於在控制檯看見了清爽的一幕!問題成功解決。

Webpack模組引用中還有什麼坑?

結語

平時在繁忙的搬磚中可能都沒遇到這個問題,關心的最多的可能也只是babelrc的配置方法。熟練的使用著cli工具,安靜地當著配置工程師。cli固然是提升效率的法寶,但是在使用他們的時候應該去想想它背後都有些工具在默默地支援,不要求深入地瞭解每個細節,但是大致的架構,執行原理的瞭解是很有必要的。有了這些架構和原理的指引,以後遇到任何問題也不會像一個無頭蒼蠅,無從下手…。至少有個方向,方向對了也就意味著離真相不遠了!

好了,這次踩坑與大家共勉!如果發現說的不對的地方,歡迎指正!

最後再無恥地打個廣告,主角就是上面引出問題的那個外掛,一個基於ElementUI多選級聯選擇器。歡迎使用,歡迎 Start 連結在此>>,逃~

相關文章