前端人 精学webpack

背景

webpack静态模块化打包工具。无论是前端工程化,还是高级前端岗位都是绕不开的话题之一,面试经常问到构建优化的的方案,自定义loader,自定义plugin等。无论是进阶,还是面试高级岗位,在这里你都可以找到答案。webpack简单来说就是各种令人眼花缭乱的配置,笔者也是感同身受,学了很快就会忘记,所以才有了这篇文章。采用费曼学习法,用简洁的思想和简单的语言向大家表达出来,帮助大家也是帮助自己,本文的学习资料大部分来自于官方文档。本文将持续迭代,收藏===学会~

安装

shell 复制代码
# 创建文件夹
mkdir learn-webpack 
# 进入文件夹
cd learn-webpack
# 初始化
pnpm init
# 安装依赖
pnpm i webpack webpack-cli -D

结构划分

代码仓库:github.com/GetWebHB/le...

  • 每一个小的章节,都会存放在对应的文件夹中(例:0.start),文件夹会存放对应的配置文件 ,源代码产物 。打包命令如下所示,b-0build-step0的简写,方便大家理解
js 复制代码
// package.json
  "scripts": {
    "b-0": "webpack --config ./packages/0.start/webpack.config.js"
  },

scripts脚本,本质上就只在.bin文件夹下寻找webpack, 即npm run b-1等同于npx webpack--config代表配置文件存在的目录。

因为每个章节都会有不一样的配置,给它们拆分开这样会更加清晰。如果是公司项目中不需要这样,一般只会有一个配置文件webpack.config.js,存放在同package.json目录,就不需要指定配置文件路径,执行npm run build会自动去根目录查找webpack.config.js配置文件

目录结构

css 复制代码
├── README.MD
├── package.json
├── packages
│   └── 0.start
│       ├── build
│       │   └── bundle.js
│       ├── src
│       │   └── main.js
│       └── webpack.config.js
└── pnpm-lock.yaml

起手式

本节代码见:0.start

js 复制代码
// main.js
function sayHi() {
  console.log('hi ice 24')
}
sayHi()
export { sayHi }

// webpack.config.js
const path = require('path')
module.exports = {
  entry: path.resolve(__dirname, "./src/main.js"),
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  },
}
  • 简单走读一下,cjs的方式导出了一个对象
  1. entry代表入口,发现我们使用的是绝对路径,因为默认情况下相对路径为package.json存在的目录
  2. output代表出口,即产物打包后的位置,同样是绝对路径,打包到build的文件夹下,文件名为bundle.js
  3. npm run b-0, 即打包产物,就会发现该目录下出现了产物

mode&devtool

本节代码见:1.mode_devtool

上一小节中,我们学习到了entry,output这两项配置,这一章节中,我们学习modedevtool

mode

概述:告诉webpack使用相应模式的内置优化

当我们执行npm run b-0的时候,webpack会有这一串警告,说我们没有设置mode 那什么是模式(即mode),从提示看说我们可以设置为developmentorproduction
传送门webpack.js.org/configurati...

mode也是最重要的优化,webpack都会帮我们做好。接下来我们来一一了解对应模式展示的不同行为

  • mode = 'none' | 'development' | 'production'(default)
js 复制代码
// main.js
const mes = 'hi ice 24'
function sayHi() {
  console.log(mes)
}
sayHi()

export { sayHi }

none

产物分析

  • 我们大致扫一眼即可

development

我们平常使用的cli, vue/cli(维护阶段),create-react-app等,反正所有底层使用webpack的,npm run serve / npm run start这种在本地开启服务的,采用的策略都是使用development,主打的就是一个快,不需要通过一些plugin,例如terser(后面会讲)丑化压缩代码
产物分析 从注释中我们可以得知,它使用eval函数可以在浏览器的开发工具中创建一个单独的源文件,在或者说devtool:false的时候就会移除(source map),那么创建一个单独的文件可以干嘛呢?可以映射到代码报错的位置,这也是devtool配置项的作用,我们后面会详细探讨。

production

就是那么朴实无华,甚至连函数都帮你执行了,直接打印出结果

devtool

概述:是否生成,控制如何生成source map(源码映射),不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。
默认值

  • dev: eval
  • prod: none
    传送门webpack.docschina.org/configurati...
  • mode模式为development中,我们看见了eval函数,可以映射出代码的错误位置信息,即配置为mode: "eval",现在让我们来深入探讨一下devtool

就拿mode:prod来说,我们发现代码是已经被丑化过,编译后的产物,如果在测试阶段,代码发生了错误压根不知道代码出错在哪里,那我们如何debug呢?这正是source map的作用,编译后的产物 ->(映射)源代码的位置

false

js 复制代码
// main.js
const mes = 'hi ice 24'
function sayHi() {
  console.log(mes)
}
console.log(age) // age is not defined
sayHi()

export { sayHi }

// bundle.js
(()=>{"use strict";console.log(age),console.log("hi ice 24")})();

跑到浏览器上(测试阶段),我们可以看到错误信息,但是却看不到代码详细出错在第几行,这在一个庞大的项目中,是非常致命的(即devtool: false),不开启source map

eval

使用eval函数可以在浏览器的开发工具中创建一个单独的source map

source-map

当我们配置改为它,我们先看下产物

会多出来一个.map的文件,即源码映射文件,最后一行代表着引用哪个.map文件,接下来我们在到浏览器下看下行为。

竟然神奇的映射出来了源代码的位置(第几行,甚至第几个字符),非常的神奇是吧

接下来,让我们继续深入探究,简单看下map文件

  • version:3,从之前1,2的版本构建出来的map文件有点大,随着不断的迭代构建出来的.map文件也越来小
  • file:映射的源文件(转换后的源文件)
  • mappings:记录位置信息的字符串(VLQ编码)
  • sources:源的路径
  • sourcesContent:源代码的内容
  • names:转换前的所有变量名和属性名
  • sourceRoot:映射目录的位置,为根目录

最佳实践

  • prod:none(默认) | false
  • test:source-map
  • development: source-map
相关推荐
小白学习日记19 分钟前
【复习】HTML常用标签<table>
前端·html
john_hjy22 分钟前
11. 异步编程
运维·服务器·javascript
风清扬_jd1 小时前
Chromium 中JavaScript Fetch API接口c++代码实现(二)
javascript·c++·chrome
丁总学Java1 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele1 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范
It'sMyGo1 小时前
Javascript数组研究09_Array.prototype[Symbol.unscopables]
开发语言·javascript·原型模式
懒羊羊大王呀1 小时前
CSS——属性值计算
前端·css
睡觉然后上课1 小时前
c基础面试题
c语言·开发语言·c++·面试
xgq1 小时前
使用File System Access API 直接读写本地文件
前端·javascript·面试
李是啥也不会1 小时前
数组的概念
javascript