前端构建踩坑 --- babel-loader 对已编译的脚本进行再编译从而导致文件执行出错

3,556 阅读3分钟

前言

本人博客原地址:前端构建踩坑 --- babel-loader 对已编译的脚本进行再编译从而导致文件执行出错

问题描述: babel-loader 对已编译的脚本进行再编译从而导致文件执行出错。

  因为打算开发一个小组件库,但是要对已经编译完成的组件库的脚本进行一遍完整的测试。所以,本人就很自然的启动一个项目,引入已经编译好的组件库脚本,想着大展伸手,结果。。。

  遇到了一大堆脑瓜子疼的警告"export 'default' (imported as 'a') was not found in 'xxx' ",或乱七八糟的报错...(捂脸哭.jpeg)。

  • 原本我要引入的脚本a.umd.js是使用了ES6 模块的写法,将对应的模块export default 出来的。
  • 再将组件库发包到 npm上,并通过npm install 去将该组件库安装到node_modules对应的目录中。
  • 然后使用import a from 'XXX'去引入,结果这个组件库是可以正常使用的。
  • 但是,当直接在本地(不是在node_modules)引入该脚本或在直接在package.json中将该组件库作为本底依赖安装也不行时,就会出现上面提示的警告(或报错)。

  原本想着只有在node_modules中才能正常使用,好,为了调试,我选择直接将该脚本(a.umd.js)作为本地依赖引入,因此,我就很兴奋去尝试了。。。步骤是这样的:

// 在package.json直接通过通过本地依赖的方式引入脚本a.umd.js
{
  "name": "baz",
  "dependencies": {
    "a": "file:./config/a.umd.js"
  }
}

嗯,很顺利npm i完成,然鹅。

直接通过本地依赖的方式依旧存在以上的问题。

那么为什么通过npm i发布到 npm 的脚本a.umd.js能在 node_modules 正常使用而通过本地依赖的方式安装 node_modules 以及直接引用却不行?

后来

经过网上查资料以及分析项目,终于发现了这么一个事情。。。

  嗯,是的,babel-loader 对a.umd.js这个脚本,再次进行了编译。。。导致原本编译好的可以正常使用的脚本再次进一步被编译了,所以才会报错"export 'default' (imported as 'a') was not found in 'xxx' "

因此

  为了能顺利地在本地调试组件库的脚本a.umd.js,我只能选择在引入该脚本 a.umd.js调试的项目中进行 babel-loader 的配置,将 babel-loader 对 a.umd.js 的编译进行exclude。即babel-loader 不编译名字中包含a.umd字符的文件。

  • 如果直接使用webpack配置,则配置如下:
module: {
  rules: [
    {
      test: /\.m?js$/,
      exclude: /a.umd/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']
        }
      }
    }
  ]
}
  • 如果是使用vue-cli,则vue.config.js配置如下:
chainWebpack: (config, isServer) => {
// config 是 ChainableConfig 的一个实例    
config.module.rule('js').use('babel-loader')
.loader('babel-loader').tap(options => {
    options.exclude = /a.umd/
    // 修改它的选项...
    return options
  })
},

从过以上的方式就可以避免babel-loader 对已经编译的文件进行二次编译

  • 第三解决方案: 既然该脚本已经是被编译好的代码,无需二次编译,我们只需要让项目的中babel编译的时候,忽略该文件即可。在babel.config.js中添加以下红色圈出来的代码(当然如果项目中用的配置文件是.babelrc,则同理),让babel编译时忽略的该脚本即可解决问题。示例要忽略message-service-sdk.js这个脚本如下:

Untitled.png

所以,综上所述

  • vue-cli3 中 babel-loader 的配置是不对 node_moudules 文件夹中的文件进行编译,所以当直接将脚本放在 node_modules 或直接通过 npm 远程 install 都能正常使用。
  • 而当引入的脚本不在 node_modules 中或通过本地依赖的方式安装到 node_modules 都会被babel-loader二次编译(当然设置了exclude的除外)