Node学习第六天

165 阅读22分钟

webpack

yarn包管理器

注意: 如果yarn实在安装不上可以用npm

快速、可靠、安全的依赖管理工具。(类似npm作用)

中文官网地址: yarn.bootcss.com/

下载yarn

下载地址: yarn.bootcss.com/docs/instal…

  • windows - 软件包(在笔记文件夹里)

    • ==建议不要安装到中文路径下==
    • ==建议和node安装到一个盘符下==
  • mac - 通过命令安装(也可还用npm)

sudo npm i -g yarn

如果上面不行, 试试这个

curl -o- -L https://yarnpkg.com/install.sh | bash

使用yarn

与npm类似, 可以试试, 新建一个空白文件夹, 执行以下命令尝试一下

# 1. 初始化, 得到package.json文件(终端路径所在文件夹下)
yarn init  -y
# 类似: npm init

# 2. 添加依赖(下包)
# 语法: yarn add [package]
# 语法: yarn add [package]@[version]
yarn add jquery
yarn add jquery@3.5.1
# 类似: npm install jquery

# 3. 移除包
# 语法: yarn remove [package]
yarn remove jquery
# 类似: npm remove jquery
             
# 4. 安装项目全部依赖(一般拿到别人的项目时, 缺少node_modules)          
yarn
# 会根据当前项目package.json记录的包名和版本, 全部下载到当前工程中
# 类似: npm i

# 5. 全局
# 安装: yarn global add [package]
# 卸载: yarn global remove [package]
# 注意: global一定在add左边
yarn global add @vue/cli
# 如何使用, 为明天学习vue做铺垫
# 类似: npm install -g @vue/cli 

yarn可能遇到的问题

如果报错参考报错文档: lidongxuwork.gitee.io/error/#811

建议安装的vscode插件

文件夹和文件的关系, 和该创建文件, 不要创建文件夹了

1632318934691.png

知识点自测

对这些知识点了如指掌, 学习今天的内容会轻松很多

  • 如何使用ES6模块化
  • 默认导出和导入
// 默认导出
export default {
    a: 10,
    b: 20
}

// 默认导入
import Obj from 'js文件路径'
  • 按需导出和导入
// 按需导出
export {
	a: 10,
	b: 20
}
// 按需导入
import {a, b} from 'js文件路径'
import * as Obj from 'js文件路径' // 搜集*所有按需导出, 合并到变量obj中
  • 无导出和导入(只为让js代码执行)
// 无导出
Array.prototype.MyForEach = function(){
    // ...内部实现略
}

// 无导入
import "js文件路径"

// 后面用数组就可以调用MyForEach方法了
  • 字体图标的使用

    1. 去阿里巴巴矢量图标库, 选中想要的图标, 登录后, 生成css文件和字体文件
    2. 下载css文件和字体文件, 也可以使用在线地址
    3. 在自己页面中引入iconfont.css, 并在想显示字体图标的标签上使用类名即可
  • ==箭头函数非常熟练, 伸手就写==

// 1. 基础定义
const fn = () => {}   
fn()

// 2. 有参, 有返回值
const fn2 = (a, b) => {return a + b} 
fn(10, 20); // 结果是30

// 3. 参数"只有一个", 省略()
const fn3 = a => {return a * 2}
fn(50); // 结果是100

// 4. 函数体"只有一句"可以省略大括号和return, "默认返回这句话结果"给函数调用地方
const fn4 = a => a * 2;
fn(50); // 结果是100
  • 什么是服务器, 本地如何搭建服务器, 服务器和浏览器关系, 什么是请求和响应
// 1. 什么是服务器
// 服务器是一台性能高, 24小时可以开机的电脑
// 服务器可以提供服务(例如: 文件存储, 网页浏览, 资源返回)

// 2. 本地如何搭建服务器
// 安装node软件环境, 下载express模块包, 编写相关代码, 即可得到一个web服务器, 给前端返回资源

// 3. 服务器和浏览器的关系
// 浏览器不负责保存网页, 都要靠着url地址去服务器后端, 请求网页相关代码, 回来在浏览器上解析显示
// 浏览器也不负责保存数据, 如果是前后端分离项目, 也要用ajax调用后端接口, 拿到数据回到浏览器上铺设显示

// 4. 请求和响应区别
// 浏览器 -> 请求资源 -> 服务器

// 浏览器 <-  响应数据 <- 服务器
  • 开发环境 和 生产环境 以及英文"development", "production" 2个单词会写会读

  • 初始化包环境和package.json文件作用

// npm下载的包和对应版本号, 都会记录到package.json文件里
// 把项目发给别人, 他也用包管理器, 一个命令就能下载你项目需要的所有第三方依赖包
  • 终端的熟练使用: 切换路径, 清屏, 包下载命令等
切换路径  cd  

清屏 cls 或者 clear

今日学习目标

  1. 能够理解webpack基本概念和作用

  2. 能够掌握webpack使用步骤

  3. 能够使用webpack相关配置

  4. 能够使用webpack开发服务器

  5. 能够使用webpack中文文档

1.webpack-概念

目标

为何学webpack

什么是webpack

场景

开发完项目, 可以用node+webpack来分析, 翻译, 压缩, 打包, ==加快浏览器打开速度==

1627289735578.png

1627289742417.png

概念

webpack官网

  • 现代 javascript 应用程序的 静态模块打包器 (module bundler)

    • 静态: 文件资源

    • 模块: node环境, 引入文件, 遵守模块化语法

  • 除了合并代码, 还可以翻译压缩代码

    • less/sass -> css
    • ES6/7/8 -> ES5
    • html/css/js -> 压缩合并

image-20210207234927772.png

小结

  1. 什么是webpack?

    答案
    • 静态模块打包器
    • 还能翻译和压缩代码
    • 减小代码包体积, 让浏览器更快速打开网页

2.webpack-使用前-准备

目标

用webpack, 需要准备什么

软件

webpack依赖Node环境

npm或yarn等模块管理工具

步骤

  1. 创建Day01_webpack基础使用文件夹
  2. 初始化包环境
yarn init
  1. 安装依赖包

    为何指定版本: 防止以后包更新, 造成课程内容报错

yarn add webpack@5.31.2 webpack-cli@4.6.0 -D
  1. 在package.json中, 配置scripts(自定义命令)
scripts: {
	"build": "webpack"
}

小结

  1. 使用webpack前, 准备什么?

    答案
    • Node环境软件
    • npm或yarn模块管理器
    • 项目文件夹和包环境
    • 下载webpack并配置命令

3.webpack-基础使用

目标

学习webpack使用, 打包2个js文件

步骤

  1. 新建src/add/add.js - 定义求和函数导出
export const addFn = (a, b) => a + b
  1. 新建src/index.js导入使用
// webpack打包的入口
import { addFn } from './add/add'
console.log(addFn(5, 2));
  1. 运行打包命令
yarn build

效果

  1. src并列处, 生成dist目录和main.js文件

  2. 查看main.js文件, 是打包压缩后的代码

(()=>{"use strict";console.log(7)})();
  1. 打包关系图

1627448159455.png

小结

  1. webpack如何使用?

    答案
    • 先下载安装webpack, 配置打包命令
    • 默认入口src/index.js-要被打包的文件, 要引入到这里使用
    • 输入yarn build打包命令(实际是项目环境webpack命令)
    • 输出代码到dist/main.js中

4.webpack-更新打包

目标

代码变化, 如何打包

步骤

  1. 新建src/tool/tool.js - 导出数组求和方法
export const getArrSum = arr => arr.reduce((sum, val) => sum += val, 0)
  1. src/index.js - 导入使用
import { addFn } from './add/add'
import { getArrSum } from './tool/tool'

console.log(addFn(5, 2));
console.log(getArrSum([5, 6, 9, 10]));
  1. 重新打包
yarn build

效果

  1. 自动覆盖原dist, 结果压缩极致
(()=>{"use strict";console.log(7),console.log([5,6,9,10].reduce(((o,e)=>o+e),0))})();

1627450857686.png

小结

  1. 代码增加后如何打包?

    答案
    • 要和src/index.js有直接或间接的引入关系
    • 重新执行yarn build

5.webpack-配置修改

目标

修改默认入口和出口

默认入口: src/index.js

默认出口: dist/main.js

步骤

配置文档

  1. 项目根目录 - 新建webpack.config.js文件 (默认配置文件名)
  2. 填入配置项
const path = require("path")

module.exports = {
    entry: "./src/main.js", // enter: 默认入口
    output: { 
        path: path.join(__dirname, "dist"), // 出口"文件夹"名
        filename: "bundle.js"               // 出口"文件"名
    }
}
  1. 修改代码里src/index.js 为 src/main.js
  2. 重新打包观察输出文件名

小结

  1. webpack默认入口和出口是什么?

    答案
    • 默认入口src/index.js
    • 默认出口dist/main.js
  2. webpack默认配置文件名?

    答案
    • webpack.config.js

6.webpack-打包流程图

目标

运行yarn build发生了什么

图示流程

  1. 敲击命令, 代码执行过程

image-20210421125257233.png 2. 代码源文件和webpack之间关系图

源码一定要和入口产生直接/间接引入关系, 才会被一起打包

1627471544248.png

小结

  1. 简述总结下打包流程?

    答案
    • 执行局部webpack命令(前提项目中下载了webpack包)
    • 有webpack.config.js用, 否则用内置默认
    • 根据入口建立引入关系
    • 编译翻译整合打包输出到指定位置
  2. 模块想要被webpack识别打包, 要注意什么?

    答案
    • 模块文件要和webpack入口产生直接或间接引入关系

7.webpack-案例-发送ajax

目标

webpack打包前端项目

yarn下的包, 如何作用在前端项目

步骤

  1. 回顾从0准备环境

    • 初始化包环境

    • 下载依赖包

    • 配置自定义打包命令

  2. 下载jquery

yarn add axios
  1. 新建public/index.html - 前端首页
  2. 新建src/main.js - webpack打包入口

image-20210208100817930.png

  1. index.html 准备一些li
<!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>
</head>
<body>

    <button>按钮</button>

</body>
</html>
  1. 在src/main.js引入jquery
import axios from 'axios'
  1. main.js中编写, 隔行变色代码
document.querySelector("button").onclick = function() {
    axios({
        url: 'http://www.liulongbin.top:3009/api/getbooks'
    }).then(({data:res}) => {
        console.log(res);
    });
}
  1. 执行打包命令
yarn build
  1. 把public/index.html手动复制到dist下

image-20210421125602484.png 10. 再手动引入打包后bundle.js

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

关键

  1. yarn下的包, 在js文件里, 用import语法导入

    浏览器不支持import语法

  2. webpack翻译打包后输出到bundle.js

  3. html页面引入翻译打包后的js即可正常使用

1627556803300.png

小结

  1. 前端项目如何使用yarn下的包?

    答案
    • 借助webpack, 把模块和代码打包
    • 把打包后js文件, 引入到html执行查看效果

8.webpack-插件-自动生成html文件

目标

学习webpack插件html-webpack-plugin

自动生成html文件

自动引入打包后文件

步骤

html-webpack-plugin插件文档

  1. 下载插件

    yarn add html-webpack-plugin@5.3.1  -D
    
  2. webpack.config.js配置

    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin') 
    
    module.exports = {
        // ...省略其他代码
        plugins: [
            new HtmlWebpackPlugin({
                // 以此为基准生成打包后html文件
                template: './public/index.html' 
            })
        ]
    }
    
  3. 重新打包后观察dist下

    • 自动生成html文件
    • 自动引入打包后js文件

总结: webpack就像一个人, webpack.config.js是人物属性, 给它穿什么装备它就干什么活

小结

  1. 自动生成html和引入打包后文件, 如何做?

    答案
    • 下载html-webpack-plugin插件包, 给webpack.config.js配置上

9.webpack-加载器-处理css文件问题

目标

webpack能否打包css文件

步骤

1.新建 - src/css/index.css

2.编写去除li圆点样式代码

button {
    width: 200px;
    height: 50px;
}

3.==在main.js引入index.css==

一定要引入到入口才会被webpack打包

import "./css/index.css"

4.执行打包命令观察效果

错误解释: 你可能需要一个loader来支持这种类型文件, 解析css代码

原因: webpack默认只识别js文件

1627617044316.png

小结

  1. 为何webpack打包css文件会报错呢?

    答案
    • 不能, 因为webpack默认只识别js文件

10.webpack-加载器-处理css文件

目标

学习loader加载器, 打包更多类型文件

步骤

style-loader文档

css-loader文档

  1. 安装依赖

    需要这2个模块包, 帮助webpack打包css

    yarn add css-loader@5.2.1 style-loader@2.0.0  -D
    
  2. webpack.config.js 配置

    module.exports = {
        // ...其他代码
        module: { // 如何处理项目中不同模块文件
            rules: [ // 规则
              {
                test: /\.css$/, // 匹配所有的css文件
                // use数组里从右向左运行
                // 先用 css-loader 让webpack能够识别 css 文件的内容并打包
                // 再用 style-loader 将样式, 把css插入到dom中
                use: [ "style-loader", "css-loader"]
              }
            ]
        }
    }
    
  3. 执行打包命令, 观察打包后dist下

效果

  1. css代码被打包进了dist/bundle.js中
  2. 运行时, css代码插入到html的style标签中

小结

  1. webpack如何支持css打包?

    答案
    • 使用style-loader和css-loader
  2. style-loader和css-loader作用?

    答案
    • css-loader让webpack识别.css文件, 打包代码到js中
    • style-loader把js中的css代码, 插入到style标签里显示
  3. 打包后样式在哪里?如何生效?

    答案
    • 打包后样式在.js文件中
    • 运行后, 被插入到style标签里

11.webpack-加载器-处理less文件

目标

学习less-loader处理.less文件

步骤

less-loader文档

  1. 新建src/less/index.less - 设置li字体大小24px
@size:24px;

body {
    button {
        font-size: @size;
    }
}
  1. 引入到main.js中
import "./less/index.less"
  1. 下载依赖包
yarn add less@4.1.1 less-loader@8.1.0 -D
  1. webpack.config.js 配置
module: {
  rules: [ 
    // ...省略其他
    {
    	test: /\.less$/, // 匹配.less结尾文件
    	// 使用less-loader, 让webpack处理less文件, 内置还会用less模块, 翻译less代码成css代码
        use: [ "style-loader", "css-loader", 'less-loader']
    }
  ]
}

总结: 只要找到对应的loader加载器, 就能让webpack处理不同类型文件

小结

  1. webpack如何支持less打包?

    答案
    • 下载less和less-loader2个包
    • less-loader识别less文件
    • less是翻译less代码到css代码
  2. less翻译后, 还要注意什么?

    答案
    • 还要用css-loader把css代码进js中
    • style-loader, 把css代码插入到DOM上

12.webpack-加载器-处理图片文件

目标

配置webpack, 打包图片文件

步骤

  1. 素材文件夹/2个图文件
  2. 在css/less/index.less - 把小图片用做背景图
body{
    background: url(../assets/logo_small.png) no-repeat center;
}
  1. 在src/main.js - 把大图插入到创建的img标签上, 添加body上显示
// 引入图片-使用
import imgUrl from './assets/1.gif'
const theImg = document.createElement("img")
theImg.src = imgUrl
document.body.appendChild(theImg)

配置

webpack5内置处理方案, 只需要填入配置即可

asset module资源模块文档

  1. webpack.config.js填写
module: {
    rules: [ 
        // ...省略其他
        {
            test: /\.(png|jpg|gif|jpeg)$/i, // 匹配图片文件
            type: 'asset' // 在导出一个 data URI 和一个单独的文件之间自动选择
        }
    ]
}

  1. 打包后运行dist/index.html观察区别

小结

  1. webpack如何支持图片打包?

    答案
    • webpack5内置了, 只需要配置type:'asset'

13.webpack-加载器-图片处理区别

目标

为何图片要分2种情况处理

配置

  1. asset模块区分
module: {
    rules: [ 
        // ...省略其他
        {
            test: /\.(png|jpg|gif|jpeg)$/i, // 匹配图片文件
            type: 'asset' // 在导出一个 data URI 和一个单独的文件之间自动选择
            // 小于8kb的, 转成data URI(图片转成base64字符串打包进js中)
            // 大于8kb的, 直接复制文件到dist目录下(因为转base64会体积增30%)
        }
    ]
}

小结

  1. 对图片有哪两种处理方案?

    答案
    • 默认8kb以下图片, 转成base64字符串打包进js中, 减少网络请求次数
    • 超过8kb的图片, 直接复制到dist下, 转base64会增加30%体积

14.webpack-加载器-处理字体文件

目标

webpack如何处理字体文件

步骤

  1. 素材文件夹/字体库fonts文件夹
  2. 在main.js引入iconfont.css
// 引入字体图标文件
import './assets/fonts/iconfont.css'
  1. 在public/index.html使用字体图标样式
<i class="iconfont icon-weixin"></i>

配置

webpack5, 用asset module技术

webpack.config.js

{ 
    test: /\.(eot|svg|ttf|woff|woff2)$/,
    type: 'asset/resource',  // 当做静态资源直接复制文件
    generator: {
    	filename: 'font/[name].[hash:6][ext]' // 放到dist/font文件夹, 文件名格式如左
    }
}

小结

  1. webpack如何处理字体文件?

    答案
    • 在webpack.config.js的rules里针对字体图标文件类型设置asset/resource,直接输出到dist下

15.webpack-加载器-处理高版本js语法

目标

让webpack, 对高版本js语法降级

介绍

babel编译器=> 用于处理高版本 js语法 的兼容性 babel官网

webpack配合babel-loader 对js语法做处理 babel-loader文档

步骤

  1. src/main.js - 编写箭头函数
const fn = () => { // 高级语法
  console.log("你好babel");
}
console.log(fn) // 一定打印函数, 才会被webpack把"函数体"打包起来
  1. 安装包
yarn add -D babel-loader@8.2.2 @babel/core@7.13.15 @babel/preset-env@7.13.15
  1. webpack.config.js 配置规则
module: {
    rules: [
        {
            test: /\.js$/, // 匹配js结尾文件
            exclude: /(node_modules|bower_components)/, // 不转换这2个文件夹里的js
            use: { 
                loader: 'babel-loader', // 使用加载器-处理
                options: {
                    presets: ['@babel/preset-env'] // 预设:转码规则(用bable开发环境本来预设的)
                }
            }
        }
    ]
}
  1. 打包后观察dist/的js文件, 自动变成普通函数

小结

  1. webpack如何帮助我们降低js版本语法?

    答案
    • 借助babel-loader和babel编译器,给webpack配置上, 翻译再打包使用

16.webpack-开发服务器-为何学

目标

开发时, 快速自动打包查看效果

问题

每次修改代码, 重新打包, 才能看到最新的效果

实际工作中, 打包非常费时 (10-30s) 之间, 影响开发效率

原因

  1. 构建入口和所有模块依赖关系图
  2. 磁盘读取对应的文件到内存, 才能加载
  3. 用对应的 loader 进行处理和翻译
  4. 将处理完的内容, 输出到磁盘指定文件内
  5. 以后代码变化, 从1重新开始

代码演示

复制上一个项目

写几行代码, 想要看打包后运行效果, 打包ing....

又改了几行代码, 想看打包后运行效果, 重新打包ing...(2000 Years later..)

小结

  1. 为何要学webpack的开发服务器?

    答案
    • 因为webpack每次打包很久, 甚至只改几行代码, 也要从0打包

17.webpack-开发服务器-学习

目标

下载webpack-dev-server, 启动一个开发服务器, 用于快速开发应用程序

步骤

webpack-dev-server文档

  1. 构建入口和所有模块依赖关系图
  2. 磁盘读取对应的文件到内存, 才能加载
  3. 用对应的 loader 进行处理和翻译
  4. 将处理完的内容, 输出到内存里而非磁盘上
  5. 以后代码变化, 自动更新打包变化的代码, 显示到浏览器上

步骤

  1. 下载包

    yarn add webpack-dev-server@3.11.2 -D
    
  2. 配置自定义命令serve

    scripts: {
    	"build": "webpack",
    	"serve": "webpack serve"
    }
    
  3. 运行命令-启动webpack开发服务器

    yarn serve
    #或者 npm run serve
    
  4. 启动一个web服务器和端口, 在浏览器访问查看

效果: 以后改src下的代码, 自动打包更新到浏览器上

小结

  1. 如何用webpack开发服务器, 实时打包我们的代码?

    答案
    • 下载webpack-dev-server包
    • 在package.json配置serve命令, 启动
    • webpack-dev-server给我们一个地址+端口, 供浏览器访问查看index.html页面和打包后的js和css等
  2. webpack开发服务器好处是?

    答案
    • 打包进内存里, 使用更快
    • 代码变化, 只会重新打包和更新, 变化的文件和代码

18.webpack-开发服务器-配置

目标

查找文档, 修改开发服务器配置

步骤

webpack-dev-server配置文档

  1. webpack.config.js中添加服务器配置

    module.exports = {
        // ...其他配置
        devServer: {
          port: 3000, // 端口号
          open: true // 启动后自动打开浏览器
        }
    }
    
  2. 重启开发服务器观察效果即可

小结

  1. 如何修改webpack开发服务器的配置呢?

    答案
    • 去文档查找配置项的名字
    • 在webpack.config.js的devServer选项里添加

19.webpack-项目打包发布

目标

项目做完了, 要上线怎么办

步骤

  1. 执行之前的yarn build产生dist目录

    所有代码, 被整合打包

  2. 把dist目录交给后台/运维, 部署给客户使用即可

    开发环境的代码不用发

  3. 准备一个后端web服务, 把dist放进去, 暴露成静态资源目录供别人访问

    // 准备一个node+express的web服务, 可以部署和启动在一个接入外网的电脑上, 别人都可以访问
    
    const express = require('express')
    const app = express()
    
    // . 当前文件所在文件夹
    // / 打开文件夹
    // ./当前当前文件夹(也可以省略)
    app.use(express.static('./dist'))
    
    app.listen(4005)
    

小结

  1. 项目分哪2个环境?

    答案
    • 线上和线下2个环境
    • 线上也叫"生产环境"/"部署", 英文"production"
    • 线下也叫"开发环境"/写代码, 英文"development"

今日总结

最少要学会这些, 支撑后面

  • yarn命令的使用

    // 拿到新项目, 缺少node_modules, 执行命令下包, 根据package.json记录的哪些包下载
    yarn
    
    // 安装某个包
    yarn add 包名
    
  • 说出webpack的作用, 加载器和插件的作用即可

    webpack在node环境下使用

    可以对任何模块, 分析, 压缩, 打包

    加载器给webpack带来识别功能类型文件的能力

    插件是给webpack带来更多的功能

  • 前端为何能用yarn下的包?

    因为webpack翻译后输出到js, 再插入到html中运行

  • babel是什么?

    babel是一个插件, 也是编译器

    可以把你的高版本js代码, 转换成低版本的js代码

  • 以后开发时, 使用webpack还是webpack-dev-server? 为什么?

    使用webpack-dev-server启动的服务器, 只打包更新的代码, 还提供地址让浏览器访问打包后代码

面试题

1、什么是webpack(必会)

  1. webpack是一个javascript的静态模块打包工具
  2. webpack里一切文件皆模块,通过loader转换文件,通过plugin注入钩子
  3. 最后输出由多个模块组合成的文件,webpack专注构建模块化项目

2、webpack的优点是什么?(必会)

  1. 专注于处理模块化的项目,能做到开箱即用,一步到位
  2. 通过plugin扩展,完整好用又不失灵活
  3. 通过loaders扩展, 可以让webpack把所有类型的文件都解析打包
  4. 社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展

3、webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全(必会)

​ webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

  1. 初始化参数:从配置文件读取与合并参数,得出最终的参数
  2. 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,开始执行编译
  3. 确定入口:根据配置中的 entry 找出所有的入口文件
  4. 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
  5. 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系
  6. 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会
  7. 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。

在以上过程中,webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 webpack 提供的 API 改变 webpack 的运行结果

4、说一下 webpack 的热更新原理(必会)

​ webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。

​ HMR的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS(webpack-dev-server) 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。

​ 后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。

5、webpack与grunt、gulp的不同?(必会)

1) 三者之间的区别

​ 三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。

​ grunt和gulp是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。

​ webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。

2) 从构建思路来说

​ gulp和grunt需要开发者将整个前端构建过程拆分成多个Task,并合理控制所有Task的调用关系 webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工

3) 对于知识背景来说

​ gulp更像后端开发者的思路,需要对于整个流程了如指掌 webpack更倾向于前端开发者的思路

6、有哪些常见的Loader?他们是解决什么问题的?(必会)

1、 file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件

2、 url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去

3、 source-map-loader:加载额外的 Source Map 文件,以方便断点调试

4、 image-loader:加载并且压缩图片文件

5、 babel-loader:把 ES6 转换成 ES5

6、 css-loader:加载 CSS,支持模块化、压缩、文件导入等特性

7、 style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。

8、 eslint-loader:通过 ESLint 检查 JavaScript 代码

7、Loader和Plugin的不同?(必会)

1) 不同的作用

​ loader直译为"加载器"。webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。

​ Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果。

2) 不同的用法

​ Loader在module.rules中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)

​ Plugin在plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。

额外扩展

这部分给基础超强的同学, 自行学习扩展

webpack4-图片打包

如用的是webpack4版本, 尝试这里配置

当然webpack5是向下兼容的, 也可以使用

url-loader文档

file-loader文档

  1. 下载依赖包

    yarn add url-loader file-loader -D
    
  2. webpack.config.js 配置

    {
      test: /\.(png|jpg|gif|jpeg)$/i,
      use: [
        {
          loader: 'url-loader', // 匹配文件, 尝试转base64字符串打包到js中
          options: {  // 配置limit, 超过8k, 不转base64字符串, 自动用file-loader复制文件到dist下
            limit: 8 * 1024,
          }
        }
      ]
    }
    

webpack4-字体图标

webpack.config.js配置

{ // 处理字体图标的解析
    test: /\.(eot|svg|ttf|woff|woff2)$/,
        use: [
            {
                loader: 'url-loader',
                options: {
                    limit: 2 * 1024,
                    // 配置输出的文件名
                    name: '[name].[ext]',
                    // 配置输出的文件目录
                    outputPath: "fonts/"
                }
            }
        ]
}

source map的说明

目标: source map概念, 用于在浏览器调试错误使用, 记录代码打包前原始位置

  1. 准备: src/main.js产生一个未定义变量的报错, 启动webpack服务器
console.log(abc); // 不要声明abc变量
  1. 问题: 看浏览器-控制台报错信息, 但是==发现看不出哪行代码报错了==

    原因: webpack对代码, 压缩, 混淆, 减小文件的体积(提高文件的加载效率)

    • 变量被替换成没有任何语义的名称
    • 空行和注释被剔除, 压缩到一行

image-20201213134820689.png

解决方案: 启用source map

开发环境

  1. webpack.config.js - 配置

    module.exports = {
      // ...其他配置
      mode: 'development', // 开发模式 - webpack内部不会使用内置优化, 不压缩代码(使用'production'上线生产模式, 会压缩代码)
      devtool: 'cheap-module-source-map', // cheap-module-source-map 开发模式下使用, 保证运行时的行数 和 源代码行数 一致  (默认不写是eval模式)
    }
    
  2. 重新启动开发服务器/打包, 观察是否有错误代码打包前的位置信息了

生产环境

  1. 不显示源码, 但是可以看到哪行报错

    devtool: 'nosources-source-map'
    

image-20201213135929321.png

  1. 显示源码

    devtool: 'source-map'
    

image-20201213140218039.png

devtool值说明

规则字符串列表:webpack.docschina.org/configurati…

格式: [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map (了解即可)

规则值速度位置说明
false建立:最快
重建:最快
不开启sourcemap(规则值写错也是这个)
inline建立:最慢
重建:最慢
内嵌报错信息, 以及源码和源码位置信息
hidden建立:最慢
重建:最慢
独立map文件报错信息, 没有源码和源码位置信息
eval建立:快
重建:最快
内嵌报错信息, 以及源码
(mode为development时使用这个值)
cheap建立:固定
重建:慢
独立map文件报错信息, 以及源码和源码的行数(没有列)
module建立:慢
重建:快速
与别的一起用是否为loaders加载器生成source map
[xxx-...]source-map建立:最慢
重建:最慢
独立map文件报错信息, 以及源码和源码位置信息
nosource建立:最慢
重建:最慢
独立map文件报错信息, 不显示源码

总结: 名字如何组合, 还要看上面文档, 不记录 快于 内嵌 快于 独立文件

devtool常用组合

image-20210227130825907.png