阅读 192

Webpack模块引用中还有什么坑?

大家都知道(如果暂时还不清楚的可以戳这里>>),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插件的干扰,我使用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中引入的文件,都可以正常使用。

  • 引用成功的都顺利打印出了插件对象,看起来是这么美好…

  • 引用失败车祸现场

点进去发现是Vueundefined,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-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,终于在控制台看见了清爽的一幕!问题成功解决。

结语

平时在繁忙的搬砖中可能都没遇到这个问题,关心的最多的可能也只是babelrc的配置方法。熟练的使用着cli工具,安静地当着配置工程师。cli固然是提升效率的法宝,但是在使用他们的时候应该去想想它背后都有些工具在默默地支持,不要求深入地了解每个细节,但是大致的架构,运行原理的了解是很有必要的。有了这些架构和原理的指引,以后遇到任何问题也不会像一个无头苍蝇,无从下手…。至少有个方向,方向对了也就意味着离真相不远了!

好了,这次踩坑与大家共勉!如果发现说的不对的地方,欢迎指正!

最后再无耻地打个广告,主角就是上面引出问题的那个插件,一个基于ElementUI多选级联选择器。欢迎使用,欢迎 Start 链接在此>>,逃~

关注下面的标签,发现更多相似文章
评论