babel-loader 编译node_module 报错

发布于 2022-09-11 16:21:20 字数 5335 浏览 17 评论 0

问题

在vue的webpack模板项目中,我把 node_module目录 include 给 babel-loader 对引用到的模块进行es6 -> es5 转译,结果npm run build 的时候出现了 警告和错误,错误和警告都比较多且重复,我下面展示几个不同的错误区域截图。

我为了解决这个问题开了一个github项目,项目很小,安装完依赖就可以build复现错误。
https://github.com/Yatoo2018/...

错误截图

clipboard.png

clipboard.png

clipboard.png

babelrc内容

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime"]
}

这是webpack的配置:

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}



module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        
        // include: [resolve('src'), resolve('test'),resolve('node_modules/webpack-dev-server/client')], //  原先配置是这个
        include: [resolve('src'), resolve('test'), resolve('node_modules')] // 我把node_moudle加进去了,然后就出现了我的问题
      }
    ]
  },
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
}

之所以添加node_module目录这个配置给babel-loader去转换语法,是因为

我在项目中引用了一个swiper,通过 import Swiper from "swiper" 这样的ES6的方式引入了swiper,且按照swiper官网的提示,需要添加babel-loader的exclude配置。
clipboard.png

我们先看下这个exclude配置的正则排除了什么样的文件路径:
这个 /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/

clipboard.png

这个正则匹配了只要字符串中包含node_modules目录下的dom7,ssr-window和swiper就不匹配,其他的都匹配。

而这个正则放在exclude的配置下,那么就说明它的含义是要把其他node_module中的模块都从babel-loader的转义中排除掉,没有排除上面那三个module。

所以问题1 一般来想,开发这些库的人应该会比我考虑的更严谨一些,所以我就很奇怪:要明确对这三个模块进行语法转义不应该是将其添加到include配置吗, 为啥要绕一下,反过来排除其他的而留下他们三个,就不担心这样的配置被添加到项目中,本来想要被babel-loader转义的模块,结果被你swiper给的配置给排除了,出现问题?

先让我们把上面疑问略过,我根据swiper给的webpack配置把babel-loader的rule配置调整如下:

 {
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/,
    include: [resolve('src'), resolve('test'),resolve('node_modules/webpack-dev-server/client')]
  },

但是编译的 vender.hashxxxxx.js 中还是能看到

clipboard.png

问题2:这个文件中仍然存在dom7模块的const 声明的变量,并没有转换?

好吧,猜测这个方式存在问题,于是我想 既然要明确的把这三个模块进行转义,那么我就include这三个模块给babel-loader

 {
    test: /\.js$/,
    loader: 'babel-loader',
    include: [resolve('src'), resolve('test'),resolve('node_modules/webpack-dev-server/client'),resolve('node_modules/swiper'),resolve('node_modules/dom7'),resolve('node_modules/ssr-window')]
  },

编译后的文件信息:

clipboard.png

这样做了之后,npm run build之后语法都转换完成了,也正常了。至此swiper引入的问题应该解决了,但是项目中还有一些其他的类似swiper这样的module, 要把他们一个个摘出来include一下也是可行的,稍微麻烦了一点。所以既然是这样,那么我何不将 node_module目录 include给babel-loader,这样做的话,babel-loader应该就能转义被项目引用到的任何文件(也就是node_module中那些直接或者间接被依赖的module),而我也期待任何可能用es6语法写的模块都会被babel转一下。
于是,我调整配置

{
    test: /\.js$/,
    loader: 'babel-loader',
    //exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/,
    include: [resolve('src'), resolve('test'),resolve('node_modules/webpack-dev-server/client'),resolve('node_modules')]
    // include: [resolve('src'), resolve('test'),resolve('node_modules/webpack-dev-server/client'),resolve('node_modules/swiper'),resolve('node_modules/dom7'),resolve('node_modules/ssr-window')]
  }

但是当我这么做了,结果却出现了很多错误,如上面截图部分的错误。
所以 问题3 当我把node_module给了babel-loader去转译,事实上我的目的达到了,文件确实都被babel转成功了,但是 为什么会出现很多上述警告和错误?
这时候编译后的文件信息:
clipboard.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

裸钻 2022-09-18 16:21:20

第一个问题:

exclude : /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/

代表匹配后面不是dom7|ssr-window|swiper这3个的规则,也就是说如果你import了这个3个都会被babel处理,因为这三个都是支持esm的语法。
第二个问题:

exclude: /node_modules\/(?!(dom7|ssr-window|swiper)\/).*/,
include: [resolve('src'), resolve('test'),resolve('node_modules/webpack-dev-server/client')]

这种写法你并没有include(dom7|ssr-window|swiper),所以自然不会babel处理,exclude主要是进行排除法。

第三个问题:

include: [resolve('src'), resolve('test'),resolve('node_modules/webpack-dev-server/client'),resolve('node_modules')]

你将所有的node_modules include进来,这就可能有些模块没有esm的语法,比如babel-runtime,lodash等,就可能导致报错或者警告。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文