美文网首页
Webpack模块引用中还有什么坑?

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

作者: JarvanIV | 来源:发表于2019-04-19 16:10 被阅读0次

    大家都知道(如果暂时还不清楚的可以戳这里>>),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
    

    构建截图:

    image

    为了排除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中引入的文件,都可以正常使用。

    • 引用成功的都顺利打印出了插件对象,看起来是这么美好…
    image
    • 引用失败车祸现场
    image

    点进去发现是Vueundefined,WTF?

    image image

    How to resolve?

    最开始一直认为是node的模块引用机制导致的问题,后来再次仔细了解了相关规范,node支持的是commonJs,而umd是兼容commonJs的所以跟node的模块机制没有关系。

    睡午觉的时候还在想这个问题,经过以上的种种表现可以推测,只能是webpack打包导致的问题。umd这种兼容语法在node环境中直接require是不能直接使用的,如果要正常使用,必须要通过转码。嗯,转码!!

    是谁负责转码呢?肯定是Babel了,只是不知道具体用的哪个插件。到这里问题已经解决了 90% 了。

    plugin-transform-modules

    打开node_modules@babel文件夹可以看到关于模块转换的几个插件!

    image

    真相已经很明确了,就是这个 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,终于在控制台看见了清爽的一幕!问题成功解决。

    image

    结语

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

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

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

    相关文章

      网友评论

          本文标题:Webpack模块引用中还有什么坑?

          本文链接:https://www.haomeiwen.com/subject/dgqcgqtx.html