webpack基础篇

150 阅读5分钟

一、webpack4使用

1. webpack安装

  • 全局安装
npm i webpack webpack-cli -g
  • 项目本地安装
npm i webpack webpack-cli -D
  • 指定版本安装
npm i webpack@4 webpack-cli -D

  通常,全局安装是为了可以在任意位置直接执行webpack命令。实际开发项目中还是推荐在本地安装,因为针对每个项目需要使用的webpack版本可能不同,每个开发者电脑上全局安装的webpack也不相同,使用全局的webpack可能会带来一些不必要的问题。

2. 默认配置

  webpack默认不需要配置文件,其内部已经制定了一些常用的默认配置。webpack默认读取的入口文件为webpack当前执行文件下的src/index.js文件,如果没有这个文件,webpack会报错找不到入口文件。如果没有webpack.config.js配置文件,直接执行webpack命令,还会提示警告The 'mode' option has not been set,可以在执行webpack带上参数webpack --mode=production

  在wenpack构建代码或启动服务的时候,当制定了mode的时候,webpack会自动带上一些默认的配置。mode分为development/production,默认为production。每个选项的默认配置如下(common指两个配置项都存在的属性):

  • 开发/生产环境公共的默认配置:
//parent chunk中解决了的chunk会被删除
optimization.removeAvailableModules:true
//删除空的chunks
optimization.removeEmptyChunks:true
//合并重复的chunk
optimization.mergeDuplicateChunks:true
  • 开发环境的默认配置:
//调试
devtool:eval
//缓存模块, 避免在未更改时重建它们。
cache:true
//缓存已解决的依赖项, 避免重新解析它们。
module.unsafeCache:true
//在 bundle 中引入「所包含模块信息」的相关注释
output.pathinfo:true
//在可能的情况下确定每个模块的导出,被用于其他优化或代码生成。
optimization.providedExports:true
//找到chunk中共享的模块,取出来生成单独的chunk
optimization.splitChunks:true
//为 webpack 运行时代码创建单独的chunk
optimization.runtimeChunk:true
//编译错误时不写入到输出
optimization.noEmitOnErrors:true
//给模块有意义的名称代替ids
optimization.namedModules:true
//给模chunk有意义的名称代替ids
optimization.namedChunks:true
  • 生产环境的默认配置:
//性能相关配置
performance:{hints:"error"....}
//某些chunk的子chunk已一种方式被确定和标记,这些子chunks在加载更大的块时不必加载
optimization.flagIncludedChunks:true
//给经常使用的ids更短的值
optimization.occurrenceOrder:true
//确定每个模块下被使用的导出
optimization.usedExports:true
//识别package.json or rules sideEffects 标志
optimization.sideEffects:true
//尝试查找模块图中可以安全连接到单个模块中的段。- -
optimization.concatenateModules:true
//使用uglify-js压缩代码
optimization.minimize:true

  webpack运行时还会根据mode设置一个全局变量process.env.NODE_ENV,这里的process.env.NODE_ENV不是node中的环境变量,而是webpack.DefinePlugin中定义的全局变量,允许你根据不同的环境执行不同的代码。
下的代码:

if(process.env.NODE_ENV === 'development'){
    //开发环境 do something
}else{
    //生产环境 do something
}

最终将编译成:

if(true){
   //开发环境 do something
}else{
   //生产环境 do something
}

在境下,uglify打包代码时会自动删除不可达代码,也就是说生产环境压缩后最终的代码为:

  //生产环境 do something

3. webpack的五个核心参数:

  • Entry
    入口(entry)指示webpack以那个入口起点开始打包,分析构建内部依赖图
  • Output
    输出(output)指示webpack打包后的资源bundles输出到哪里去,以及如何命名
  • Loader
    加载器(loader)能够处理那些非Javascript/Json的文件(webpack自身职能理解识别Javascript和Json数据代码)
  • Plugin
    插件(plugin)可以用于执行范围更广的任务,插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等
  • Mode
    模式(mode)指示webpack使用相应模式的默认配置,有生产模式(production)和开发模式(development)两种,如果不配置webpack会报警告,并以生产模式(production)打包。

4. webpack4常用的loader和plugin配置

5. webpack-dev-server开发配置

二、webpack打包优化

三、webpack4升级到webpack5的差异记录

  webpack从4升级到5之后,很多的插件可能不兼容,或者是对应功能的插件换了新的插件名称,webpack5本身也有一些不一样的地方,比如本身就内置了file-loader和url-loader的加载器,通过type来制定文件资源的处理方式。使用webpack4老版本的配置,容易出现各种问题,在这做一下记录,后续遇到的话持续更新。

1.eslint-loader改为eslint-webpack-plugin

plugins: [
  new ESLintPlugin({
    fix: true, // 启用ESLint自动修复功能
    extensions: ['js', 'jsx'],
    context: resolve('src'), // 文件根目录
    exclude: '/node_modules/',// 指定要排除的文件/目录
    cache: true //缓存
  })
]

2.内置file-loader和url-loader

{
  test: /.(eot|svg|ttf|woff|woff2?)$/,
  type: 'asset/resource',
  generator: {
    filename: 'static/fonts/[hash][ext][query]'
  }
},
{
  test: /.(png|jpe?g|gif|svg)(?.*)?$/,
  type: 'asset/resource',
  generator: {
    filename: 'static/images/[hash][ext][query]'
  }
}

3.本地启用devserver命令更改,webpack-dev-server改为webpack serve

"start":  "webpack serve --config build/webpack.dev.js --progress",

4. 不支持babel-polyfill,改用@babel/runtime-corejs3和@babel/plugin-transform-runtime

5.图片路径问题

webpack5生产环境需要使用mini-css-extract-plugin的loader,升级后发现背景图片不显示(img标签正常),排查发现是打包后相对路径出现问题,修改publicPath解决

  • 修改前
{
  test: /.(sa|sc|c)ss$/,
  use: [
   isEnvProduction ? MiniCssExtractPlugin.loader : 'style-loader',
   'css-loader',
   'postcss-loader',
   'sass-loader'
  ]
}
  • 修改后
const cssLoader = () => {
  const loader = devModel ? 'style-loader' : {
    loader: devModel ? 'style-loader' : MiniCssExtractPlugin.loader,
      options: {
        publicPath: '../'  
    }
  }
  return [
    loader,
    'css-loader',
    'postcss-loader',
    'sass-loader'
  ]
}
// rule
{
   test: /.(sa|sc|c)ss$/,
   use: cssLoader()
},

6. 部分页面报错,文件引用出现问题(大坑)

排查后发现是用了旧的插件出现问题
new webpack.optimize.ModuleConcatenationPlugin()
删掉OK

7.optimize-css-assets-webpack-plugin替换为css-minimizer-webpack-plugin

optimization: {
    moduleIds: 'deterministic',
    minimizer: [
      new CssMinimizerPlugin({
        parallel: true // 开启多线程压缩
      }),
    ]
}