首先安装webpack
yarn global add webpack@4.41.2 webpack-cli@3.3.10
之后创建一个webpack-demo,并进入这个文件
安装它的两个依赖
npm init -y
yarn add webpack webpack-cli --dev
安装完成之后,就会多一个node_modules目录
接下来,分成几个小目标,逐步完成它们,从而学习webpack
目标一:用webpack编译JS
在webpack-demo中创建一个src文件夹,并在这里创建一个index.js文件,里面输入console.log('hi')
运行webpack,
由于webpack只是局部安装,所以需要指定在哪里去找webpack的执行程序
./node_modules/.bin/webpack
除此之外,还有一种简单的方法
npx webpack
npx会自动找出webpack在本地的哪个位置,但是这种方法有时候不太稳定
当我们运行了之后,就会发现webpack-demo中多出了一个dist文件夹,里面有一个main.js文件
点开main.js之后,会发现里面有console.log('hi')
试试稍微复杂一点的状况,现在src目录下创建一个x.js文件,写入
export default 'xxx'
之后,更改index.js的内容
import x from './x.js'
console.log(x)
再次运行webpack,得到一个新的main.js
这里会得到console.log("xxx"),至此我们发现一个问题:
在index.js文件中console.log(x)中的x,实际是从x.js中引入的,而x.js只导出了xxx三个字符,所以实际上最后打印出的就是xxx三个字符,
于是webpack敏锐的发现了这一点,它就直接的打印出了xxx这三个字符
也就是说webpack会分析JS代码,然后把JS代码变成IE或者更低版本浏览器可以用的JS,而main.js中前面的一大串代码,是兼容代码,是为了保证import,require等代码可以运行而写得代码
————————————————————————————————————————————————
在做这些操作时,一直有一个警告
意为mode没有被设置,
于是,我们在webpack-demo下创建一个webpack.config.js文件,并在里面写入
module.exports = {
mode: "development",
}
}
再次运行webpack,并点开新的main.js,会发现main.js大不一样
这个development模式,就是开发者模式
而之前使用的模式默认是production模式,是生产者模式,是直接给用户使用的
目标二:理解文件名中的hash的用途
先给webpack.config.js添加一些东西
const path = require('path');
module.exports = {
mode: "development",
entry: './src/index.js',//默认入口
output: {
path: path.resolve(__dirname, 'dist'),//默认创建出口的目录
filename: 'index.js'//出口名
}
}
删除之前的dist文件,再次运行webpack
会得到一个新的dist文件,里面有index.js
这样,我们就大概清楚了它的入口和出口的一些配置 ————————————————————————————————————————————————
更改上述文件中的 filename: 'index.js'为filename: '[name].[contenthash].js'
再次运行webpack,就会得到一个文件名很复杂的文件
为什么会创建这么一个文件?
这与HTTP缓存有关
HTTP缓存
比如去访问baidu.com
- 假设它会给我们返回一个index.html(首页)
- 这个index.html会去加载1.css,2.css,3.js,4.js…,并就把这些文件缓存
- 当我第二次访问baidu.com时,
- 它就不会再去加载这些文件,
- 这时,只需要下载index,html(首页),它会去从内存(或硬盘)之中得到1.css,2.css,3.js,4.js…
- 这么一来,就能加快访问速度
图中可以看出,缓存的文件可以不费时就完成加载
而禁用缓存,加载每个文件就会耗费一些时间
取消禁用缓存,我们点开一个JS文件,查看它的响应头
可以看到它的cache-control:max-age-25920000,
这串数字的单位是秒,换算成天就是300天,
也就是说300天之内,再次访问baidu.com时,不需要重复下载这个文件
这就是缓存的作用
现在有一个问题,如果百度要更新这个JS文件怎么办?
很简单,因为缓存是跟着文件名走的,所以只要改了文件名就好了
更改文件名
怎么改文件名?
只要对文件内容做一个哈希就可以,webpack就会自动做这么一件事
做一个简单的实验,我们再更改了上述的filename之后,对index,js做一点简单的改动
import x from './x.js'
console.log(x)
console.log('hi')
再次运行webpack
就会得到一个新的以main开头的文件
所以只要每次发布,内容不一样,文件名就会跟内容有一一对应,(可以理解为不同文件名对应不同版本)
这样在重新发布时候,根据文件名不同,浏览器就知道要更新一个新的文件,之前的缓存也就作废了
这里可以看出上述更改的filename的意义,就是产生一个新的哈希
但是首页不能缓存,如果首页都缓存了,就没办法更新里面的文件内容了
—————————————————————————————————————————————
在图中可以看到,每次重新webpack都会生成一个新的文件,为了不让文件增加,需要更改一下webpack-demo里的package.json文件
{
...
"scripts": {
...
"build": "rm -rf dist && webpack",
...
},
...
}
加上这么一句,这样每次需要打包的时候,直接运行yarn build,它就会删除之前的dist文件,重新webpack
目标三:用webpack生成HTML
首先安装html-webpack-plugin
yarn add html-webpack-plugin@3.2.0 --dev
再次更改webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: "development",
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js'
},
plugins: [new HtmlWebpackPlugin()]
}
运行yarn build,会发现dist里多了一个index.html文件
点开这个文件,可以看到生成了一个空的html,这个html自动引用了dist里的main.xxxxxxx.js
且每一次更新JS,再次打包,生成新的JS文件,这里面引用的JS文件也会自动更新
—————————————————————————————————————————————
但是这个html文件里面,不能随便加东西,加了之后下次打包加的东西就不见了
这里,需要再次更改webpack.config.js里的plugins
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
},
plugins: [new HtmlWebpackPlugin({
title: 'My App',
template: "src/assets/index.html"
})]
}
并在src文件夹中,创建assets文件夹,assets里创建index.html文件
进入这个assets/index.html文件,将其初始化
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- 根据配置里的title生成 title-->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
再次yarn build
完事之后,进入dist/index.html,就会发现这个文件的title为My APP,且在这个文件的body里也有一个id为app的div
用这个的方法,就可以往dist/index.html里添加东西