0
点赞
收藏
分享

微信扫一扫

5. webpack 优化配置

蛇发女妖 2022-03-13 阅读 54

第 5 章:webpack 优化配置

* 开发环境性能优化
* 生产环境性能优化

开发环境性能优化

* 优化打包构建速度
  * HMR
* 优化代码调试
  * source-map

生产环境性能优化

* 优化打包构建速度
  * oneOf
  * babel缓存
  * 多进程打包
  * externals
  * dll
* 优化代码运行的性能
  * 缓存(hash-chunkhash-contenthash)
  * tree shaking
  * code split
  * 懒加载/预加载
  * pwa

5.1 HMR

HMR: hot module replacement 热模块替换 / 模块热替换
 作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块) 极大提升构建速度      
 
 样式文件:可以使用HMR功能:因为style-loader内部实现了~
 		开发环境使用 style-loader,因为能使性能和打包速度更快 ; 而生产环境使用 提取css单独文件,是考虑到了性能优化
 		
 js文件:默认不能使用HMR功能 --> 需要修改js代码,添加支持HMR功能的代码
 注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。如监听 print.js 
 
 html文件: 默认不能使用HMR功能.同时会导致问题:html文件不能热更新了~ ,即修改html代码,页面没有自动更新
 解决:修改entry入口,将html文件引入;
 		entry: './src/js/index.js',
 		改成 entry: ['./src/js/index.js', './src/index.html'],
	最后结果就是,修改html中的文件热更新依然会打包所有模块
结论:html不用做HMR功能

开启HMR功能: 在devServer中设置hot: true 即可
  1. 创建文件
    在这里插入图片描述
    index.js
// 引入
import print from './print';
import '../css/iconfont.css';
import '../css/index.less';

console.log('index.js文件被加载了~');

print();

function add(x, y) {
  return x + y;
}

console.log(add(1, 3));

if (module.hot) {
  // 一旦 module.hot 为true,说明开启了HMR功能。 --> 让HMR功能代码生效
  module.hot.accept('./print.js', function() {
    // 方法会监听 print.js 文件的变化,一旦发生变化,其他模块不会重新打包构建。
    // 会执行后面的回调函数
    print();
  });
}

print.js

console.log('print.js被加载了~');

function print() {
  const content = 'hello print';
  console.log(content);
}

export default print;
  1. 修改配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: ['./src/js/index.js', './src/index.html'],
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // loader的配置
      {
        // 处理less资源
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        // 处理css资源
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          // 关闭es6模块化
          esModule: false,
          outputPath: 'imgs'
        }
      },
      {
        // 处理html中img资源
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        // 处理其他资源
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    // plugins的配置
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',
  devServer: {
    static: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    // 开启HMR功能
    // 当修改了webpack配置,新配置要想生效,必须重新webpack服务 npx webpack-dev-server
    hot: true
  }
};
  1. 运行指令: npx webpack-dev-server; 浏览器中开启成功标志:
    浏览器中开启成功标志
    在这里插入图片描述

5.2 source-map

source-map: 一种 提供源代码到构建后代码映射 技术 (如果构建后代码出错了,通过映射可以追踪源代码错误)
开启: devtool: 'source-map'     // 举例: 外部,在build下生成 built.js.map

devtool的值:
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

source-map:外部
  错误代码准确信息 和 源代码的错误位置
inline-source-map:内联
  只生成一个内联source-map
  错误代码准确信息 和 源代码的错误位置
hidden-source-map:外部
  错误代码错误原因,但是没有错误位置
  不能追踪源代码错误,只能提示到构建后代码的错误位置
eval-source-map:内联
  每一个文件都生成对应的source-map,都在eval
  错误代码准确信息 和 源代码的错误位置
nosources-source-map:外部
  错误代码准确信息, 但是没有任何源代码信息
cheap-source-map:外部
  错误代码准确信息 和 源代码的错误位置 
  只能精确的行
cheap-module-source-map:外部
  错误代码准确信息 和 源代码的错误位置 
  module会将loader的source map加入

内联 和 外部的区别:1. 外部生成了文件,内联没有 2. 内联构建速度更快

开发环境:速度快,调试更友好
  速度快(eval>inline>cheap>...)
    eval-cheap-souce-map
    eval-source-map
  调试更友好  
    souce-map
    cheap-module-souce-map
    cheap-souce-map

  --> eval-source-map  / eval-cheap-module-souce-map
  // vue-cli中默认使用的是eval-source-map

生产环境:源代码要不要隐藏? 调试要不要更友好
  内联会让代码体积变大,所以在生产环境不用内联
  nosources-source-map 全部隐藏
  hidden-source-map 只隐藏源代码,会提示构建后代码错误信息

  --> source-map / cheap-module-souce-map
  1. 配置文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: ['./src/js/index.js', './src/index.html'],
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // loader的配置
      {
        // 处理less资源
        test: /\.less$/,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        // 处理css资源
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          // 关闭es6模块化
          esModule: false,
          outputPath: 'imgs'
        }
      },
      {
        // 处理html中img资源
        test: /\.html$/,
        loader: 'html-loader'
      },
      {
        // 处理其他资源
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media'
        }
      }
    ]
  },
  plugins: [
    // plugins的配置
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true
  },
  //  [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
  devtool: 'eval-source-map'
};
  1. 执行webpack指令生成构建后的代码
    在这里插入图片描述

5.3 oneOf

     oneOf提高打包构建速度;
     只会匹配一个loader;
     类似于数组列表,以前每一个文件需要遍历全部找到处理该文件类型对应loader,而使用oneOf 只需要使用匹配到的loader即可。
    // 注意:不能有两个配置处理同一种类型文件;
    比如js需要两个loader来进行处理,需要把其中一个移出oneOf外面
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

// 定义nodejs环境变量:决定使用browserslist的哪个环境
process.env.NODE_ENV = 'production';

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 还需要在package.json中定义browserslist
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()]
    }
  }
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只会匹配一个
        // 注意:不能有两个配置处理同一种类型文件
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          /*
            正常来讲,一个文件只能被一个loader处理。
            当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
              先执行eslint 在执行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {version: 3},
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ]
            }
          },
          {
            test: /\.(jpg|png|gif)/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              outputPath: 'imgs',
              esModule: false
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader'
          },
          {
            exclude: /\.(js|css|less|html|jpg|png|gif)/,
            loader: 'file-loader',
            options: {
              outputPath: 'media'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  mode: 'production'
};

5.4 缓存

5.5 tree shaking

5.6 code split

5.7 lazy loading

5.8 pwa

5.9 多进程打包

5.10 externals

5.10 dll

举报

相关推荐

0 条评论