webpack 知识系列第五篇

133 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

一、tree shaking

  1. 创建文件

  2. 修改配置文件

    • 定义 nodejs 环境变量:决定使用 browserslist 的哪个环境
    • 复用 loader
    • 需要在 package.json 中定义 browserslist
    • 在 package.json 中 eslintConfig --> airbnb
    • 一个文件只能被一个 loader 处理。当一个文件要被多个 loader 处理,那么一定要指定 loader 执行的先后顺序
    • 开启 babel 缓存,第二次构建时,会读取之前的缓存

先执行 eslint 在执行 babel

  1. 运行指令: webpack

二、code split

  1. 创建文件
  2. 修改配置文件
    • 多入口:有一个入口,最终输出就有一个 bundle
    • [name]:取文件名
    • 可以将 node_modules 中代码单独打包一个 chunk 最终输出
    • 自动分析多入口 chunk 中,有没有公共的文件。如果有会打包成单独一个 chunk
  3. 运行指令: webpack

三、lazy loading

  1. 创建文件
  2. 修改配置文件
  3. 运行指令: webpack

四、pwa

  1. 创建文件

  2. 下载安装包

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

  3. 修改配置文件

    • PWA: 渐进式网络开发应用程序(离线可访问),workbox --> workbox-webpack-plugin
    • 定义 nodejs 环境变量:决定使用 browserslist 的哪个环境
    • 需要在 package.json 中定义 browserslist
    • 在 package.json 中 eslintConfig --> airbnb
  4. 运行指令:webpack

五、多进程打包

  1. 创建文件

  2. 下载安装包

    npm install --save-dev thread-loader

  3. 修改配置文件

    • 开启多进程打包。
    • 进程启动大概为 600ms,进程通信也有开销。
    • 只有工作消耗时间比较长,才需要多进程打包
  4. 运行指令:webpack

六、externals

  1. 创建文件

  2. 修改配置文件

    拒绝 jQuery 被打包进来

  3. 运行指令:webpack

七、dll

  1. 创建文件

  2. 修改配置文件

    • 告诉 webpack 哪些库不参与打包,同时使用时的名称也得变~
    • 将某个文件打包输出去,并在 html 中自动引入该资源
  3. 运行指令:webpack

八、 webpack 配置详情

1、entry

  1. 创建文件

    image.png

  2. 修改配置文件

    const { resolve } = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        entry: {
            index: ['./src/index.js', './src/count.js'],
            add: './src/add.js'
        },
        output: {
            filename: '[name].js',
            path: resolve(__dirname, 'build')
        },
        plugins: [new HtmlWebpackPlugin()],
        mode: 'development'
    };
    
  3. 运行指令:webpack

2、output

  1. 创建文件

    image.png

  2. 修改配置文件

    • library: '[name]', // 整个库向外暴露的变量名
    • libraryTarget: 'window' // 变量名添加到哪个上 browser
    • libraryTarget: 'global' // 变量名添加到哪个上 node
    • libraryTarget: 'commonjs'
  3. 运行指令:webpack

3、module

  1. 创建文件

  2. 修改配置文件

    const { resolve } = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        entry: './src/index.js',
        output: {
            filename: 'js/[name].js',
            path: resolve(__dirname, 'build')
        },
        module: {
            rules: [
                // loader 的配置
                {
                    test: /\.css$/,
                    // 多个 loader 用 use
                    use: ['style-loader', 'css-loader']
                },
                {
                    test: /\.js$/,
                    // 排除 node_modules 下的 js 文件
                    exclude: /node_modules/,
                    // 只检查 src 下的 js 文件
                    include: resolve(__dirname, 'src'),
                    // 优先执行
                    enforce: 'pre',
                    // 延后执行
                    // enforce: 'post',
                    // 单个 loader 用 loader
                    loader: 'eslint-loader',
                    options: {}
                },
                {
                    // 以下配置只会生效一个
                    oneOf: []
                }
            ]
        },
        plugins: [new HtmlWebpackPlugin()],
        mode: 'development'
    };
    
  3. 运行指令:webpack

4、resolve

  1. 创建文件

  2. 修改配置文件

    const { resolve } = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
        entry: './src/js/index.js',
        output: {
            filename: 'js/[name].js',
            path: resolve(__dirname, 'build')
        },
        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: ['style-loader', 'css-loader']
                }
            ]
        },
        plugins: [new HtmlWebpackPlugin()],
        mode: 'development',
        // 解析模块的规则
        resolve: {
            // 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
            alias: {
                $css: resolve(__dirname, 'src/css')
            },
            // 配置省略文件路径的后缀名
            extensions: ['.js', '.json', '.jsx', '.css'],
            // 告诉 webpack 解析模块是去找哪个目录
            modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
        }
    };
    
  3. 运行指令:webpack

5、dev server

  1. 创建文件
  2. 修改配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
    entry: './src/js/index.js',
    output: {
        filename: 'js/[name].js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    },
    plugins: [new HtmlWebpackPlugin()],
    mode: 'development',
    resolve: {
        alias: {
            $css: resolve(__dirname, 'src/css')
        },
        extensions: ['.js', '.json', '.jsx', '.css'],
        modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
    },
    devServer: {
        // 运行代码的目录
        contentBase: resolve(__dirname, 'build'),
        // 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
        watchContentBase: true,
        watchOptions: {
            // 忽略文件
            ignored: /node_modules/
        },
        // 启动 gzip 压缩
        compress: true,
        // 端口号
        port: 5000,
        // 域名
        host: 'localhost',
        // 自动打开浏览器
        open: true,
        // 开启 HMR 功能
        hot: true,
        // 不要显示启动服务器日志信息
        clientLogLevel: 'none',
        // 除了一些基本启动信息以外,其他内容都不要显示
        quiet: true,
        // 如果出错了,不要全屏提示~
        overlay: false,
        // 服务器代理 --> 解决开发环境跨域问题
        proxy: {
            // 一旦 devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器
            (3000)
            '/api': {
                target: 'http://localhost:3000',
                // 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
};

6、optimization

  1. 创建文件
  2. 修改配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin')
module.exports = {
    entry: './src/js/index.js',
    output: {
        filename: 'js/[name].[contenthash:10].js',
        path: resolve(__dirname, 'build'),
        chunkFilename: 'js/[name].[contenthash:10]_chunk.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    },
    plugins: [new HtmlWebpackPlugin()],
    mode: 'production',
    resolve: {
        alias: {
            $css: resolve(__dirname, 'src/css')
        },
        extensions: ['.js', '.json', '.jsx', '.css'],
        modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
    },
    optimization: {
        splitChunks: {
        chunks: 'all'
        // 默认值,可以不写~
        },
        // 将当前模块的记录其他模块的 hash 单独打包为一个文件 runtime
        // 解决:修改 a 文件导致 b 文件的 contenthash 变化
        runtimeChunk: {
            name: entrypoint => `runtime-${entrypoint.name}`
        },
        minimizer: [
            // 配置生产环境的压缩方案:js 和 css
            new TerserWebpackPlugin({
                // 开启缓存
                cache: true,
                // 开启多进程打包
                parallel: true,
                // 启动 source-map
                sourceMap: true
            })
        ]
    }
};
  1. 运行指令:webpack

九、总结

本篇主要介绍了 webpack 其他优化配置,使得 webpack 高效的为我们服务,最后介绍了 webpack 配置详情,包括:entry、output、module、resolve、dev server、optimization。快来一起学习吧!