Webpack 起航
文章写于 2020-3-11,官方文档首先一上来就有很多概念内容讲的多,我是看不太懂的,所以就自己来吧,慢慢学,慢慢讲概念,本文章基于 Webpack v4.42.0
1. 安装
- 确保你安装了 Node.js 较新版本
移步至官网查看 推荐安装版本 ,下载后运行安装
本地安装webpack
新建一个项目文件[project name]
webpack_start
进入 webpack_start
文件夹的 cmd
运行webpack 安装命令
移步至官网查看最新版本,以下安装命令可能被修改
npm install --save-dev webpack //最新版本
npm install --save-dev webpack@<version> //指定版本
安装存在于你的项目目录中,如果你是用webpack 4+ 版本,你还需要安装 CLI。
npm install --save-dev webpack-cli
全局安装webpack
npm install --global webpack
官方不推荐这种安装方式,这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。
安装完后可能会出现一堆的 warn
,没有关系,现在去执行初始化
初始化创建package.json
npm init
命令行会提示你输入一些信息,如果需要请填写,可以一路默认按
Enter
如果你使用的是 npm 5,你可能还会在目录中看到一个
package-lock.json
文件。
2. 核心概念
Entry
– 指定webpack从哪个文件开始打包,分析构建内部的依赖结构Output
– 指定webpack将打包后的资源(bundles)放于何处,以及命名Loader
– 可使webpack去理解那些非 JavaScript 文件,webpack本身只理解js(翻译官)Plugins
– 可帮助webpack 完成一些原本不具有的功能(如压缩代码等等)Mode
– 指定打包时候使用的模式(分为development、production 两种)
3. 起步使用
使用你的ide打开新建的 webpack_start
,进入cmd
首先先安装webpack-cli
,该工具可以使用webpack指令来简化操作,(首先全局安装)
npm i webpack-cli -g
再次安装本地webpack-cli
(作用域为当前项目文件夹内)(-D 代表 开发环境)
npm i webpack-cli -D
新建文件目录为如下所示:
webpack_start
node_modules
(自带)build
(文件夹,打包后保存的目录)src
(文件夹,源码目录)index.js
(在后面的示例中作为入口文件)
官网推荐的目录命名为:
webpack_start
node_modules
dist
(打包后存放的目录)src
index.js
4. 验证阶段
验证webpack 默认只能解析 JavaScript
、JSON
文件
JavaScript 打包
在index.js
中输入任意可执行有输出的代码,如下所示:
function sum(a,b){
console.log(a+b)
}
sum(1,2)
接下来使用如下命令,webpack一下(打包)([ ]
表示可替换)
webpack [入口文件所处的相对路径] -o [输入到哪个指定的位置] --mode=development //示例
webpack ./src/index.js -o ./build/built.js --mode=development //转换成
以上的意思为使用 webpack指令打包 位于xxx 下面的
index.js
输出到 xxx 目录下面命名为built.js
,以开发环境的模式!结尾可以指定 --mode=production 的方式来跑,(有压缩优化代码的效果)
接下来你就可以使用node 来跑这个最终生成的js
node ./build/built.js
最终结果显示为3
JSON打包
在src
下新建一个json文件 :
src
test.json
内容为:
{
"name":"zhangsan",
"age": 22
}
然后再在index.js
文件中导入该文件夹
import jsondata from './test.json'
console.log(jsondata)
重新执行开发环境的模式打包。然后在node 中运行,得出结果
{ name: 'zhangsan', age: 22 }
其它格式的文件打包
你可以用同样的方法(记得编写好后在index.js
文件中引入)然后执行同意的步骤进行打包,然后就会喜提error
查看最终生成的文件以更加清楚webpack为何只理解JS、JSON
打开你最终生成的文件 built.js
(官方推荐的命名 bundle.js
)
可以看出,最终是built.js
中生成的代码中有 eval()
方法。
eval()
方法能解析JavaScript语句,
而能识别json 是因为 webpack 在 eval()
方法中用到了 JSON.parse()
4. 使用0配置的webpack直接打包文件
webpack 为开发者提供了直接打包的命令webpack
,
webpack
使用规则如下:
-
你必须拥有 src 文件夹
-
你必须在 src 文件夹下拥有名为
index.js
的入口文件
被动接受规则如下:
-
最终webpack将会默认以
production
的方式打包文件 -
最终webpack将会创建
dist
文件夹 以作为输出文件夹 -
最终webpack会在
dist
文件夹下生成main.js
文件
文件生成如下:
webpack_start
-
|--
dist
main.js
-
|--
node_modules
-
|--
src
index.js
-
|--
package.json
-
|--
package-lock.json
5. 使用配置文件来指定webpack配置
从 webpack v4.0.0 开始,可以不用引入一个配置文件。然而,webpack 仍然还是高度可配置的(官方原话)
既然可以配置,然后又是打着学习的目的,肯定得来折腾一下
第一步:先新建一个webpack.config.js
Q:能瞎jb命名嘛?
A:不要闹,就这个名字,内部已经指定好了,死活要改可以 参考官网
第二步:编写配置文件
const path = require('path'); // 导入遵循 node使用的 CommonJS规范
module.exports = { // 导出遵循 node使用的 CommonJS规范
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
path
是用的CommonJS
的规范引入的 node 模块,用来操作路径的(人家node暂时在我写文档的这个时期还只普遍支持用 require ,并不用ES6 的 import)
entry
后面的字符串值你爱怎么改怎么改
__dirname
是node 的变量,代表当前项目下的绝对路径
output.path
的参数2 你爱怎么改怎么改
output.filename
的值 你爱怎么改怎么改
6. 使用webpack打包CSS资源
上文提到了webpack本身只能理解 Javas,并且能用JSON.parse()来解析JSON,所以说想要使用webpack去理解CSS 这些,就需要一个翻译官:Loader
上文中也提到了配置文件,现在我们来配置loader :
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
//loader 的配置
module:{
//具体的规则
rules: [
//参数接收一个数组
{
//想到了正则匹配 test() 方法
test: /\.css$/,
//指定使用哪个loader
use:[
'style-loader',
'css-loader'
]
}
]
},
plugins: [],
mode: "development" // or "production"
};
use
数组中的loader执行顺序为:从后往前,先执行 css-loader 再执行 style-loader (重点)style-loader
创建style标签,将js中的css样式资源插入进去,添加到页面head中生效css-loader
将 css 文件变成CommonJS模块 ,加载到js中,内容为样式字符串
配置完毕我们接下来要安装两个依赖 style-loader
和 css-loader
npm install --save-dev style-loader css-loader
// 二选一,两个命令其实一样
npm i css-loader style-loader -D
你每次都得安装这两个依赖包,或者使用node往上查找的原则
(如果当前项目不存在所需依赖,往上一个目录查找)
在根目录 webpack_start
(以后就将他作为根目录,以后需要用到webpack来打包的项目都创建在
webpack_start
文件夹中)
中创建测试项目,但是常用依赖安装在webpack_start
中,目录构建如下:
webpack_start
node_modules
package.json
package-lock.json
my_project1
– 在具体的项目中安装 webpack 和 webpack-cli 就行my_project2
- …xxx
然后在src
目录下新建一个 index.css
,在其中编写任意css来测试,
*{
margin: 0;
padding: 0;
}
html,body{
width: 100%;
height: 100vh;
background: pink;
}
运行webpack,你会发现不再报错了
webpack
在生成的 dist > bundle.js
中找到了 index.css 的一栏
接下来新建index.html
来测试,核心代码如下:
<body>
<script src="./bundle.js"></script>
</body>
可以在浏览器中看到如下所示代码:
这里就要想到之前提到的,use 数组中,指定的loader 的执行顺序,是先执行的将css样式字符串以CommonJS的形式加载到了生成的 bundle.js中,然后在bundel.js中有创建
使用webpack打包scss
scss 是 sass 的人性化版本,所以还是要用sass的loader 需要用到以下两个包:
npm i sass-loader -D
npm i node-sass -D
我在安装 node-sass 的时候老是出问题,我网络连github 很慢,然后就安装了淘宝的
cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
然后使用
cnpm
cnpm i node-sass -D
{
test: /\.scss$/,
use:[
'style-loader',
'css-loader',
'sass-loader'
]
}
使用webpack打包less
安装这两个包然后配置use:
less
less-loader
其它的 css 预编译打包没查
7. 使用webpack打包html资源
按照之前的方式新建一个项目,先执行npm init
然后 安装webpack webpack-cli
,新建src
文件夹,新建入口文件与html文件,用来测试
需要用到插件
npm i html-webpack-plugin -D
安装完成后首先引入
const HtmlWebpackPlugin = require('html-webpack-plugin') //引入class 它是一个构造器
然后再配置 webpack.config.js
的plugins
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
filename: "built.js",
path: path.resolve(__dirname,'build')
},
module: {
rules: []
},
plugins: [
new HtmlWebpackPlugin() // 这里
],
mode: "development"
}
然后直接运行
webpack
之后就能看到build
文件夹下面多了个html文件,打开可发现这个html页面自动引入了built.js
那么这个插件的功能默认就是:
默认创建一个空的HTML 文档,自动引入打包的所有文件(css/js)
使用参数传 template 指定参考html
我们肯定是需要自己定义好的结构的HTML文档而不是 空的HTML文档,所以:
new HtmlWebpackPlugin({
template:'./src/index.html'
})
假设
./src/index.html
这个文件我们已经定义好了结构,那么指定作为参考
8. 使用webpack打包图片资源
按照之前的方法创建一个新的项目,打包图片资源的时候仅仅需要一个包就能打包,
src
下新建 index.html
,编写
<body>
<div id="box1">1</div>
<div id="box2">2</div>
<div id="box3">3</div>
</body>
再新建一个样式文件,指定三个div的背景图片,然后在入口文件中引入样式文件就行了(此处省略)
npm install --save-dev file-loader
接下来配置webpack.config.js
,需要开启样式打包loader与html打包loader,给出改动的配置:
rules:[
{
test: /\.(jpg|png|gif)$/,
use: [
'file-loader'
]
}
]
然后打包运行,可以看到输出目录出来了几张图片资源,都被打包进去了
启用base64转换
如果要启用转换的话,那么再加一个依赖
npm install --save-dev url-loader
会将图片进行 url base64打包,转换成字符串
优点:变成了字符串编码,所以没有请求服务器,请求就-1
缺点:变成了字符串编码,(一长串的字符串)体积更大了些,解析起来慢
我们来配置url-loader
验证一下,并看看它是如何工作的
rules:[
{
test: /\.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:8 * 1024 // 指定如果图片size 小于等于 8kb 就启用 url base64编码
}
}
]
使用单个loader 可直接使用
loader
属性进行配置使用多个loader 就得使用
use
来进行顺序加载
注意 :url-loader
依赖于file-loader
很可惜,上面那种方法只能打包样式当中的图片,并不能打包html中链接的图片,比如:
<body>
<img src="1.jpg"> <!--这是打包不了的-->
</body>
所以此处再安装一个loader:
npm i html-loader -D
乍一看这个loader 是处理 html的,但其实不是。
新增一个配置:
{
test: /\.html$/,
loader: 'html-loader'
}
接下来进行打包:
webpack
打开构建完成的目录中的index.html
,发现会变成这样
<img src="[object Module]">
原因是因为
file-loader
,url-loader
采用的是ES6的模块化规范而
html-loader
采用的是CommonJS
的模块化规范
我们配置关闭ES6模式即可:
{
test: /\.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:8 * 1024
esModule:false
}
}
或者:
{
test: /\.(jpg|png|gif)$/,
loader: 'file-loader',
options: {
esModule:false
}
},
注意需要存在
loader
属性的时候才可配置options
属性。或者在use 中使用:(只需将数组元素写成对象的格式)
{ test:'', use:[ { loader:'', options:{} } ] }
启用资源重命名
{
test: /\.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:8 * 1024
esModule:false,
name:'[hash:10].[ext]'
}
}
指定options 的 name 属性,
[hash:10]
代表 取生成的hash值的前10位.
代表文件的.[ext]
代表文件夹的原始扩展名
启用压缩
需要用到这个 image-webpack-loader
依赖包
npm install image-webpack-loader --save-dev
小结
在这一章节认识了新属性
loader
options
options.limit
options.esModule
options.name
当在webpack打包时,如果使用到某一张图片多次,webpack 只打包出一张图片
9. 使用webpack打包其它类型资源
重复以上步骤,然后可以去导入阿里的iconfont 来测试,如.svg
.woff
.eto
.tff
这种类型的
均可使用 file-loader
来进行打包
npm i file-loader -D
然后写配置, 以下为 rules
中的一条
{
exclude: /\.(css|js|html)$/,
loader: 'file-loader',
options:{
name:'[hash:10].[ext]'
}
}
使用
exclude
排除掉了 css、js、html ,除了这些格式之外的 都走这条loader匹配
10. 使用devServer自动化
上面的例子中修改了一次代码就得重新webpack
打包一下 , 这样对于开发环境很麻烦,为此webpack 提供了自动化工具,接下来 来配置:
依然是在webpack.config.js
中 配置,
const xxx = require(‘xxx’) //导入
...
module.exports = {
entry:'',
output:{},
module:{},
plugins:{},
mode:'',
devServer:{
// 重点在这里!!
}
}
devServer 配置:
devServer:{
contentBase:path.resolve(__dirname,'dist'), // 指定最终运行哪个目录
compress:true, // 启用gzip压缩
port:8081, // 指定开发环境运行的端口号
open:true //指定自动打开浏览器运行项目
}
注意:配置了devServer 后不会在
dist
中进行输出打包文件,而是在内存中进行打包
使用 webpack-dev-server
指令来运行 devServer 配置,首先你需要安装这个依赖
npm i webpack-dev-server -D
然后再运行指令
npx webpack-dev-server
以后更改了src 下的代码后就会自动编译、打包、运行了
11. 开发环境的基本配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module:{
rules: [
// 处理scss sass
{
test:/\.(scss|sass)$/,
use:['style-loader','css-loader','sass-loader']
},
// 处理css
{
test: /\.css$/,
use:['style-loader','css-loader']
},
// 处理图片资源
{
test: /\.(jpg|png|gif)$/,
loader:'url-loader',
options:{
limit:8 * 1024, // 指定如果图片size 小于等于 8kb 就启用 url base64编码
esModule:false,
name:'[hash:10].[ext]'
}
},
// 处理 html 标签里面的图片资源
{
test: /\.html$/,
loader: 'html-loader'
},
// 处理其它资源
{
exclude: /\.(css|js|html|scss|jpg|png|gif)$/, // 其它资源统统交给 file-loader
loader: 'file-loader',
options: {
name:'[hash:10].[ext]'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
})
],
mode: "development", // or "production"
devServer:{
contentBase:path.resolve(__dirname,'dist'), // 指定最终运行哪个目录
compress:true, // 启用gzip压缩
port:8081, // 指定开发环境运行的端口号
open:true //指定自动打开浏览器运行项目
}
};