hgq's docs
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)

guoguoqiqi

漫不经心的向往
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)
  • webpack是什么、为什么选择它
  • webpack中module、chunk和bundle的概念
  • 说一下在webpack中的loader和plugin的不同
  • webpack 三种hash的区别
  • webpack基本核心概念
  • webpack工作机制
  • 常用的Loader
  • 常用的Plugin
  • webpack配置与优化实践
    • webpack热更新原理
    • 如何配置webpack热更新
    • 如何提升webpack构建速度
    • babel中polyfill的作用
    • npm和yarn的对比
    • 如何减小打包体积提高页面加载速度
    • 介绍SourceMap
    • 搭建一个前端工程
    • 自定义loader
    • 自定义plugin
    • 相关面试题集合
    • 相关文档网站
    • 对比一下webpack、vite、rollup等构建工具.md
    • loader、plugin的区别,以及编写的思路
    • css-loader和style-loader的区别
    • url-loader和file-loader的区别
    • webpack代码分割和公共代码提取
    • Webpack
    guoguoqiqi
    2022-02-14

    webpack配置与优化实践

    # webpack配置与优化实践

    • webpack.common.js
    const chalk = require('chalk')
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const ProgressBarPlugin = require('progress-bar-webpack-plugin');
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    const paths = require('./paths');
    
    const ctx = {
      isEnvDevelopment: process.env.NODE_ENV === 'development',
      isEnvProduction: process.env.NODE_ENV === 'production',
    }
    
    const {
      isEnvDevelopment,
      isEnvProduction
    } = ctx
    
    
    // 小型项目无需 thread-loader,因此注释了
    // const threadLoader = require('thread-loader');
    
    // threadLoader.warmup(
    //   {
    //     // 池选项,例如传递给 loader 选项
    //     // 必须匹配 loader 选项才能启动正确的池
    //   },
    //   [
    //     'sass-loader',
    //   ]
    // );
    
    
    module.exports = {
      // 入口
      entry: {
        index: './src/index.tsx',
      },
      // 输出
      output: {
        // 仅在生产环境添加 hash
        filename: ctx.isEnvProduction ? '[name].[contenthash].bundle.js' : '[name].bundle.js',
        path: paths.appDist,
        // 编译前清除目录
        clean: true,
        // publicPath: ctx.isEnvProduction ? 'https://xxx.com' : '', 关闭该 CDN 配置,因为示例项目,无 CDN 服务。
      },
      resolve: {
        alias: {
          '@': paths.appSrc,
        },
        extensions: ['.tsx', '.js'],
        modules: [
          'node_modules',
          paths.appSrc,
        ],
        symlinks: false,
      },
      plugins: [
        // 生成html,自动引入所有bundle
        new HtmlWebpackPlugin({
          title: 'release_v1',
        }),
        // 进度条
        new ProgressBarPlugin({
          format: `  :msg [:bar] ${chalk.green.bold(':percent')} (:elapsed s)`
        }),
      ],
      module: {
        rules: [
          {
            test: /\.(png|svg|jpg|jpeg|gif)$/i,
            include: paths.appSrc,
            type: 'asset/resource',
          },
          {
            test: /.(woff|woff2|eot|ttf|otf)$/i,
            include: paths.appSrc,
            type: 'asset/resource',
          },
          {
            test: /\.module\.(scss|sass)$/,
            include: paths.appSrc,
            use: [
              // 将 JS 字符串生成为 style 节点
              'style-loader',
              isEnvProduction && MiniCssExtractPlugin.loader, // 仅生产环境
              // 将 CSS 转化成 CommonJS 模块
              {
                loader: 'css-loader',
                options: {
                  // Enable CSS Modules features
                  modules: true,
                  importLoaders: 2,
                  // 0 => no loaders (default);
                  // 1 => postcss-loader;
                  // 2 => postcss-loader, sass-loader
                },
              },
              // 将 PostCSS 编译成 CSS
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      [
                        // postcss-preset-env 包含 autoprefixer
                        'postcss-preset-env',
                      ],
                    ],
                  },
                },
              },
              // {
              //   loader: 'thread-loader',
              //   options: {
              //     workerParallelJobs: 2
              //   }
              // },
              // 将 Sass 编译成 CSS
              'sass-loader',
            ].filter(Boolean),
          },
          {
            test: /\.(js|ts|jsx|tsx)$/,
            include: paths.appSrc,
            use: [
              {
                loader: 'esbuild-loader',
                options: {
                  loader: 'tsx',
                  target: 'es2015',
                },
              }
            ]
          }
        ],
      },
      cache: {
        type: 'filesystem', // 使用文件缓存
      },
    }
    
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    • webpack.dev.js
    const webpack = require('webpack')
    const { merge } = require('webpack-merge');
    const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
    const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
    const common = require('./webpack.common')
    
    const smp = new SpeedMeasurePlugin();
    
    const isNeedSpeed = true
    
    const config = merge(common, {
      // 模式
      mode: 'development',
      // 开发工具,开启 source map,编译调试
      devtool: 'eval-cheap-module-source-map',
      // 开发模式,自动更新改动
      devServer: {
        contentBase: './dist',
        hot: true, // 热更新
      },
      plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new ReactRefreshWebpackPlugin(),
      ],
    })
    
    module.exports = isNeedSpeed ? smp.wrap(config) : config
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    • webpack.prod.js
    const glob = require('glob')
    const { merge } = require('webpack-merge');
    const TerserPlugin = require('terser-webpack-plugin');
    // const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    const PurgeCSSPlugin = require('purgecss-webpack-plugin')
    const common = require('./webpack.common')
    const paths = require('./paths')
    
    module.exports = merge(common, {
      // 模式
      mode: 'production',
      plugins: [
        // 打包体积分析
        // new BundleAnalyzerPlugin(),
        // 提取 CSS
        new MiniCssExtractPlugin({
          filename: "[hash].[name].css",
        }),
        // CSS Tree Shaking
        new PurgeCSSPlugin({
          paths: glob.sync(`${paths.appSrc}/**/*`,  { nodir: true }),
        }),
      ],
      optimization: {
        runtimeChunk: true,
        moduleIds: 'deterministic',
        minimizer: [
          // 在 webpack@5 中,你可以使用 `...` 语法来扩展现有的 minimizer(即 `terser-webpack-plugin`),将下一行取消注释
          // `...`,
          // new CssMinimizerPlugin({
          //   parallel: 4,
          // }),
          new TerserPlugin({
            parallel: 4,
            terserOptions: {
              parse: {
                ecma: 8,
              },
              compress: {
                ecma: 5,
                warnings: false,
                comparisons: false,
                inline: 2,
              },
              mangle: {
                safari10: true,
              },
              output: {
                ecma: 5,
                comments: false,
                ascii_only: true,
              },
            },
          }),
        ],
        splitChunks: {
          // include all types of chunks
          chunks: 'all',
          // 重复打包问题
          cacheGroups:{
            vendors:{ // node_modules里的代码
              test: /[\\/]node_modules[\\/]/,
              chunks: "all",
              // name: 'vendors', 一定不要定义固定的name
              priority: 10, // 优先级
              enforce: true 
            }
          }
        },
      },
    })
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    • path.js
    const fs = require('fs')
    const path = require('path')
    
    const appDirectory = fs.realpathSync(process.cwd());
    const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
    
    module.exports = {
      resolveApp,
      appPublic: resolveApp('public'),
      appHtml: resolveApp('public/index.html'),
      appSrc: resolveApp('src'),
      appDist: resolveApp('dist'),
      appTsConfig: resolveApp('tsconfig.json'),
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    • package.json
    "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1",
      "dev": "cross-env NODE_ENV=development webpack serve --open --config config/webpack.dev.js",
      "build": "cross-env NODE_ENV=production webpack --config config/webpack.prod.js"
    },
    
    1
    2
    3
    4
    5

    # 参考文章链接

    webpack配置与优化实践 (opens new window)

    ← 常用的Plugin webpack热更新原理→

    最近更新
    01
    vuex数据持久化怎么做
    05-22
    02
    vue的动态路由怎么配置使用
    05-22
    03
    vue权限控制一般怎么做
    05-22
    更多文章>
    Theme by Vdoing | Copyright © 2022-2022 Guoquoqiqi | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式