- 理解前端“工程化”概念、工具、目标
- 一个团队总要有那么几个人需要熟悉Webpack,某种程度上可以成为个人的核心竞争力
- 高阶前端工程师的必经之路
前端项目是往往是由以下资源构成
以往处理引用这些资源会像下面这样去用标签一个一个的手动引入去手动管理这些资源
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="./style.css">
head>
<body>
<div>
<img src="./img.jpg" alt="">
div>
<script src="./main.js">script>
<script src="./foo.js">script>
<script src="./bar.js">script>
body>
html>
但是:
- 依赖手工,比如有50个或者更多JS文件…,过程繁琐
- 当代码文件之间有依赖的时候,就的严格按依赖顺序书写
- 开发与生产环境一致,难以接入TS或JS新特性
- 比较难以接入Less、Sass等工具
- JS、图片、CSS资源管理模型不一致
于是为了解决这个问题也出现了很多像下面的工具
Webpack本质上是一种前端资源编译、打包工具;它具有一下的特点
- 多份资源文件打包成一个
Bundle
- 支持Babel、Eslint、TS、CoffeScriot、Less、Sass
- 支持模块化处理css、图片等资源文件
- 支持HMR+开发服务器
- 支持持续监听、持续构建
- 支持代码分离
- 支持Tree-shaking
- 支持Sourcemap
- …
1.安装
npm i -D webpack webpack-cli
2.编辑配置文件
const path = require('path');
module.exports ={
entry: "./src/index",
output: {
filename: "[name].js",
path: path.join(__dirname, './dist'),
}
}
其中参数
entry
:定义当前项目文件的路径入口output
: 定义当前这个打包后放在哪里
filename
: 定义打包后的文件名(默认是main)path
:定义打包后存放路径
3.执行编译命令
npx webpack
- 入口处理
从entry
文件开始,启动编译流程
2.依赖解析
从entry
文件开始,根据require
orimport
等语句找到依赖资源
3.资源解析
根据module
配置,调用资源转移器,将png、css等非标准JS资源转译为JS内容
递归调用2、3,直到所以资源处理完毕
4.资源合并打包
将转译后的资源内容并打包可直接在浏览器运行的JS文件
Webpack 所做的主要作用就是模块化+一致性
- 多个文件资源合并成一个, 减少HTTP请求数
- 支持模块化开发
- 支持JS特性
- 支持Typescript、CoffeeScript方言
- 统一图片、CSS、字体 等其他资源的处理模型
关于Webpack的使用方法,基本都围绕“配置”展开,而这些配置大致可划分为两类:
流程类: 作用于流程中某个 or 若干个环节, 直接影响打包效果的配置项
工具类: 主流程之外,提供更多的工程化能力的配置项
按使用频率:
entry/output
module/plugins
mode
watch/devServer/devtool
Webpack配置官方文档>>>
>>>js文件>>>
import bar from './index.css';
// or
const styles = require('./index.css');
文件路径
npm add -D css-loader style-loader
2.编辑配置文件
const path = require('path');
module.exports = {
entry: "./src/index",
mode: 'development',
devtool: false,
output: {
filename: "[name].js",
path: path.join(__dirname, './dist'),
},
module: {
rules:[{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
}]
},
}
执行
npx webpack
运行后的结果
Babel备注:
Babel本质是一个JS代码版本转译的工具,可以将ES6及以上的JS新语法特性转译成ES5的语法让浏览器识别,获得更好的兼容性。这样就能解决一些浏览器无法识别ES6及以上的新语法特性例如class、箭头函数、迭代器等的问题。
Babel的作用:
- 语法转换
- 对目标进行特性补充polyfill
- 代码替换
Babel与Webpack的关系
- babel 是编译工具,把js高级语言转换成浏览器能识别的js语言。
- webpack 是打包工具,定义入口文件,将所有模块引入整理后,通过 loader 和 plugin 处理后,打包输出。
- webpack 通过 babel-loader 使用 babel 。
>>>js文件>>>
class Person {
constructor(){
this.name = "江流儿"
}
}
console.log((new Person()).name);
const say = ()=>{};
文件路径
npm i -D @babel/core @babel/preset-env babel-loader
2.编辑配置文件
const path = require('path');
module.exports = {
entry: "./src/index",
mode: 'development',
devtool: false,
output: {
filename: "[name].js",
path: path.join(__dirname, './dist'),
},
module: {
rules:[{
test:/\.js$/,
use:[{
loader:'babel-loader',
options:{
presets:[
[
'@babel/preset-env'
]
]
}
}]
}]
},
}
3.执行
npx webpack
运行后的结果
使用Webpack环境,我们可以直接为js文件直接生成一个html文件
>>>js文件>>>
console.log('Hello, World!');
文件路径
npm i -D html-webpack-plugin
2.编辑配置文件
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: "./src/index",
mode: 'development',
devtool: false,
output: {
filename: "[name].js",
path: path.join(__dirname, './dist'),
},
plugins: [new HtmlWebpackPlugin()]
}
3.执行
npx webpack
运行后的结果
一共会生成两个产物,一个main.js和一个index.html文件
html产物
Hot Module Replacement—使用热替换
该工具可以让刚写的代码能立刻更新的浏览器上面,不需要刷新浏览器
1.开启HRM
主要的配置如下
module.exports ={
// ....
devServer:{
hot: true
}
};
结合到前面CSS等相关的配置使用如下:
watch:true
该配置是让webpack持续的监听文件的变化,持续的构建
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: "./src/index",
mode: 'development',
devtool: false,
devServer:{
hot:true,
open:true
},
module:{
rules:[{
test:/\.css$/,
use: ['style-loader', 'css-loader']
}]
},
output: {
filename: "[name].js",
path: path.join(__dirname, './dist'),
},
plugins: [new HtmlWebpackPlugin()],
watch: true
}
文件结构可以看看前面使用webpack处理css文件的内容
2.启用Webpack
npx webpack serve
效果
效果如下,当修改css文件的时候,浏览器内容也会自动更新
原理参考:《Webpack 原理系列十:HMR 原理全解析》
Tree-Shaking-树摇,用于删除
Deed CodeDeed Code`:
- 代码没有被用到,不可到达
- 代码的执行结果不会被用到
- 代码只读不写
Tree-Shaking
: 模块导出了,但未被其他模块使用
1.开启Tree-Shaking
主要的配置如下
module.exports ={
// ....
mode: "producrion",
optimization:{
usedExports: true,
},
};
2.启用Webpack
npx webpack
效果如下
- 缓存
- Sourcemap
- 性能监控
- 日志
- 代码压缩
- 分包
- …