webpack5 基础篇(一)

170 阅读4分钟

一、source-map

  • 外部map文件
  • 错误代码准确信息 和 源代码的错误位置
// 可任意组合
devtool: [inline-|hidden-|eval][nosource-][cheap-[module-]]source-map

inline-source-map

  • 只生成一个内联
  • 错误代码准确信息 和 源代码的错误位置

hidden-source-map

  • 外部map文件
  • 不能追踪源代码的错误位置,只能提示到构建后的错误位置
  • 只隐藏源代码

eval-source-map

  • 每一个文件会生成对应的source-map,以内联方式都在eval中
  • 错误代码准确信息 和 源代码的错误位置

nosource-source-map

  • 外部map文件
  • 错误代码准确信息,但是没有任何构建后代码信息和源代码信息
  • 隐藏源代码和构建后的代码

cheap-source-map

  • 外部map文件
  • 错误代码准确信息 和 源代码的错误位置
  • 只能精确到行

cheap-module-source-map

  • 外部map文件
  • 错误代码准确信息 和 源代码的错误位置
  • 支持第三方loader的错误提示

效果对比

  • 速度:eval > inline > chheap > ...
  • 调试友好:source-map > cheap-module-source-map > cheap-source-map > ...
  • 平衡选择
    • 开发环境:eval-source-map > eval-cheap-source-map
    • 生产环境:source-map / cheap-module-source-map(内联会让代码体积变大)

二、缓存

babel

让第二次打包构建更快

cacheDirectory: true

文件资源缓存

让代码上线运行缓存更好使用

filename: 'css/[name].[contenthash:10][ext][query]'
  • hash
  1. 每次webpack构建时都会生成一个唯一的hash值
  2. 问题:因为js与css同时使用一个hash值,如果重新打包,会导致所有缓存失效,而又可能只改动了一个文件
  • chunkhash
  1. 根据chunk生成的hash值,如果打包来自于同一个chunk,那么hash值一样
  2. 问题:因为js与css同属于一个chunk,使用一个hash值
  • contenthash
  1. 根据文件内容生成的hash值,不同文件hash值不一样

三、tree shaking

去除无用代码

  • 使用ES6模块
  • 开启production模式
  • oneOf 在package.json中配置:
sideEffects: false
/*
 所有代码都没有副作用,都可以进行tree shaking
 问题:可能会把css / @babel/polyfill 文件干掉
 可以配置:sideEffects: ["*.css", "*.less"]
*/

四、code split(代码分割)

多入口配置

entry: {
    index: './src/js/index.js',
    main: './src/js/main.js'
}

配置splitChunks

/*
    1、可以自动将node_modules中代码单独打包成一个chunk最终输出
    2、自动分析多入口chunk中,有没有公共的文件,如果有会打包成单独的chunk(webpack 有默认的限制配置,比如大小超过20k等)
*/
optimization: {
    splitChunks: {
        chunks: 'all'
    }
}

配置文档:SplitChunksPlugin

import

import(/* webpackChunkName: 'test' */'./main').then().catch()

结合splitChunks配置,import动态导入模块

五、懒加载与预加载

/*
懒加载:当资源被使用时才会去加载
预加载:prefetch会在其他正常加载的资源加载完毕后,浏览器空闲了再去加载资源,使用时直接从prefetch中拿取(会有浏览器版本要求)
*/
import(/* webpackChunkName: 'test', webpackPrefetch: true  */'./main').then().catch()

六、PWA

渐进式网络开发应用程序(离线时可访问)
workbox --> workbox-webpack-plugin
渐进式网络应用程序

七、多进程打包

一般作用于耗时的操作,比如:babel-loader
thread-loader

八、externals

防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies) 外部扩展(Externals)

九、DLL

单独打包,仅打包一次
DLL

十、性能优化总结

  1. 开发环境优化:HMR、source-map
  2. 生产环境优化:one-of、source-map、缓存(hash-chunkhash-contenthash)、tree shaking、code split、懒加载/预加载、pwa、external、dll

十一、基础配置

const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WorkboxPlugin = require('workbox-webpack-plugin')
module.exports = {
  // 入口文件
  entry: './src/index.js',
  // 输出
  output: {
    filename: 'bundle.js', // 输出文件名
    path: resolve(__dirname, 'dist'), // 输出路径,__dirname:node.js变量,代表当前文件的目录绝对路径
    // assetModuleFilename: 'images/[name].[hash][ext][query]', // 自定义输出文件名 -- 适用于全部
    clean: true
  },
  // loader配置:1.下载  2.使用
  module: {
    // 不同文件需要单独配置不同的loader
    rules: [
      {
        // 正则表达式匹配
        test: /\.css$/i,
        // 使用哪些loader:从上到下,从右到左倒序执行数组中的loader
        // 多个loader使用use数组
        use: [
          'style-loader', // 创建style标签,将js中的样式资源添加到head1中
          'css-loader' // 将css文件变成commonjs模块加载到js中,内容是 样式字符串
        ]
      },
      {
        test: /\.less$/i,
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        // type: 'asset/resource', // 指定 资源模式 resource
        type: 'asset', // webpack 将按照默认条件,自动地在 resource 和 inline 之间进行选择:小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型
        parser: { // 修改限制
          dataUrlCondition: {
            maxSize: 8 * 1024 // 4kb
          }
        },
        generator: {
          filename: 'images/[name].[hash:10][ext][query]'
        }
      },
      {
        test: /\.html$/i,
        // 单个loader使用loader
        loader: 'html-loader', // 处理img标签路径问题
        // generator: {
        //   filename: '[name][ext]'
        // }
      }
    ]
  },
  // plugins: 1.下载  2.引入  3.使用
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    }),
    // pwa
    new WorkboxPlugin.GenerateSW({
      // 这些选项帮助快速启用 ServiceWorkers
      // 不允许遗留任何'旧的' ServiceWorkers
      clientsClaim: true,
      skipWaiting: true,
    }),
  ],
  // webpack-dev-server 在编译之后不会写入到任何输出文件。而是将 bundle 文件保留在内存中
  devServer: {
    static: './dist'
  },
  mode: 'development'
}