webpack5优化的地方及搭建的一些体会

前言

在从Webpack4Webpack5的升级过程中,即使以前已经搭建过Webpack4,但是搭建Webpack5的过程中还是有点痛苦。因为Webpack提供的功能方法实在是太多了,很庞大的一个体系,所以搭建完感触还是很多的,发现不能一味的从网上找,还是得看文档
看完文档才发现原来Webpack5里面已经精简了很多插件了,不需要额外安装其他插件,很多以前概念比较模糊的东西,看了文档还是比较清晰的。大家有兴趣的话可以Fork我的webpack5-boilerplate学习交流,建议大家多敲敲多试试,过程虽然有点痛苦,但是一定会有收获的。
本文讲解,需要一定Webpack4基础,还没有搭建过Webpack4的同学,可以看看这篇Webpack4搭建
下面的讲解,都基于webpack5-boilerplate这个项目。

Webpack大体框架

首先我们对Webpack得有一个大体的框架认识

// webpack.config.js
module.exports = {
    // 入口
    entry: {},

    // 打包输出
    output: {},

    // 配置模块如何解析
    resolve: {},

    // 配置各种loader
    module: {},

    // 配置插件
    plugins: [],

    // 优化(可以进行代码分割)
    optimization: {},

    // webpack-dev-server 开发时的配置,一般用于development模式
    devServer: {}
};

所需要的Loader

CSS类的Loader

  • css-loader
  • css-minimizer-webpack-plugin
  • mini-css-extract-plugin
  • less-loader
  • less
  • style-loader
  • ...

目前我暂时用到的就这些

解析ES6类的Loader

  • @babel/core
  • @babel/plugin-transform-runtime
  • @babel/preset-env
  • babel-loader
  • core-js

解析Html类的Loader

  • html-webpack-plugin

Webpack5不需要用到的依赖

  • url-loader
  • file-loader
  • clean-webpack-plugin
  • @babel/polyfill
  • @babel/runtime
  • optimize-css-assets-webpack-plugin

最后依赖列表预览

"devDependencies": {
    "@babel/core": "^7.16.12",
    "@babel/plugin-transform-runtime": "^7.16.10",
    "@babel/preset-env": "^7.16.11",
    "babel-loader": "^8.2.3",
    "css-loader": "^6.5.1",
    "css-minimizer-webpack-plugin": "^3.4.1",
    "filemanager-webpack-plugin": "^6.1.7",
    "html-webpack-plugin": "^5.5.0",
    "less": "^4.1.2",
    "less-loader": "^10.2.0",
    "mini-css-extract-plugin": "^2.5.3",
    "style-loader": "^3.3.1",
    "webpack": "^5.67.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.7.3",
    "webpack-merge": "^5.8.0"
},
"dependencies": {
    "core-js": "^3.20.3"
},

webpack5-boilerplate这个脚手架,核心的就这些依赖,另外需要的依赖再自己装就好了。是不是觉得依赖少了很多,我是顿时觉得很舒服。接下来讲一下这些不需要用到的插件,如何在Webpack5里面用别的方式替代。

使用Asset Module模块,来管理资源

官方解释:资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。

以编译图片为例,所以如果我们要编译图片:

const 
maxSize = 10 * 1024,
outImageFileName = 'img/',
proResFileName = 'assets/';

/**
 * @maxSize 如果图片小于10Kb,会被转为base64
 * @outImageFileName 要导出到哪个文件夹,如果写在filename配置里面,则会导出到这个文件夹上
 * @proResFileName outputPath指的也是把该资源存放到proResFileName文件夹下
 */
module: {
    rules: [
        {
            test: /\.(png|svg|jpg|jpeg|gif)$/i,
            type: 'asset',
            // 设置图片导出大小,如果小于预设的值,则会被转化成base64
            parser: {
                dataUrlCondition: {
                    maxSize
                }
            },

            // 设置导出的路径为 img
            generator: {
                filename: `${outImageFileName}[name]-[hash:2][ext][query]`,
                outputPath: proResFileName
            }
        },
    ]
}

参考文章:

使用output里面配置,在生成文件之前清空output目录的内容

这样我们就可以不需要安装clean-webpack-plugin这个插件了

output: {
    clean: true
};

参考文章:

使用mini-css-extract-plugin插件来压缩css代码

// Webpack5压缩配置
optimization: {
    minimizer: [
        // 压缩css
        new CssMinimizerPlugin(),

        // '...' 来访问默认值。(不加的话,js不会压缩)
        '...'
    ],
},
// Webpack4压缩配置
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

plugins: [
    // 压缩css
    new OptimizeCssAssetsPlugin({
        assetNameRegExp: /\.css$/g,
        cssProcessor: require('cssnano'), //用于优化\最小化 CSS 的 CSS 处理器,默认为 cssnano
        cssProcessorOptions: { safe: true, discardComments: { removeAll: true } }, //传递给 cssProcessor 的选项,默认为{}
        canPrint: true //布尔值,指示插件是否可以将消息打印到控制台,默认为 true
    }),
]

Webpack5压缩css的配置对比起Webpack4的更加简单。

参考文章:

Babel依赖配置

  • @babel/polyfillBabel 7.4.0就被弃用了。所以不用在安装@babel/polyfill这个插件了
  • Babel是一个个人觉得蛮复杂的体系,大家可以好好阅读下面这几篇文章,读多几遍好好理解一下

参考文章:

关于devServer配置的理解

我想大家最懵圈的应该就是devServer.staticWebpack5staticWebpack4contentBase)这个配置了吧。是不是一直觉得,如果把里面的路径配置指向了我们打包出来的文件夹名字(dist),然后开启了webpack-dev-server服务器,就是访问的我们打包的那个资源(dist),其实并不是。这里大家可以自己建一个最简单的demo,然后配置改成下面这样:

output: {
    path: path.resolve(__dirname, `build`),
},
devServer: {
    static: {
        directory: path.resolve(__dirname, `outDir`),
    },
}

此时打包出来的文件夹是build,但是我们开启服务器访问的时候,访问是outDir文件夹,结果页面显示的还是我们的开发的index.html的内容,这就说明devServer.static的配置,根本就不是控制开启了webpack-dev-server服务器后访问的文件目录。这是经过本人测试,分析后的个人理解。

devServer.static,实际上指的是:一个存放,不经过Webpack编译的静态资源目录,他是一个目录。它的功能就很像是vue-cli里面的public文件夹,我们开发的时候,可以通过./或者../访问到那个资源(具体看目录关系)。

怎么访问到devServer.static.directory里面的文件

首先,我们先清楚这几点:

  1. 开启webpack-dev-server服务器时,以webpack5-boilerplate为例,我们的代码会根据我们的配置,在内存中生成一个打包文件,保存在内存中的打包文件目录结构:
    (http://localhost:8080/)
    ├── js
    ├── img
    ├── font
    ├── media
    ├── favicon.ico
    ├── index.html
    └── share.html
    
  2. 开启webpack-dev-server服务器时,devServer.static.directory里面的文件会直接被映射到根目录下
  3. devServer.static.directory,默认指向的是public文件夹。

OK,我们在根目录下新建一个public的文件夹,里面放一个test.txt文件。开启webpack-dev-server,打开http://localhost:8080/test.txt,我们就可以访问到这个不经打包的静态资源了。此时保存在内存中的文件目录结构就变成了:

(http://localhost:8080/)
├── js
├── img
├── font
├── media
├── favicon.ico
├── test.txt (直接被映射到根目录下)
├── index.html
└── share.html

所以想要访问devServer.static.directory的内容就是:http://localhost:8080/(文件名字)

注意:
如果在public里面新建一个index.html,访问http://localhost:8080/index.html或者http://localhost:8080/时,内容是我们的开发的index.html模板,这是因为我们的配置把编译后的index.html输出在dist文件夹根目录了,此时覆盖掉了public/index.html(可以在插件HtmlWebpackPlugin,把输的filename,设置为filename: index2.html,在public下新建一个index.html,此时访问http://localhost:8080/就是public里面的index.html)
所以我们在public文件夹里面,要避免与被编译的文件同名,否则会被覆盖掉。

关于devServer.devMiddleware.publicPath配置说明

devServer.devMiddleware.publicPath对应的是Webpack4里面的devServer.publicPath,以下简称publicPath
在没有配置publicPath的时候,我们开启webpack-dev-server,访问http://localhost:8080/得到的是覆盖掉public/index.html的编译后的模板index.html。因为publicPath默认值是:''指向根目录,所以我们访问http://localhost:8080/就是根目录,不用在后面加路径。
但是如果我们想类似以下访问我们的开发页面:http://localhost:8080/test/,我们只要将配置设置成:

output: {
    publicPath: '/test/',
},
devServer: {
    /**
     * 表示打包生成的静态文件所在的位置,意思是url访问的路径
     * 改变dist访问的路径,outpath需要跟他一致,启动访问的url为http://localhost:8080/test/index.html
     */
    devMiddleware: {
        publicPath: '/test/',
    },
}

此时我们访问的开发页面的路径就是:http://localhost:8080/test/

注意:output.publicPathdevServer.devMiddleware.publicPath要始终保持一致,不然会有问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容