webpack5 汇总

准备:node.js 16以上版本

按照webpack webpack-cli

webpack 官方网站

一. 基本示例

 打包入口js

webpack ./1.demo/main.js --mode=development  

打包结果

二. webpack五大核心

1. entry 入口

2. output 输出

3. loader 加载器

4. plugins 插件

5. mode 模式

三. 简单配置

const path = require("path")
module.exports={
    //入口
    entry:"./main.js",
    //出口
    output:{
        path:path.resolve(__dirname,"dist"),
        filename:"main.js"
    },
    //加载器
    module:{
        rules:[
            //loader的配置
        ]
    },
    //插件
    plugins:[],
    //模式
    mode:"development"
}

四. 不同模式的区别

1. 开发模式:完成两个目的

(1)编译代码

(2)代码质量检测,树立代码规范

2. 生产模式

(1)编译代码

(2)压缩代码

五. 功能实现(开发模式)

1. 样式处理

(1)css

css-loader | webpack 中文文档

安装对应的loader

npm install --save-dev style-loader css-loader

配置

const path = require("path")
module.exports = {
    //入口
    entry: "./main.js",
    //出口
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "main.js"
    },
    //加载器
    module: {
        rules: [
            //loader的配置
            //css处理
            {
                test: /\.css$/i,
                //从右到左
                use: ["style-loader", "css-loader"],
            }
        ]
    },
    //插件
    plugins: [],
    //模式
    mode: "development"
}

 直接webpack打包

会被直接打包到js里

 (2)less(其他同理)

npm i -D less-loader

配置

const path = require("path")
module.exports = {
    //入口
    entry: "./main.js",
    //出口
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "main.js"
    },
    //加载器
    module: {
        rules: [
            //loader的配置
            //css处理
            {
                test: /\.css$/i,
                //从右到左
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.less$/i,
                //从右到左
                use: ["style-loader", "css-loader","less-loader"],
            }
        ]
    },
    //插件
    plugins: [],
    //模式
    mode: "development"
}

2. 图片资源处理

webpack4需要下载两个loader,webpack5已经将他俩内置。

将图片引入到样式中或者其他方式引用

@testColor: red;

.demo1 {
    width: 100px;
    height: 100px;
    background-color: @testColor;
}

.demo2 {
    width: 100px;
    height: 100px;
    background: url("../assets//imgs/demo.png");
    background-size: cover;
}

打包发现输出为原封不动的输出

使用loader进行处理。

例如转base64 减少服务器请求数量 但是体积会更大。

loader中配置

 {
                //图片处理
                test:/\.(png|jpe?g|gif|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb转换格式
                        maxSize:10*1024,//10kb
                    }
                }
            }

转换效果

 3. 控制输出路径。

js改变和图片改变写法有不同

const path = require("path")
module.exports = {
    //入口
    entry: "./main.js",
    //出口
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "js/main.js",
        clean:true
    },
    //加载器
    module: {
        rules: [
            //loader的配置
            //css处理
            {
                test: /\.css$/i,
                //从右到左
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.less$/i,
                //从右到左
                use: ["style-loader", "css-loader","less-loader"],
            },
            {
                //图片处理
                test:/\.(png|jpe?g|gif|webp|svg)$/,
                type:"asset",
                parser:{
                    dataUrlCondition:{
                        //小于10kb转换格式
                        maxSize:10*1024,//10kb
                    }
                },
                generator:{
                    //hash文件唯一id  ext 扩展名  query 携带请求参数
                    filename:'static/imgs/[hash:10][ext][query]'
                }
            }
        ]
    },
    //插件
    plugins: [],
    //模式
    mode: "development"
}

4. 处理其他资源

都是只需要原封不动输出,只是修改路径。原封不动输出

type设置为asset/resource

5. 处理js

处理格式和兼容性

主要用两个 eslint和babel

eslint我不想用,不写了

babel:中文文档 Babel 是什么? · Babel 中文网

安装

npm install -D babel-loader @babel/core @babel/preset-env

6. 处理html资源

无需手动引用js

使用插件 HtmlWebpackPlugin | webpack 中文文档

npm install --save-dev html-webpack-plugin

使用

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

module.exports = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js',
  },
  plugins: [new HtmlWebpackPlugin()],
};

效果

但是之前的结构会消失,要让他依照我们之前的为模板

  new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "public/index.html")
        }),

效果

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
<script defer src="js/main.js"></script></head>

<body>
    <div class="demo1"></div>
    <div class="demo2"></div>
    <div class="demo3"></div>
</body>

</html>

7. 开发服务器devServer

安装

npm i -D webpack-dev-server

使用,直接加在与plugins同级就好

devServer: {
        static: {
            directory: path.join(__dirname, 'public'),
        },
        compress: true,
        port: 9000,
        open: true
    },

使用命令

webpack serve打开开发服务器

六. 功能实现(生产模式)

1. 首先将生产模式与开发模式的js配置分开

两者如下

 开发模式

const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    //入口
    entry: "./main.js",
    //出口
    output: {
        path: undefined, //开发模式无输出
        filename: "js/main.js",
        clean: true
    },
    //加载器
    module: {
        rules: [
            //loader的配置
            //css处理
            {
                test: /\.css$/i,
                //从右到左
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.less$/i,
                //从右到左
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                //图片处理
                test: /\.(png|jpe?g|gif|webp|svg)$/,
                //asset转base64 asset/resource 原封不动
                type: "asset",
                parser: {
                    dataUrlCondition: {
                        //小于10kb转换格式
                        maxSize: 10 * 1024,//10kb
                    }
                },
                generator: {
                    //hash文件唯一id  ext 扩展名  query 携带请求参数
                    filename: 'static/imgs/[hash:10][ext][query]'
                }
            },
            {
                //babel
                test: /\.m?js$/,
                //排除哪些不处理
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
                //下面的单独写在babel.config.js中
                //   options: {
                //     presets: ['@babel/preset-env']
                //   }
            }
        ]
    },
    //插件
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html")
        }),
    ],
    devServer: {
        static: {
            directory: path.join(__dirname, '../public'),
        },
        compress: true,
        port: 9000,
        open: true
    },
    //模式
    mode: "development"

}

生产模式

const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    //入口
    entry: "./main.js",
    //出口
    output: {
        path: path.resolve(__dirname,"../dist"), //生产模式有输出
        filename: "static/js/main.js",
        clean: true
    },
    //加载器
    module: {
        rules: [
            //loader的配置
            //css处理
            {
                test: /\.css$/i,
                //从右到左
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.less$/i,
                //从右到左
                use: ["style-loader", "css-loader", "less-loader"],
            },
            {
                //图片处理
                test: /\.(png|jpe?g|gif|webp|svg)$/,
                //asset转base64 asset/resource 原封不动
                type: "asset",
                parser: {
                    dataUrlCondition: {
                        //小于10kb转换格式
                        maxSize: 10 * 1024,//10kb
                    }
                },
                generator: {
                    //hash文件唯一id  ext 扩展名  query 携带请求参数
                    filename: 'static/imgs/[hash:10][ext][query]'
                }
            },
            {
                //babel
                test: /\.m?js$/,
                //排除哪些不处理
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
                //下面的单独写在babel.config.js中
                //   options: {
                //     presets: ['@babel/preset-env']
                //   }
            }
        ]
    },
    //插件
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html")
        }),
    ],
    //模式
    mode: "production"
}

使用方式

webpack --config ./config/webpack.prod.js

因为指令太长 可以提前在package.json中配置

 接下来就和脚手架一样了,只需要npm run dev/build

2. 单独提取css

原因一个是文件单独提取利于维护查看,另一个是以style的方式加入会影响html的解析,出现白屏闪屏的现象,用link标签则不会。

使用插件 MiniCssExtractPlugin | webpack 中文文档

npm install --save-dev mini-css-extract-plugin

这个就不写例子了直接看文档就行。

3. 样式兼容 

npm i postcss-loader postcss postcss-preset-env -D

设置兼容的程度  这里是ie8

 使用

在cssloader之后

const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
    //入口
    entry: "./main.js",
    //出口
    output: {
        path: path.resolve(__dirname, "../dist"), //生产模式有输出
        filename: "static/js/main.js",
        clean: true
    },
    //加载器
    module: {
        rules: [
            //loader的配置
            //css处理
            {
                test: /\.css$/i,
                //从右到左
                use: [MiniCssExtractPlugin.loader,
                    "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env" //解决大多数样式兼容性问题
                            ]
                        }
                    }
                }
                ],
            },
            {
                test: /\.less$/i,
                //从右到左
                use: [MiniCssExtractPlugin.loader,
                    "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env" //解决大多数样式兼容性问题
                            ]
                        }
                    }
                },
                    "less-loader"],
            },
            {
                //图片处理
                test: /\.(png|jpe?g|gif|webp|svg)$/,
                //asset转base64 asset/resource 原封不动
                type: "asset",
                parser: {
                    dataUrlCondition: {
                        //小于10kb转换格式
                        maxSize: 10 * 1024,//10kb
                    }
                },
                generator: {
                    //hash文件唯一id  ext 扩展名  query 携带请求参数
                    filename: 'static/imgs/[hash:10][ext][query]'
                }
            },
            {
                //babel
                test: /\.m?js$/,
                //排除哪些不处理
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
                //下面的单独写在babel.config.js中
                //   options: {
                //     presets: ['@babel/preset-env']
                //   }
            }
        ]
    },
    //插件
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename: "static/style/main.css"
        })
    ],
    //模式
    mode: "production"
}

打包后的效果

 实际工作一般用不到这么离谱的兼容,何况ie已经亡了

一般是这个配置

  "browserslist":[
    "last 2 version",
    "> 1%",
    "not dead"
  ]

4. css压缩

CssMinimizerWebpackPlugin | webpack 中文文档

直接看文档

使用不用看文档太复杂了

直接

效果

 

 5. 生产模式下的基本功能配置汇总

const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
    //入口
    entry: "./main.js",
    //出口
    output: {
        path: path.resolve(__dirname, "../dist"), //生产模式有输出
        filename: "static/js/main.js",
        clean: true
    },
    //加载器
    module: {
        rules: [
            //loader的配置
            //css处理
            {
                test: /\.css$/i,
                //从右到左
                use: [MiniCssExtractPlugin.loader,
                    "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env" //解决大多数样式兼容性问题
                            ]
                        }
                    }
                }
                ],
            },
            {
                test: /\.less$/i,
                //从右到左
                use: [MiniCssExtractPlugin.loader,
                    "css-loader",
                {
                    loader: "postcss-loader",
                    options: {
                        postcssOptions: {
                            plugins: [
                                "postcss-preset-env" //解决大多数样式兼容性问题
                            ]
                        }
                    }
                },
                    "less-loader"],
            },
            {
                //图片处理
                test: /\.(png|jpe?g|gif|webp|svg)$/,
                //asset转base64 asset/resource 原封不动
                type: "asset",
                parser: {
                    dataUrlCondition: {
                        //小于10kb转换格式
                        maxSize: 10 * 1024,//10kb
                    }
                },
                generator: {
                    //hash文件唯一id  ext 扩展名  query 携带请求参数
                    filename: 'static/imgs/[hash:10][ext][query]'
                }
            },
            {
                //babel
                test: /\.m?js$/,
                //排除哪些不处理
                exclude: /(node_modules|bower_components)/,
                loader: 'babel-loader',
                //下面的单独写在babel.config.js中
                //   options: {
                //     presets: ['@babel/preset-env']
                //   }
            }
        ]
    },
    //插件
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../public/index.html")
        }),
        new MiniCssExtractPlugin({
            filename: "static/style/main.css"
        }),
        new CssMinimizerPlugin()
    ],
    //模式
    mode: "production"
}

七. 高级功能

1. sourceMap(源代码映射)

在开发模式下,如果我们去调试webpack devServer生成的js,会与原来的文件有很大差异。使用sourceMap就会和源文件映射。

Devtool | webpack 中文文档 不同的映射模式

里面有一堆,但是我们实际开发只用两者

开发模式:cheap-module-source-map 行映射 打包快

生产模式:  source-map  行 列都映射 打包慢一些相对

2. 提升打包构建速度(HMR)

模块热替换(hot module replacement) | webpack 中文文档

按需更新,部分更新。

使用就是在devServe中加上 

 webpack5 这是默认开启。

3. oneOf

默认会使用所有的loader过一遍,但是我们希望它得到一个就停。

4. exclude include 排除什么文件/排除什么文件

5. 缓存eslint和babel的缓存,不需要每次都经过他俩扫描

6. 多线程打包

这个要注意文件体积小的话反而会更慢,因为线程的启动需要时间。如果文件体积很大可以使用。

7. 减少代码体积

Tree Shaking 移除js没有用到的代码。

已经默认配置了。

8. 减少babel插入辅助代码

安装

npm i @babel/plugin-transform-runtime -D

使用 babel.config.json

{
    "presets": [
      [
        "@babel/env",
        {
          "targets": {
            "edge": "17",
            "firefox": "60",
            "chrome": "67",
            "safari": "11.1"
          }
        }
      ]
    ],
    "plugins": ["@babel/plugin-transform-runtime"]
  }

9. 压缩图片

ImageMinimizerWebpackPlugin | webpack 中文文档

这里使用里面的无损压缩

(但是说实话,如果做简单的页面应用其实webpack自动压缩图片是可以的,如果本地图片非常多且非常大其实并不合适让其自动压缩,因为太太耗时了!!!)

这是我网上看到的评价,所以该功能慎用。

10. code split

代码分割,因为代码打包后在一个js中,这样不管打开哪个页面都会加载全部的js。所以要进行分割。

目的:分割代码,按需加载。

方案1:

最简单的,多入口打包

const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: {
        main1: "./main1",
        main2: "./main2"
    },
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "js/[name].js",
        clean: true
    },
    module: {
        rules: [

        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "public/index.html")
        })
    ],
    mode: "development"
}

优化方案:提取代码中的公共部分,避免重复打包main1和main2中的重复部分。

const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: {
        main1: "./main1",
        main2: "./main2"
    },
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "js/[name].js",
        clean: true
    },
    module: {
        rules: [

        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "public/index.html")
        })
    ],
    mode: "production",
    // 优化代码配置
    optimization: {
        //代码分割配置
        splitChunks:{
            chunks:"all" //对所有模块都分割
        }
    }
}

方案2:

单文件入口,多chunks,并且chunks自定义命名。

export default function setBtnClick() {
    document.getElementById("test").onclick = function () {
        import(/*webpackChunkName:"btnTest"*/"./hello").then(({ sayHello }) => {
            sayHello()
        })
    }
}

注意import里的注释是用来配置chunk的名字的。

const path = require('path')
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
    entry: "./main.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "js/[name].js",
        chunkFilename: "js/[name].js",
        clean: true
    },
    module: {
        rules: [

        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "public/index.html")
        })
    ],
    optimization: {
        splitChunks: {
            chunks: "all"
        }
    },
    mode: "production"
}

11. preload和prefetch

preload 立即加载资源

prefetch 空闲加载

特点是 只加载,不执行。

缺点是  兼容性差

使用插件进行配置

@vue/preload-webpack-plugin - npm

里面提示的安装指令有误:用下面的

 npm i -D @vue/preload-webpack-plugin

12. Network cache

先说场景

例如 main.js 引入 了 a.js 打包后生产【hash1】.js 和 【hash2.js】, 当我们改变【hash2】.js,该js文件的hash值会发生改变,可能是hash3,那么我们的【hash1】.js 也要发生改变因为里面有引入

import .. from hash2.js

为了不造成这种一个改变,所有的引入js都改变的情况,需要生成一个runtime来专门保存已经被引入的js的地址。

配置方式就是在代码分割下面加上一段配置。

    optimization: {
        splitChunks: {
            chunks: "all"
        },
        runtimeChunk:{
            name:(entrypoint)=> `runtime~${entrypoint.name}.js`
        }
    },

13. core.js

用来解决js兼容性问题,仅仅使用babel不能处理类似于promise asyn awit这些高版本语言,使用core.js进行转译。core就是babel的补充。

npm i core-js -D

安装 

在main js中引入

import "core-js"

打包后会生成对应的js

 当然上面只是全局引入的方式,我们也可以在Babel中配置让它自动按需引入。

@babel/preset-env · Babel 中文网

 安装babel和其他插件

npm install  babel-loader @babel/core @babel/preset-env -D

webpack中使用

    module: {
        rules: [{
            test: /\.js$/,
            use: {
                loader: "babel-loader"
            },
            exclude: /node_modules/
        }]
    },

babel中配置按需加载core

const presets = [
    [
        "@babel/preset-env",
        {
            targets: {
                chrome: "58",
                ie: "11"
            },
            useBuiltIns: "usage",
            corejs: 3 
        }
    ]
];
const plugins = [];
module.exports = {
    plugins,
    presets
};

14. PWA

给项目提供离线访问状态。

安装workbox插件

渐进式网络应用程序 | webpack 中文文档

npm install workbox-webpack-plugin --save-dev

完全按文档来就好,最后serviceworker可能会获取失败是因为我们的路劲是dist下,可以用serve dist运行html。

猜你喜欢

转载自blog.csdn.net/weixin_47964837/article/details/126119791