webpack5初体验和性能优化配置介绍

webpack5使用

1.安装依赖包

  • 创建一个文件夹
  • npm init 生成package.json文件夹 然后安装依赖
    cnpm webpack webpack-cli html-webpack-plugin webpack-dev-server cross-env -D
  • 新建一个webpack.config.js文件写配置
  • 新建src/inde.js 文件
  • 新建模板文件 src/index.html
  • packjson命令
"scripts": {
     
    "build": "webpack",  // 直接打包用
    "start": "webpack serve", // 启动服务器 可以开发用
  },
  • 配置好entry 和 output等基本信息就可以使用基础版本的了
module.exports = {
     
    mode: 'development', // 配置的模式
    devtool: 'source-map', // 调试工具
    context: process.cwd(), // node命令运行的进程的当前目录 就是这个项目根目录
    entry: {
     
        main: './src/index.js'
    },
    output: {
     
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    module: {
     
     
    },
    plugins: [
        new HtmlWebpackPlugin({
     
            template: './src/index.html',
            minify: {
     
                // 压缩html
                collapseWhitespace: true, // 压缩空白
                removeComments: true // 去除注释
            }
        }),
    ]
};

2.安装插件

2.1 日志美化安装

  • friendly-errors-webpack-plugin 可以识别某类别的 webpack 错误,并清理,聚合和优先级,以提供更好的开发人员体验
    cnpm i friendly-errors-webpack-plugin node-notifier -D
  • 使用错误提示插件
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const notifier = require('node-notifier');
const icon = path.join(__dirname, 'icon.jpg');

 plugins: [
    ...
	+  new FriendlyErrorsWebpackPlugin({
     
    +        onErrors: (severity, errors) => {
     
    +            let error = errors[0];
    +            notifier.notify({
     
    +                title: 'webpack编译失败了',
    +                message: severity + ':' + error.name,
    +                subtitle: error.file || '',
    +                icon
    +            });
    +        }
    +    }),
  ]

2.2 速度分析

  • speed-measure-webpack5-plugin 进行分析打包速度
cnpm i speed-measure-webpack5-plugin -D
const SpeedMeasureWebpack5Plugin = require('speed-measure-webpack5-plugin');
const smw = new SpeedMeasureWebpack5Plugin();
module.exports = smw.wrap({
     
	// 配置文件
	mode: 'development', // 配置的模式
    devtool: 'source-map', // 调试工具
    context: process.cwd(), // node命令运行的进程的当前目录 就是这个项目根目录
    entry: {
     
        main: './src/index.js'
    },
    output: {
     
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    module: {
     
     
    },
    plugins: [
       
    ]
})

时间分析
webpack5初体验和性能优化配置介绍_第1张图片

2.3 文件体积监控

  • webpack-bundle-analyzer 是一个 webpack 插件,需要配合 webpack 和 webpack-cli 一起使用, 生产代码分析报告,
  • 可以分析打包出文件的大小,依赖关系,压缩大小如何等。

2.3.1 安装

cnpm i webpack-bundle-analyzer -D
const {
      BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

  
  plugins: [
    ...
	 +   new BundleAnalyzerPlugin({
     
     +       analyzerMode: 'disabled', // 不启动展示打包报告的HTTP服务器 也可以启动 直接可以看效果
     +       generateStatsFile: true // 要生成stats.json文件
     +   }),
  ]      

命令:

"build": "webpack",   // 会生成stats.json文件    
  // 下次想看分析效果就执行analyzer  启动服务看
 "analyzer": "webpack-bundle-analyzer --port 8888 ./dist/stats.json"

3.编译时间优化

  • 减少要处理的文件
  • 缩小查找的范围

3.1 缩小查找范围

3.1.1 extensions

  • 指定 extensions 之后可以不用再 require 或是 import 的时候加文件拓展名
  • 查找的时候会依次尝试添加拓展名进行匹配
resolve:{
    extensions: ['.js', '.jsx','.json']
}

3.1.2 alias

  • 配置别名加快 webpack 查找模块的速度
  • 每当引入 bootstrap 模块的时候,它会直接引入 bootstrap 而不需要从 node_modules 文件夹中按模块的查找规则查找
安装 cnpm i bootstrap css-loader style-loader -S

const bootstrap = path.resolve(
    __dirname,
    'node_modules/bootstrap/dist/css/bootstrap.css'
);
 alias: {
            bootstrap // 查找别名
    },

3.2缓存

  • 利用缓存
  • 重新构件时会尝试读取缓存, 从而提高打包速度
  • 缓存存放位置 node_modules/.cache/babel-loader
  module: {
        rules: [
            {
                test: /\.js$/,
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/, // 不解析
                use: [
                    // 开启多线程池  弊端开线程和线程通信需要时间的
                    {
                        loader: 'thread-loader',
                        options: { workers: 3 }
                    },
                    {
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: true // 自动babel缓存
                        }
                    }
                ]
            },
         ]
     }

3.3 cache-loader

  • 在一些性能开销大的 loader 之前添加此 loader, 可以将结果缓存在磁盘中
  • 默认保存在 node_modules/.cache/cache-loader 目录下
cnpm i cache-loader -D
 {
     
       test: /\.css$/,
       use: [
           'cache-loader',
           'css-loader'
       ]
   }

3.4 hard-source-webpack-plugin

  • hardSourceWebpackPlugin 为模块提供了中间缓存, 缓存默认存放的路径是 node_modules/.cache/hard-source
  • 首次构建无太大变化, 第二次构建时间大约可以减少 80%
  • webpack5 已经内置了模块缓存,不需要再使用此插件

4.编译体积优化

4.1 压缩 js、css、HTML 和图片

  • optimize-css-assets-webpack-plugin 是一个优化和压缩 css 资源的插件
  • terser-webpack-plugin 是一个优化和压缩 js 资源的插件
  • image-webpack-loader 可以帮助我们对图片进行压缩和优化

4.1.2 安装

cnpm i terser-webpack-plugin optimize-css-assets-webpack-plugin image-webpack-loader -D
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin');


{
     
	   // js压缩
    optimization: {
     
        minimize: true, // 开始最小化
        minimizer: [new TerserWebpackPlugin()]
    },
    
     module: {
     
        rules: [
            {
     
                test: /\.(jpg|png|gif|bmp)$/,
                use: [
                    {
     //  图片压缩
    +                    loader: 'image-webpack-loader',
                        options: {
     
                            mozjpeg: {
     
                                progressive: true
                            },
                            // optipng.enabled: false will disable optipng
                            optipng: {
     
                                enabled: false
                            },
                            pngquant: {
     
                                quality: [0.65, 0.9],
                                speed: 4
                            },
                            gifsicle: {
     
                                interlaced: false
                            },
                            // the webp option will enable WEBP
                            webp: {
     
                                quality: 75
                            }
                        }
                    }
                ]
            },
         
        ]
    },
 	plugins: [
    	...
    +   new OptimizeCssAssetsWebpackPlugin() // 压缩css
	]  

}	


4.2 清除无用的 css

  • purgecss-webpack-plugin mini-css-extract-plugin 单独提取 css 并清除用不到的 css

4.2.1 安装

cnpm i purgecss-webpack-plugin mini-css-extract-plugin -D
const PurgecssWebpackPlugin = require('purgecss-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const glob = require('glob');

const PATHS = {
     
    src: path.resolve(__dirname, 'src')
};
module: {
     
	rules: [
	         {
     
	                test: /\.css$/,
	                use: [
	                    'cache-loader',
	                    'log-loader',
	           +         MiniCssExtractPlugin.loader,  // 在css loader 前引入
	                    'css-loader'
	                ]
	            }
	],
},

plugins: [
       // 提取的css文件名
 +       new MiniCssExtractPlugin({
     
 +           filename: '[name].css'
 +       }),
 +      // /**/*   **匹配任意字段 包括路径分隔符  *匹配任意字符 不包含路径分隔符 、、
        // 去除无用css
        new PurgecssWebpackPlugin({
     
            paths: glob.sync(`${
       PATHS.src}/**/*`, {
      nodir: true })
        }),
 +
]

5. 环境

4.1 mode 的默认值

  • webpack 的 mode 默认 production
  • webpack serve 的 mode 默认为 development
  • 可以在模块内通过 process.env.NODE_ENV 获取当前环境变量, 无法在 webpack 配置文件中获取此变量

4.2 修改

  • 命令行加–mode=production 可以赋值 可以覆盖掉配置文件 优先级 默认 mode

4.3 DefinePlugin修改

  • 设置全局变量 所有模块都能读取该变量的值
  • 可以在任意模块内通过 process.env.NODE_ENV 获取当前的环境变量
  • 但无法在 node 环境(webpack 配置文件中)下获取当前的环境变量
 // 定义全局变量 修改process.env.NODE_ENV
 plugins: [
     new webpack.DefinePlugin({
     
	    'process.env.NODE_ENV': JSON.stringify('production'),
	    ENV: JSON.stringify('ENV')
	})
]

  • 模块代码可以读取上面定义的变量
    webpack5初体验和性能优化配置介绍_第2张图片

4.4 cross-env 设置

npm i cross-env -D

命令行

"build1": "cross-env NODE_ENV=development webpack",

可以在配置文件读到该值cross-env设置的值添加按到 process.env对象里面
webpack5初体验和性能优化配置介绍_第3张图片

4.5 .env文件修改

根目录新建.env文件

// .env文件内容
NODE_ENV=development
ENV=TEST
cnpm i dotenv -D
// 可以读取.env文件, 获取里面的值 设置到process.env里面
require('dotenv').config();

webpack5初体验和性能优化配置介绍_第4张图片

小结

webpack5和webpack4配置基本差不多,使用上不会有太大区别, dll 已经去除了,使用 hard-source-webpack-plugin代替等。

  • 通过持久化缓存提高性能
  • 采用更好的持久化缓存算法和默认行为
  • 通过优化 Tree Shaking 和代码生成来减小Bundle体积
  • 提高 Web 平台的兼容性
  • 清除之前为了实现 Webpack4 没有不兼容性变更导致的不合理 state
  • 尝试现在引入重大更改来为将来的功能做准备,以使我们能够尽可能长时间地使用 Webpack 5
  • 自动 Polyfills 一些 Node 模块(例如 crypto)无疑会增加打包体积,在 Webpack5 之后去掉了这个自动行为

附:
试验过程的完整配置

/*
 * @description:
 * @author: steve.deng
 * @Date: 2020-12-19 06:51:55
 * @LastEditors: steve.deng
 * @LastEditTime: 2020-12-22 14:38:50
 */
const path = require('path');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const notifier = require('node-notifier');
const icon = path.join(__dirname, 'icon.jpg');
const SpeedMeasureWebpack5Plugin = require('speed-measure-webpack5-plugin');
const {
      BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const smw = new SpeedMeasureWebpack5Plugin();
const selfLoadersPath = path.resolve(__dirname, 'loader');
const webpack = require('webpack');
const TerserWebpackPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const ImageWebpackLoader = require('image-webpack-loader');
const PurgecssWebpackPlugin = require('purgecss-webpack-plugin');
// 因为css和js加载可以并行 所以我们可以通过此插件提取css为单独的文件 然后去掉无用css 进行压缩
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const glob = require('glob');
const {
      DefinePlugin } = require('webpack');
const PATHS = {
     
    src: path.resolve(__dirname, 'src')
};
const bootstrap = path.resolve(
    __dirname,
    'node_modules/bootstrap/dist/css/bootstrap.css'
);
// 可以读取.env文件, 获取里面的值 设置到process.env.NODE_ENV里面
require('dotenv').config();
console.log('.env process.env.NODE_ENV', process.env.NODE_ENV);
console.log('.env ENV', process.env.ENV);
// 默认值undefined 无法在配置文件中获取   在模块代码内可以获取
console.log('process.env.NODE_ENV', process.env.NODE_ENV);
module.exports = smw.wrap({
     
    // mode: 'development', // 配置的模式
    devtool: 'source-map', // 调试工具
    context: process.cwd(), // node命令运行的进程的当前目录 就是这个项目根目录
    entry: {
     
        main: './src/index.js'
    },
    output: {
     
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js'
    },
    // js压缩
    optimization: {
     
        minimize: true, // 开始最小化
        minimizer: [new TerserWebpackPlugin()]
    },
    resolve: {
     
        extensions: ['.js', '.jsx', '.json'], // 指定扩展名
        alias: {
     
            bootstrap // 查找别名
        },
        modules: ['node_modules'], // 指定查找目录
        mainFields: ['browser', 'module', 'main'], // 从package.json中的哪个字段查找入口文件
        mainFiles: ['index'] // 如果找不到mainFields的话 会找索引文件 index.js
    },
    resolveLoader: {
     
        modules: [selfLoadersPath, 'node_modules'] // selfLoadersPath 自定义loader解析
    },
    externals: {
     
        jquery: 'jQuery'
    },
    module: {
     
        rules: [
            {
     
                test: /\.js$/,
                include: path.resolve(__dirname, 'src'),
                exclude: /node_modules/, // 不解析
                use: [
                    // 开启多线程池  弊端开线程和线程通信需要时间的
                    {
     
                        loader: 'thread-loader',
                        options: {
      workers: 3 }
                    },
                    {
     
                        loader: 'babel-loader',
                        options: {
     
                            cacheDirectory: true // 自动babel缓存
                        }
                    }
                ]
            },
            {
     
                test: /\.(jpg|png|gif|bmp)$/,
                use: [
                    {
     
                        loader: 'image-webpack-loader',
                        options: {
     
                            mozjpeg: {
     
                                progressive: true
                            },
                            // optipng.enabled: false will disable optipng
                            optipng: {
     
                                enabled: false
                            },
                            pngquant: {
     
                                quality: [0.65, 0.9],
                                speed: 4
                            },
                            gifsicle: {
     
                                interlaced: false
                            },
                            // the webp option will enable WEBP
                            webp: {
     
                                quality: 75
                            }
                        }
                    }
                ]
            },
            {
     
                test: /\.css$/,
                use: [
                    'cache-loader',
                    'log-loader',
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
     
            template: './src/index.html',
            minify: {
     
                // 压缩html
                collapseWhitespace: true, // 压缩空白
                removeComments: true // 去除注释
            }
        }),
        new MiniCssExtractPlugin({
     
            filename: '[name].css'
        }),
        // /**/*   **匹配任意字段 包括路径分隔符  *匹配任意字符 不包含路径分隔符 、、
        // 去除无用css
        new PurgecssWebpackPlugin({
     
            paths: glob.sync(`${
       PATHS.src}/**/*`, {
      nodir: true })
        }),
        new FriendlyErrorsWebpackPlugin({
     
            onErrors: (severity, errors) => {
     
                let error = errors[0];
                notifier.notify({
     
                    title: 'webpack编译失败了',
                    message: severity + ':' + error.name,
                    subtitle: error.file || '',
                    icon
                });
            }
        }),
        new BundleAnalyzerPlugin({
     
            analyzerMode: 'disabled', // 不启动展示打包报告的HTTP服务器
            generateStatsFile: true // 要生成stats.json文件
        }),
        // 忽略模块打包 比如语言包
        new webpack.IgnorePlugin({
     
            resourceRegExp: /^\.\/locale$/, // 资源正则
            contextRegExp: /moment$/ // 上下文, 目录正则
        }),
        // 定义全局变量
        new webpack.DefinePlugin({
     
            // 定义在编译使用的全局变量 在浏览器运行阶段时就是值了
            // 'process.env.NODE_ENV': JSON.stringify('production'),
            'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
            ENV: JSON.stringify('ENV')
        }),
        new OptimizeCssAssetsWebpackPlugin() // 压缩css
    ]
});

你可能感兴趣的:(webpack)