1.环境配置

全局安装

node install webpack webpack-cli -g

本地安装,指定版本,使用3.6.0时不需要安装webpack-cli

node install webpack@3.6.0 --save-dev

2.webpack起步

编写main.js

1
2
3
4
5
6
7
8
9
10
11
//main.js引用到其它模块时,webpack打包时会自动引入
const {add,mul} = require('./mathUtil')

console.log(add(1,2))
console.log(mul(2,2))

import {name,age,height} from "./info";

console.log(name)
console.log(age)
console.log(height)

打包命令

npx webpack ./src/main.js -o ./dist/bundle.js --mode development (默认使用的是全局安装的webpack进行打包)

表示把当前目录下的src/main.js作为入口进行打包,结果为当前目录下/dist/bundle.js,以开发的模式(代码不压缩,便于调试)

编写index.html

在index.html中引入bundle.js

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>

</body>
<script src="./dist/bundle.js"></script>
</html>

3.webpack配置

初始化

1
2
3
4
# 初始化当前文件夹,会生成package.json用以版本控制
npm init
# 本地安装webpack,@加版本号,可以指定版本,下方所有代码均以3.6.0为例
npm i webpack@3.6.0 --save-dev

编写webpack的配置文件webpack.config.js

1
2
3
4
5
6
7
8
const path = require('path')
module.exports = {
entry: './src/main.js', //表示webpack打包的入口
output: { //表示打包后的文件输出位置,即./dist/bundle.js
path: path.resolve(__dirname,'dist'), //表示路径./dist/
filename: 'bundle.js'
},
}

有了配置文件后,就可以在终端输入命令webpack来代替npx webpack ./src/main.js -o ./dist/bundle.js --mode development,值得注意的是,此处使用的webpack仍旧是全局的

package.json中添加一个script脚本

可以在package.json中添加一个script脚本,用脚本代替输入webpack命令

1
2
3
4
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},

之后便可使用nmp run build命令执行打包操作,区别就是使用脚本的方式,会优先使用本地版本的webpack,而webpack命令则直接使用全局webpack**,终端输入的命令都是默认全局**

一般为了控制版本,开发都是使用本地的webpack,因此可以用
npm install webpack@3.6.0 –save-dev
不加@3.6.0则使用默认的最新版本,–save-dev表示运行时依赖,可用-D简写

4.webpack-loader

​ 在我们之前的实例中,我们主要是用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关的依赖。

  但是,在开发中我们也需要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件等等。

  对于webpack本身的能力来说,对于这些转化是不支持的。因此需要安装配置对应的loader才可使用。

一般的loader安装步骤为:

  1. 从官网查询,通过npm安装需要使用的loader
  2. 在webpack.config.js中的modules关键字下进行配置

例如下方

4.1css-loader处理css

安装对应的loader

npm install --save-dev css-loader@2.0.2 style-loader@0.23.1

指定版本是为了和webpack@3.6.0进行兼容,后文的所有模块指定版本均为如此

在webpack.config.js中配置module相关信息

1
2
3
4
5
6
7
8
9
10
module:{
rules:[
//注意:一般使用时css-loader和style-loader以及webpack的版本可能会冲突。灵活使用
{
test: /\.css$/, //正则表达式,匹配.css结尾的文件
//loader的使用是从右向左的,css-loader负责打包css,而style-loader负责加载样式
use: ['style-loader','css-loader']
},
]
}

4.2less-loader处理less

less-loader负责处理less文件,less可编译成css文件

安装对应的loader

npm install --save-dev less-loader@4.1.0 less@3.9.0

less-loader负责把less文件加载成css文件,less是负责编译less代码的工具

在webpack.config.js中配置module相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module:{
rules:[
{
test: /\.less$/,
//use里也可以存放对象格式,配置loader的其它属性
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
//即使匹配.css文件时已经配置过css-loader和style-loader,在此处也不能缺少
},
]
}

4.3url-loader处理图片

当打包图片资源时需要引入的url-loader,url-loader需要依赖file-loader

npm install --save-dev url-loader@1.1.2

npm install --save-dev file-loader@3.0.1

配置module相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
module:{
rules:[ //只需配置url-loader,file-loader不需要配置rule
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [{
loader: 'url-loader',
options: {
//当图片小于8kb时,这也是limit属性的作用,对图片进行base64编码
//图片大小小于8kb,就会被base64处理
// 优点: 减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
//如果大于8kb,会通过file-loader进行处理
limit: 8 * 1024, //自己定义的值

// name属性指定生成图片的保存路径
// img:文件要打包到的文件夹
// name:获取图片原来的名字,放在该位置
// hash:8:为了防止图片名称冲突,依然使用hash,但是我们只保留8位
// ext:使用图片原来的扩展名
name: 'img/[name].[hash:8].[ext]',
}
}]
},
]
}

但是,我们发现图片并没有显示出来,这是因为图片使用的路径不正确。默认情况下,webpack会将生成的基于项目的路径直接返回给使用者。但是,我们整个程序是打包在dist文件夹下的,所以这里我们需要修改一下配置文件中的output。**(后文会介绍更优的方法)**

1
2
3
4
5
6
7
8
output: {
path: path.resolve(__dirname,'dist'),
filename: 'bundle.js',
//由于用file-loader生成的img图片后,webpack是直接返回绝对路径进行url引用的,从项目的根目录开始
//而设置publicPath后,会所有url都会拼接dist/,而不是使用本地电脑上的磁盘路径
//之后会介绍更优的方法
publicPath: 'dist/'
},

4.4babel-loader处理es6

由于我们的使用es6规范进行编码,而部分浏览器只支持es5的语法格式,因此需要配置对应的loader实现es6转es5

1
2
3
4
5
npm install --save-dev babel-loader@7.1.5 babel-core@6.26.3 babel-preset-es2015@6.24.1
# babel-loader依赖于babel-core进行处理,
# 而babel处理时根据配置文件进行配置,因此需要babel-preset-env
# 又由于我们使用babel只是用es6转es5,因此可不需要配置文件,
# 即可用babel-preset-es2015替代babel-preset-env

配置module相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module:{
rules:[ //只需配置url-loader,file-loader不需要配置rule
{
test: /\.js$/,
// 排除以下文件,他们不能进行随便的转化
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015'] //当配置babel-preset-env指定配置文件时['@babel/preset-env']
}
}
},
]
}

当在main.js中使用了es6语法,或者是引入了其它css,less,jpg等文件,例如require(‘./css/normal.css’),对应的loader会进行转换处理,便于webpack打包

5.webpack配置vue

5.1起步

当需要在项目中使用vue进行开发时,webpack默认支持处理vue文件,需要进行配置。

安装

1
2
npm install vue@2.5.21 --save # 为了兼容版本我们使用vue@2.5.21版本。
# 后续是在实际项目中也会使用vue的,所以并不是开发时依赖 --save-dev,去掉-dev

使用

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
{{message}}
</div>

</body>
<script src="./dist/bundle.js"></script>
</html>

main.js

1
2
3
4
5
6
7
import Vue from 'vue'
const app = new Vue({
el: "#app",
data: {
message: "Hello Vue!"
}
})

这样之后发现报如下错误:

bundle.js:1447 [Vue warn]:
You are using the runtime-only build of Vue where the template compiler is not available.
Either pre-compile the templates into render functions, or use the compiler-included build.

原因:

runtime-only :代码中不可以有任何的template。runtime-compiler:代码中可以有template,因为有compiler 可以用于编译template。在html中使用的div 就是vue实例的template。所以会报错。

解决方案:把runtime-only改成runtime-compile,在webpack.config.js中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname,'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
//解决runtime-only和runtime-compiler的问题
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
},
}

重新打包即可在webpack中使用vue


正常运行之后,我们来考虑另外一个问题:
如果我们希望将data中的数据显示在界面中,就必须修改index.html。
如果我们后面自定义了组件,也必须修改index.html来使用组件。
但是html模板在之后的开发中,我并不希望手动的来频繁修改,
当el和template共存时,template会替换el模块的html代码
因此可通过修改template实现间接的修改div#app

例如:

index.html中

1
2
3
<div id="app">
{{message}}
</div>

main.js中

1
2
3
4
5
6
7
8
9
10
11
12
13
const myVue = new Vue({
el: '#app',
template: `
<div>
<h2>{{message}}</h2>
<button>{{name}}</button>
</div>
`,
data:{
message:"Hello Vue!",
name: "点我"
}
})

标记#app的div标签会被替换为vue实例中的template

5.2使用vue文件解耦

虽然实现了html页面和vue的解耦,但是vue中的耦合了template和data和methods等,不易于开发,可以通过新建一个.vue文件把他们进行解耦。

例如:

app.vue文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!--编写html代码,template -->
<template>
<div>
<h2 class="title">{{message}}</h2>
<button @click="btnClick">{{name}}</button>
</div>
</template>

<!--编写js代码 -->
<script>
export default {
name: "app",
data(){
return {
message:"Hello Vue!",
name: "点我"
}
},
methods:{
btnClick(){
alert(("你点了点我!!!"))
}
},
components:{

}
}
</script>

<!--编写css代码 -->
<style scoped>
.title{
color: red;
}
</style>

main.js

1
2
3
4
5
import app from "./vue/app";
new Vue({
el:"#app2", //把该vue实例挂载到html页面中
template: `<app/>`,
})

index.html

1
2
3
<div id="app2">
{{message}}
</div>

抽取出.vue文件后,webpack无法识别打包,因此需要安装并配置对应的Loader

npm install vue-loader vue-template-compiler --save-dev

配置vue-loader版本大于15时,需要配置一个VueLoaderPlugin,并且注意vue-template-compiler和vue的版本需要一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const VueLoaderPlugin = require('vue-loader/lib/plugin');//用于vue-loader使用插件
module.exports = {
.......
module:{
rules:[
{
test: /\.vue$/,
use: {
loader: 'vue-loader'
}
}
]
},
plugins: [ //配置插件的节点,所有插件都要在这里配置
new VueLoaderPlugin(),
],
},

5.3vue组件相互调用

当你想引用其它组件时,如下:

app.vue文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div>
<h2 class="title">{{message}}</h2>
<button @click="btnClick">{{name}}</button>
<cpn></cpn><!--3使用该子组件 -->
</div>
</template>

<script>
import cpn from './cpn' //1. 引入组件(位于同一文件夹)
export default {
name: "app",
data(){
return {
message:"Hello Vue!",
name: "点我"
}
},
methods:{
btnClick(){
alert(("你点了点我!!!"))
}
},
components:{
cpn//2注册为子组件
}
}
</script>

<style scoped>
.title{
color: red;
}
</style>

main.js

1
2
3
4
5
6
7
8
9
import app from "./vue/app";
new Vue({
el:"#app2", //把该vue实例挂载到html页面中
template: `<app/>`,
components:{
//在该vue实例中注册import引入的app组件,然后再template中使用它
app //相当于app:app的简写
}
})

index.html

1
2
3
<div id="app2">
{{message}}
</div>

在js引入文件时,一般需要加上后缀名,例如import app from “./vue/app.vue”;

有时候我们不想写文件的后缀名,可以进行如下配置

1
2
3
4
5
6
module.exports = {
resolve: {
// 配置 省略文件后缀名,以后在使用时,可省略文件后缀,.js默认可省,若配置了extensions,则必须显示配置.js
extensions: ['.js', '.css', '.vue'],
},
}

6.webpack-plugin

plugin,顾名思义是对webpack功能的扩展插件

于loader类型,需要安装并且在webpack.config.js中进行配置

BannerPlugin

属于webpack自带的插件,不需要安装用于为打包的文件添加版权声明

使用如下

1
2
3
4
5
6
7
const webpack = require('webpack')  //使用webpack自带的banner插件
module.exports = {
plugins: [ //配置插件
//然后便可在打包得到的bundle.js中看到此说明
new webpack.BannerPlugin('版权所有,转载请注明出处!'),
],
}

html-webpack-plugin

考虑一个问题:目前,我们的index.html文件是存放在项目的根目录下的。

在真实发布项目时,发布的是dist文件夹中的内容,但是dist文件夹中如果没有index.html文件,那么打包的js等文件也就没有意义了。
所以,我们需要将index.html文件打包到dist文件夹中,这个时候就可以使用HtmlWebpackPlugin插件

安装html-webpack-plugin的作用
自动生成一个空的index.html文件到dist中(可以指定模板来生成)
将打包的js文件,自动通过script标签插入到body中

使用如下

安装

npm install html-webpack-plugin@3.2.0 --save-dev

在配置文件中引入插件,使用插件

1
2
3
4
5
6
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin(),
],
}

当我们需要生成的index.html代码需要有一定代码时,就需要指定模板
一般需要指定一个html作为模板去生成index.html,便于加载vue相关代码
只需在配置文件中更改为:
new HtmlWebpackPlugin({
template: “index.html”,
}),

模板中的script可不添加,会自动引入

uglifyjs-webpack-plugin

npm install uglifyjs-webpack-plugin@1.1.1 --save-dev

使用uglify压缩代码
版本号指定1.1.1,和后面要使用CLI2保持一致,便于兼容
注意,在webpack4之后,只要我们将生产模式设置为生产环境, mode: ‘production’ 它就会自动压缩js代码。

1
2
3
4
5
6
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
plugins: [
new UglifyjsWebpackPlugin(),
],
}

7.webpack-dev-server

webpack提供了一个可选的本地开发服务器webpack-dev-server,
这个本地服务器基于node.js搭建,内部使用express框架,
可以实现我们想要的让浏览器自动刷新显示我们修改后的结果。

步骤:

  1. npm install –save-dev webpack-dev-server@2.9.1
    安装的版本是需要与webpack以及vue脚手架对应的,此处指定2.9.1
  2. 在配置文件中进行如下配置
    devServer: {
     //为哪个文件夹提供本地服务,默认是根目录
    contentBase: resolve(__dirname,’dist’),
     inline: true, //页面实时刷新
     port:8080,//端口号,默认8080
    },
  3. 添加一个脚本命令,运行本地服务器,因为web-dev-server是本地安装的,因此不可直接在命令行使用命令

–open表示自动通过浏览器打开
“scripts”: {
“dev”: “webpack-dev-server –open”
},
注意:当手动ctrl +s时,服务器会自动编译,当开发软件失去焦点后也会自动编译

webpack.config.js

1
2
3
4
5
6
7
8
9
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
devServer: {
//为哪个文件夹提供本地服务,默认是根目录
contentBase: path.resolve(__dirname,'dist'),
inline: true, //页面实时刷新
port:8080,//端口号,默认8080
},
}
1
2
3
4
5
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"dev": "webpack-dev-server --open"
},

之后便可使用命令npm run dev开启本地服务器


注:笔记根据B站视频学习整理