webpack5、babel配置遇到的坑

这周接手了一个前后端未分离的老项目,需要用webpack重新打包,重新设置html入口,之前没接触过webpack,急着学了点皮毛,遇到了很多问题,踩了很多坑,我这边简单总结一下。

下载的webpack5,用webpack4语法打包,资源文件(如图片)加载不出来

因为是拼布式的学习,急着赶项目进度,webpack中文文档看了前几章就着急上手项目想要解决问题了,直接install,所以下载的是最新版的5
具体的安装版本:
webpack 5.52.1
webpack-cli 4.8.0

配置如下
webpack.config.js中代码:

const path = require(‘path‘);
const HtmlWebpackPlugin = require(‘html-webpack-plugin‘);

module.exports = {
    mode: ‘production‘,
    entry: {
        index: ‘./src/index.js‘,
        init: ‘./src/init.js‘
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: ‘cloudTrial.html‘,
            title: ‘测试‘,
        }),
    ],
    output: {
        filename: ‘./js/[name].js‘,
        path: path.resolve(__dirname, ‘./dist‘),
        clean: true,
    },
    module: {
        rules: [
            {
                test: /\.css$/i,
                exclude: path.resolve(__dirname, ‘node_modules‘),
                use: [‘style-loader‘,‘css-loader‘],
            },
        ],
    }
  };

到这里我都是一步一步跟着5的文档走的,所以没有出现什么问题,因为不希望每次都要更改入口文件,方便打包入口和开发的html分离开来,也引入了html-webpack-plugin(结果这成了我遇到终极大坑的由头,后面细说),希望尽量减少请求的调用所以加了css-loaderstyle-loader将css代码也并入了js里,但是打包完运行,发现有404,css里的url图片并没有跟着一起打包出来,所以找不到图片。然后文档继续项下看了一些,讲到webpack关于资源打包的方式,用文档中的方式打包,但不知道为什么,报错了,我这边没有记录报错的内容,估计是有什么字段写错了。
然后就又进入了一个深坑:我去浏览器上查找怎么打包css中的图片。跟着这些博主的文章,我安装了url-loaderfile-loader(这边一开始我只装了url-loader,还报了缺失file-loader的问题)去重新配置了我的webpack,加入了以下内容:

            {
                test: /\.(jpg|png|gif)$/,
                loader:"url-loader", //url-loader依赖于file-loader
                options:{
                    limit: 8 * 1024 //图片小于8kb就是用base64的方式
                }
                  
            }

能正常打包没有报错了,也没有404找不到图片的问题了,但是图片还是没有加载出来,我直接在vscode里也无法打开打包的图片,网上几乎没有一篇提到这个问题的博客,可能是因为5用的人少吧
后来就是不断尝试,我去重新翻5的文档看,这次自己重新建了个demo,一步一步跟着文档做,然后发现到了5,已经不需要什么url-loaderfile-loader之类的加载器了,网上给的都是4的配置方式,我却用5的版本运行,可能就导致了这个问题(关键是也没有报错,就特别难以排查,而且我第一次配置webpack,一开始错以为打包后的图片就是应该无法正常打开的)。
所以后面我用下面这样的配置,就可以解决图片打包的问题了(第二行是排除node_modules里的内容,我这边也踩了坑,不好好配置这个也会报错):

            {
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                exclude: path.resolve(__dirname, ‘node_modules‘),
                type: ‘asset/resource‘,
            },

但这时候不太美观,图片的输出路径直接暴露在dist目录底下了,然后又翻了大半天博客,往下翻了翻文档,用4的写法是没法法配置的,最后问了mentor,她帮我又往下翻了翻文档,最后在很下面竟然找到了配置方法,按照说明配置如下:

            {
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                exclude: path.resolve(__dirname, ‘node_modules‘),
                type: ‘asset/resource‘,
                generator: {
                    filename: ‘img/[hash][ext][query]‘,
                },
            },

这样就好看多了
webpack5、babel配置遇到的坑

到此webpack最最最简单的配置就差不多结束了,我以为到这差不多简单打包应该就结束了,结果提测那边反映了项目在实机运行中存在偶发性问题(ios,还是一个ipod),所以又把我的提交打回了,我只的继续探索,并排查原因


配置babel又踩了一些坑

一开始是不想引入babel的,但是没办法,在测试机上运行经常出现问题,然后我在自己手机和同事的iphone上运行好像又没有问题,所以认为是浏览器版本导致的兼容性问题,那就不得不用babel了,其实也用简单方法测试了一下是不是浏览器版本问题,但是因为项目特殊性,无法直接通过代码的方式测试,只能先配上再说(后来证明其实和浏览器兼容性没关系)
这边因为babel的文档给我感觉稍微有点乱,然后引用的方式也太多,而我只想在webpack中配置使用,所以我直接找了个博主,跟着他的方法一步一步配置的:原文
整体没毛病,但是要注意babel-core和babel-loader也有个版本适配性的问题,不过没事这边就算报错了也会清晰提示你该换哪个的版本,所以还算顺利,但是这边配置好了还是有报错:

BabelLoaderError: SyntaxError: Unexpected token 
|                     ...someString,

就是认不得扩展运算符,这个给我感觉蛮匪夷所思的,其他语法都能转换,竟然这个不能转换,谈到的博客也比较少,但总算也找到个靠谱的博客,安装一个插件即可解决
所以我的最后babel系列版本如下(url-loaderfile-loader没用到,删了也可以)
package.json中部分内容:

"dependencies": {
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-runtime": "^6.26.0",
  },
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.7.0",
    "css-loader": "^6.2.0",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^5.3.2",
    "style-loader": "^3.2.1",
    "url-loader": "^4.1.1"
  },

webpack.config.js中部分内容:

            {
                test: /\.js$/,
                exclude: path.resolve(__dirname, ‘node_modules‘),
                use: {
                  loader: ‘babel-loader‘,
                },
            },

.babelrc中内容:

{
    "presets": [["babel-preset-env", {
        "targets": {
        "browser": ["> 1%", "last 2 versions"]
        }
    }]],
    "plugins":[
        "transform-runtime",
        "transform-object-rest-spread" // 解决无法识别拓展运算符babel插件
    ]
}

到此babel也配置完毕了,但我尝试测试项目,bug却还是没有解决。


终极bug排查,真相大白,问题出在html-webpack-plugin

这个问题特别难以排查,而且因为项目整体建立在websocket通信上,我这边的代码也只是一些外部的操作,导致我一直认为是内部一个sdk的问题,我问了我们这最强的同事,他帮我调出了查看websocket通信的调试页面(我以前没接触过,不知道这玩意儿),但是也没发现到底是什么问题,但是他调出的websocket连接查看,帮了我大忙。我看了看连接情况,对比原版(前后端未分离时候版本的该项目的的运行状态),发现它只建立了一次websocket连接,而我每次启动项目都会建立两条(而当我这边建立的线路通往不同地区的主机时,bug就发生了)。然后我就一份js一份js的累加在项目中,发现不用webpack打包的话,也只建立一条,但是一尝试使用webpack打包,运行时就会建立两条通信连接,然后我在打包生成的index.html代码,格式化了一下(因为打包会变成一行,我以前一直都不愿意),发现我打包的js,它的引用自动注入到了html前面,而我在我自己写的html里,本身又写了调用js的方法,所以等于一条js,调用了两次的情况。
还记得我提到的html-webpack-plugin吗,其描述有一段这样的话:

如果在代码编辑器中打开 index.html,你会看到 HtmlWebpackPlugin 创建了一个全新的文件,所有的 bundle 会自动添加到 html 中。

也就是说,凡是在我的webpack.config.js配置文件中有的入口文件,都会自动放置到生成的html文件头部,如下:

    <script defer="defer" src="./js/index.js"></script>
    <script defer="defer" src="./js/init.js"></script>

如果我再在我原始html文件里引用js的话,就会造成js执行两遍的情况
果然,在我删除原始html中关于js的引入之后,bug就不复存在了,真相终于大白了。
所以这也告诉我们一个深刻的道理:
学习知识要踏实,系统性的学习一些工具和知识点还是很重要的,不然像我这样到处找补丁,急着完成任务就反而会被拖的更慢。

webpack5、babel配置遇到的坑

上一篇:标签是干嘛的


下一篇:linux安装python