# 9. webpack

本文webpack版本如下所示,版本不同命令可能会不一致,相关的配置可能会不一致。

https://www.webpackjs.com/concepts/

# 前言

# 在网页中会引用哪些常见的静态资源?

  • js
    • .js
    • .jsx
    • .coffee
    • .ts(TypeScript)
  • css
    • .css
    • .less
    • .sass
    • .scss
  • Images
    • .jpg
    • .png
    • .gif
    • .bmp
    • .svg
  • 字体文件(Fonts)
    • .svg
    • .ttf
    • .eot
    • .woff
    • .woff2
  • 模板文件
    • .ejs
    • .jade
    • .vue[这是在webpack中定义组件的方式(推荐)]

# 网页中静态资源多了会产生的问题

  1. 网页加载速度慢,需要发起很多二次请求;
  2. 要处理错综复杂的依赖关系;

# 如何解决上述问题

  1. 合并、压缩、精灵图、图片的Base64编码
  2. 可以使用requireJS、也可以使用webpack可以解决各个包之间的复杂依赖关系。

# 如何完美实现上述的解决方案

  1. 使用Gulp基于task任务
  2. 使用Webpack基于整个项目进行构建

# webpack是什么?

webpack 是前端的一个项目构建工具,它基于 Node.js 开发出来的一个前端打包工具。

一张图概括webpack可以做的事情。

不仅如此,它可以为我们提供良好的语法支持。

比如在正常浏览器下某些ES6语法并不支持,比如import关键字,webpack能够帮助我们把这些不被浏览器认识的语法解析成浏览器能正常识别的语法,使我们在开发过程中无需再担心ES6语法不兼容的问题。

# webpack安装的两种方式

全局安装(不推荐)

npm i webpack -g
1

局部安装(推荐)

下列选择指定版本安装或者直接最新安装,建议选择版本安装。

请在项目根目录执行命令

npm install --save-dev webpack
npm install --save-dev webpack@<version>
1
2

webpack4.x以上还需要安装CLI

npm install --save-dev webpack-cli
1

# 使用webpack打包构建项目

# 列表隔行变色案例(基础打包)

1.运行npm init -y初始化项目,使用npm管理项目中的依赖包。

注意:直接使用npm init会让你输入很多信息,一般直接npm init -y即可。

2.创建项目基本目录结构

规范化项目结构,拥有一个dist目录、src目录,src下包含jsimagecss目录,并拥有index.html主页,main.js入口js文件。

3.使用npm i jquery安装jquery类库

4.创建main.js并书写隔行变色的代码逻辑:

// main.js 是项目的入口文件
// 1. 导入jquery
// import *** from *** 是ES6中导入模块的方式
// 由于浏览器解析不了ES6语法,所以不使用打包工具这一行执行会报错
import $ from 'jquery'
// 等同于node.js 中的 const $ = require('jquery')

$(function () {
    $('li:odd').css('backgroundColor', 'lightblue')
    $('li:even').css('backgroundColor', function () {
        return '#' + 'D97634'
    })
})
1
2
3
4
5
6
7
8
9
10
11
12
13

5.编写index.html页面代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <!-- 注意: 不推荐直接在这里引入任何包和任何css文件 -->
    <script src="../dist/bundle.js"></script>
    <style>
        
    </style>
</head>
<body>
    <ul>
        <li>这是第1个li</li>
        <li>这是第2个li</li>
        <li>这是第3个li</li>
        <li>这是第4个li</li>
        <li>这是第5个li</li>
        <li>这是第6个li</li>
        <li>这是第7个li</li>
        <li>这是第8个li</li>
        <li>这是第9个li</li>
        <li>这是第10个li</li>
    </ul>
</body>
</html>
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

5.使用webpackmain.js打包成bundle.js文件,执行命令。

注意:

下面语法使用对应版本

npx webpack ./src/main.js -o ./dist/main.js
1

注意:

上述命令包含了npx命令,该命令是调用项目安装的模块。

npx 的原理很简单,执行命令时会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。

由于 npx 会检查环境变量$PATH,所以系统命令也可以调用。

6.直接打开index.html 可看到如下效果。

# 使用配置文件打包

1.在项目根目录我们创建一个webpack.config.js文件。

// 这个配置文件,其实就是一个js文件,通过 Node 中的模块操作,向外暴露一个配置对象。
// 下面使用的 const path = require('path') 是node中的语法,获取到根目录路径。
const path = require('path')
module.exports = {
    // 手动定义 入口 和 出口
    entry: path.join(__dirname, './src/main.js'), // 打包哪个文件
    output: { // 输出目录相关的位置
        // 指定打包好的文件输出到哪个目录
        path: path.join(__dirname, './dist'),
        filename: 'bundle.js' // 这是指定输出的文件的名称
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

2.根目录输入命令打包

npx webpack
1

# 使用热部署

使用 webpack-dev-server 工具实现自动打包编译的功能。

执行以下命令安装

npm i webpack-dev-server -D
1

安装完成后直接替换webpack命令即可。

注意:局部安装需要加上npx命令

webpack-dev-server
1

# 使用命令行方式配置(推荐)

webpack-dev-server --port 80 --contentBase src --open --hot
1
  • --open 启动服务后,默认打开浏览器
  • --contentBase xxx 指定托管的根目录
  • --hot 热部署,修改一行代码保存只更新一行代码,同时实现浏览器异步刷新。
  • --port xxxx 指定服务端口

# 使用配置文件方式配置

webpack.config.js文件中添加依赖。

// 导入webpack包,需要用到webpack的HotModuleReplacementPlugin插件对象。
const webpack = require('webpack')
1
2

plugins节点中创建插件对象。

plugins: [
    // new 一个 热部署的模块对象
    new webpack.HotModuleReplacementPlugin()
]
1
2
3
4

在跟节点中配置devServer

devServer: {
    open: true, // 默认打开浏览器
    port: 80, // 设置端口
    contentBase: 'src', // 指定托管的根目录
    hot: true // 启用热部署
}
1
2
3
4
5
6

# 使用html-webpack-plugin插件

上述webpack打包不会帮我们打包html,所以需要html-webpack-plugin来进行html的打包,并且实现自动加载js文件。

添加依赖

npm i html-webpack-plugin -D
1

导入插件

在webpack.config.js文件中导入插件

// 导入html-webpack-plugin插件
const htmlWebpackPlugin = require('html-webpack-plugin')
1
2

创建插件对象

plugins节点中创建插件对象。

// 创建html-webpack-plugin插件
new htmlWebpackPlugin({
    // 需要托管的html文件路径
    template: path.join(__dirname, './src/index.html'),
    // 托管后的html文件名
    filename: 'index.html'
})
1
2
3
4
5
6
7

# 使用loader打包样式表

添加依赖

下面包含了css/less/sass的依赖

npm i style-loader css-loader less less-loader -D
cnpm i node-sass sass-loader -D
1
2

webpack.config.js文件中modulerules增加匹配对象

module: {
    // 这个节点,用于配置所有的第三方模块加载器
    rules: [
        // 这是所有第三方模块的匹配规则
        // 匹配正则 - 使用什么loader 注意loader加载顺序为从右到左
        { test: /\.css$/, use: ['style-loader', 'css-loader'] },
        { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },
        { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }
    ]
}
1
2
3
4
5
6
7
8
9
10

main.js导入cssless样式表

import './css/index.css'
import './css/index.less'
import './css/index.scss'
1
2
3

# loader

# 什么是loader?

在使用webpack经常需要跟loader打交道,loader到底是什么呢?

我们可以理解为它就是一个webpack的第三方装载器集合,它为我们提供了很多插件解决webpack无法装载一些特别文件的问题。

有了它我们可以在打包时把静态资源比如图片、字体库、css样式表这些文件一起打包。

# 使用loader打包url文件

在项目中经常用到图片等信息,如果不加loader,webpack默认不打包这些资源。

添加依赖

cnpm i url-loader file-loader -D
1

webpack.config.js文件中modulerules增加匹配对象

配置打包图片

{
    test: /\.(jpg|jpeg|png|gif|bmp)$/, use: {
        loader: 'url-loader',
        options: { limit: 5000, name: '[hash:8]-[name].[ext]' }
    }
}
1
2
3
4
5
6

配置打包字体文件

{ test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' }
1

# Babel 高级语法支持

# 介绍

image

官方网站:https://www.babeljs.cn/

当遇到javascript高级语法,比如class关键字是ES6的高级语法,使用webpack打包默认并不支持这些语法导致无法编译。

而我们可以添加babelloader对这些高级语法进行有效编译。

babel原理是将高级语法转换为低级语法,使webpack能够识别。

下面指引将以最新的dabel7作为标准。

# 使用步骤

添加依赖(执行下面两行命令)

npm i @babel/core@7 @babel/plugin-proposal-class-properties@7 @babel/plugin-transform-runtime@7 @babel/preset-env babel-loader -D
npm i @babel/runtime@7 -S
1
2

上述添加了以下包

  • @babel/core
    • 源码
  • @babel/plugin-proposal-class-properties
    • class部分语法支持
  • @babel/plugin-transform-runtime
    • 避免编译重复
  • @babel/preset-env
    • 语法支持
  • babel-loader
    • babel加载器
  • @babel/runtime
    • 配合transform-runtime,添加到构建版本中

webpack.config.js中的module节点下的 rules数组中添加新的匹配规则

{ test:/\.js$/, use: 'babel-loader', exclude: /node_modules/ }
1

exclude排除node_modules的目录,避免babel对第三方js文件进行打包编译。

在项目根目录新建文件.babelrcbabel配置文件。

文件采用JSON格式进行编写如下配置。

{
    "presets": [
        "@babel/preset-env"
    ],
    "plugins": [
        "@babel/plugin-transform-runtime",
        "@babel/plugin-proposal-class-properties"
    ]
}
1
2
3
4
5
6
7
8
9

配置完成

最近更新: 2019/10/17 上午4:20:42