Webpack详解

2023-10-30

零、文章目录

Webpack详解

1、webpack基本概念

(1)webpack是什么

(2)webpack为何学

  • 开发完的网站,文件很多,体积很大。为了让网页加载的更快,需要缩小网站代码的体积。

image-20230624172520765

(3)webpack的作用是什么

  • webpack是一个静态模块打包工具,作用是分析、压缩、打包代码。
    • 支持所有类型文件的打包
    • 支持less/sass => css
    • 支持ES6/7/8 => ES5
    • 压缩代码, 提高加载速度

image-20230624173324488

2、webpack使用步骤

(1)webpack安装

  • webpack本质是node环境下的包,所以用npm直接安装即可。
  • node安装之后自动安装了npm,node相关知识请参考node初识,npm相关知识请参考npm与包
  • webpack不同的版本是有差异的,不同的项目不建议使用相同版本,不建议安装全局版本,建议安装项目版本。
  • webpack准备工作如下:
    1. 先创建项目文件夹webpack-study
    2. 打开cmd,切换当前路径到webpack-study
    3. 初始化环境命令npm init -y直接生成配置文件package.json
    4. 安装webpack包到当前项目npm install webpack webpack-cli -D
    5. 在配置文件package.json节点scripts添加build配置
    6. 运行打包命令npm run build就会执行webpack打包

image-20230625135715255

(2)webpack使用

  • **需求:**打包2个js文件 -> 打包成1个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. 运行打包命令npm run build
  • 效果
  1. 在src并列处, 生成dist目录和main.js文件

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

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

image-20230625152922151

  1. 最终目录结构

image-20230625154526380

(3)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. 运行打包命令npm run build
  • 效果
  1. 自动覆盖原dist中的main.js,生成的内容压缩极致
(()=>{"use strict";console.log(7),console.log([5,6,9,10].reduce(((o,e)=>o+e),0))})();
  1. 打包关系图

image-20230625155146992

3、webpack的配置

(1)入口和出口

  1. 创建项目文件夹webpack-config
  2. webpack-study案例的文件复制一份进来
  3. 在项目根目录新建webpack.config.js文件 (默认配置文件名)
const path = require("path")

module.exports = {
    entry: "./src/main.js", // 入口:可以是相对路径
    output: {
        path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
        filename: "bundle.js" // 出口"文件"名
    }
}
  1. 重命名文件src/index.jssrc/main.js

  2. 运行打包命令npm run build

  • **效果:**在dist目录生成bundle.js文件

(2)打包流程

  • 运行yarn build/npm run build发生了什么

image-20230625163804335

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

image-20230625163837258

(3)案例-隔行变色

  • **概要:**引入jquery,实现隔行变色

  • 步骤:

    1. 创建项目文件夹webpack-jquery

    2. webpack-config案例的文件复制一份进来

    3. 安装jquerynpm install jquery

    4. 新建前端首页public/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>
    </head>
    <body>
    
    <div id="app">
      <!-- ul>li{我是第$个li}*10 -->
      <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>
      </ul>
    </div>
    
    </body>
    </html>
    
    1. 修改src/main.js文件
    import $ from 'jquery'
    
    $(function() {
      $('#app li:nth-child(odd)').css('color', 'red')
      $('#app li:nth-child(even)').css('color', 'green')
    })
    
    1. 运行打包命令npm run build

    2. public/index.html文件手动复制到dist/index.html,在dist/index.html手动引入打包后的bundle.js

    <script src="../dist/bundle.js"></script>
    
  • 效果:

    • 最终运行效果

    image-20230626100743166

    • 打包关系图

    image-20230626103639297

(4)打包html文件

  • 概要:

  • 步骤:

    1. 创建项目文件夹webpack-htmlplugin
    2. webpack-jquery案例的文件复制一份进来
    3. 安装html-webpack-plugin
    npm install html-webpack-plugin -D
    
    1. 修改webpack.config.js配置文件
    const path = require("path")
    
    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        entry: "./src/main.js", // 入口:可以是相对路径
        output: {
            path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
            filename: "bundle.js" // 出口"文件"名
        },
        plugins: [
            // html 插件
            new HtmlWebpackPlugin({
                // 指定要复制的HTML文件位置
                // 可以使用相对路径
                // 作用: 每次打包时自动从该目录下复制HTML到出口, 同时自动引入js文件, 并添加defer属性
                // defer: 等页面资源加载完成后加载js文件
                template: './public/index.html'
            })
        ]
    }
    
    1. 执行打包命令npm run build
  • **效果:**和上面隔行变色手动复制一样

(5)处理CSS文件

  • 概要:

  • 步骤:

    1. 创建项目文件夹webpack-css
    2. webpack-htmlplugin案例的文件复制一份进来
    3. 安装css-loader,style-loader
    npm install css-loader style-loader -D
    
    1. 修改webpack.config.js配置文件
    const path = require("path")
    
    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        entry: "./src/main.js", // 入口:可以是相对路径
        output: {
            path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
            filename: "bundle.js" // 出口"文件"名
        },
        plugins: [
            // html 插件
            new HtmlWebpackPlugin({
                // 指定要复制的HTML文件位置
                // 可以使用相对路径
                // 作用: 每次打包时自动从该目录下复制HTML到出口, 同时自动引入js文件, 并添加defer属性
                // defer: 等页面资源加载完成后加载js文件
                template: './public/index.html'
            })
        ],
        module: { // 如何处理项目中不同模块文件
            rules: [ // 规则
                {
                    // . 表示除换行符以外的任意字符
                    // \ 转义符
                    test: /\.css$/, // 匹配所有的css文件
                    // loader的加载顺序是从右往左
                    // 先用css-loader让webpack能够识别css文件并打包
                    // 再用style-loader将样式插入到dom中
                    use: ["style-loader", "css-loader"]
                }
            ]
        }
    }
    
    1. 新建src/css/index.css,填上样式去除li圆点样式
    li{
        list-style: none;
    }
    
    1. main.js引入index.css,一定要引入到入口才会被webpack打包
    import "./css/index.css"
    
    1. 执行打包命令npm run build
  • **效果:**实现去除li圆点样式

(6)处理Less文件

  • 概要:

  • 步骤:

    1. 创建项目文件夹webpack-less
    2. webpack-css案例的文件复制一份进来
    3. 安装less-loader,less
    npm install less less-loader -D
    
    1. 修改webpack.config.js配置文件
    const path = require("path")
    
    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        entry: "./src/main.js", // 入口:可以是相对路径
        output: {
            path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
            filename: "bundle.js" // 出口"文件"名
        },
        plugins: [
            // html 插件
            new HtmlWebpackPlugin({
                // 指定要复制的HTML文件位置
                // 可以使用相对路径
                // 作用: 每次打包时自动从该目录下复制HTML到出口, 同时自动引入js文件, 并添加defer属性
                // defer: 等页面资源加载完成后加载js文件
                template: './public/index.html'
            })
        ],
        module: { // 如何处理项目中不同模块文件
            rules: [ // 规则
                {
                    // . 表示除换行符以外的任意字符
                    // \ 转义符
                    test: /\.css$/, // 匹配所有的css文件
                    // loader的加载顺序是从右往左
                    // 先用css-loader让webpack能够识别css文件并打包
                    // 再用style-loader将样式插入到dom中
                    use: ["style-loader", "css-loader"]
                },
                {
                    test: /\.less$/, // 匹配.less结尾文件
                    // 使用less-loader让webpack能够识别less文件 
                    // 内置还会用less模块, 翻译less代码成css代码
                    // 然后再打包CSS文件,并将样式插入到dom中
                    use: ["style-loader", "css-loader", 'less-loader']
                }
            ]
        }
    }
    
    1. 新建src/less/index.less,设置li字体大小24px
    @size:24px;
    
    ul, li{
        font-size: @size
    }
    
    1. 引入到main.js
    import "./less/index.less"
    
    1. 执行打包命令npm run build
  • **效果:**字体设置成需求大小

(7)处理图片文件

  • 概要:

  • 步骤:

    1. 创建项目文件夹webpack-pic

    2. webpack-less案例的文件复制一份进来

    3. src文件夹下创建assets文件夹,放入两张图片

    4. css/less/index.less设置body背景图片

body{
    background: url(../assets/logo_small.png) no-repeat center;
}

​ 5. 在src/main.js把图片添加body上显示

// 引入图片-使用
import imgUrl from './assets/1.gif'
const theImg = document.createElement("img")
theImg.src = imgUrl
document.body.appendChild(theImg)

​ 6. 修改webpack.config.js配置文件

const path = require("path")

// 引入自动生成 html 的插件
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: "./src/main.js", // 入口:可以是相对路径
    output: {
        path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
        filename: "bundle.js" // 出口"文件"名
    },
    plugins: [
        // html 插件
        new HtmlWebpackPlugin({
            // 指定要复制的HTML文件位置
            // 可以使用相对路径
            // 作用: 每次打包时自动从该目录下复制HTML到出口, 同时自动引入js文件, 并添加defer属性
            // defer: 等页面资源加载完成后加载js文件
            template: './public/index.html'
        })
    ],
    module: { // 如何处理项目中不同模块文件
        rules: [ // 规则
            {
                // . 表示除换行符以外的任意字符
                // \ 转义符
                test: /\.css$/, // 匹配所有的css文件
                // loader的加载顺序是从右往左
                // 先用css-loader让webpack能够识别css文件并打包
                // 再用style-loader将样式插入到dom中
                use: ["style-loader", "css-loader"]
            },
            {
                test: /\.less$/, // 匹配.less结尾文件
                // 使用less-loader让webpack能够识别less文件 
                // 内置还会用less模块, 翻译less代码成css代码
                // 然后再打包CSS文件,并将样式插入到dom中
                use: ["style-loader", "css-loader", 'less-loader']
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/i, // 匹配图片文件
                // asset
                // 大于 8KB 不转 base64 直接复制
                // 小于 8KB 转成 base64 插入到 js 中
                type: 'asset',
                // generator 就是定义打包输出的规则
                generator: {
                    // [] 的内容当做内置的变量
                    // [name] 表示原先的文件名
                    // [hash:6] 表示使用哈希字符串, 长度6
                    // [ext] 表示后缀名 带 .
                    filename: 'imgs/[name].[hash:4][ext]'
                }
            }
        ]
    }
}

​ 7. 执行打包命令npm run build

  • 效果
    • 图片正确显示
    • 类型设置type
      • 大于 8KB 不转 base64 直接复制
      • 小于 8KB 转成 base64 插入到 js 中
    • 转base64
      • 优点:减少网络请求
      • 缺点:增加30%的体积

(8)处理字体文件

  • **概要:**配置webpack,打包字体文件

  • 步骤:

    1. 创建项目文件夹webpack-font

    2. webpack-pic案例的文件复制一份进来

    3. assets文件夹下创建fonts文件夹,放入字体文件

    4. main.js引入iconfont.css

    // 引入字体图标文件
    import './assets/fonts/iconfont.css'
    
    5. 在`public/index.html`使用字体图标样式
    
    <i class="iconfont icon-weixin"></i>
    
    1. 修改webpack.config.js配置文件
    const path = require("path")
    
    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        entry: "./src/main.js", // 入口:可以是相对路径
        output: {
            path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
            filename: "bundle.js" // 出口"文件"名
        },
        plugins: [
            // html 插件
            new HtmlWebpackPlugin({
                // 指定要复制的HTML文件位置
                // 可以使用相对路径
                // 作用: 每次打包时自动从该目录下复制HTML到出口, 同时自动引入js文件, 并添加defer属性
                // defer: 等页面资源加载完成后加载js文件
                template: './public/index.html'
            })
        ],
        module: { // 如何处理项目中不同模块文件
            rules: [ // 规则
                {
                    // . 表示除换行符以外的任意字符
                    // \ 转义符
                    test: /\.css$/, // 匹配所有的css文件
                    // loader的加载顺序是从右往左
                    // 先用css-loader让webpack能够识别css文件并打包
                    // 再用style-loader将样式插入到dom中
                    use: ["style-loader", "css-loader"]
                },
                {
                    test: /\.less$/, // 匹配.less结尾文件
                    // 使用less-loader让webpack能够识别less文件 
                    // 内置还会用less模块, 翻译less代码成css代码
                    // 然后再打包CSS文件,并将样式插入到dom中
                    use: ["style-loader", "css-loader", 'less-loader']
                },
                {
                    test: /\.(png|jpg|gif|jpeg)$/i, // 匹配图片文件
                    // asset
                    // 大于 8KB 不转 base64 直接复制
                    // 小于 8KB 转成 base64 插入到 js 中
                    type: 'asset',
                    // generator 就是定义打包输出的规则
                    generator: {
                        // [] 的内容当做内置的变量
                        // [name] 表示原先的文件名
                        // [hash:6] 表示使用哈希字符串, 长度6
                        // [ext] 表示后缀名 带 .
                        filename: 'imgs/[name].[hash:4][ext]'
                    }
                },
                {
                    test: /\.(eot|svg|ttf|woff|woff2)$/i, // 匹配字体文件
                    // asset/resource:不做base64转换, 无论多大多小都直接复制到出口
                    type: 'asset/resource',
                    generator: {
                        // [] 的内容当做内置的变量
                        // [name] 表示原先的文件名
                        // [hash:6] 表示使用哈希字符串, 长度6
                        // [ext] 表示后缀名 带 .
                        filename: 'fonts/[name].[hash:4][ext]'
                    }
                }
            ]
        }
    }
    

    ​ 7. 执行打包命令npm run build

  • 效果:

    • 正确显示字体
    • asset/resource:不做base64转换, 无论多大多小都直接复制到出口

(9)处理高版本js语法

  • 概要:

  • 步骤:

    1. 创建项目文件夹webpack-es6
    2. webpack-font案例的文件复制一份进来
    3. src/main.js编写箭头函数
    const fn = () => { // 高级语法
      console.log("你好babel");
    }
    console.log(fn) // 一定打印函数, 才会被webpack把"函数体"打包起来
    
    1. 安装包babel-loader,@babel/core,@babel/preset-env
    npm install babel-loader @babel/core @babel/preset-env -D
    
    1. 修改webpack.config.js配置文件
    const path = require("path")
    
    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        entry: "./src/main.js", // 入口:可以是相对路径
        output: {
            path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
            filename: "bundle.js" // 出口"文件"名
        },
        plugins: [
            // html 插件
            new HtmlWebpackPlugin({
                // 指定要复制的HTML文件位置
                // 可以使用相对路径
                // 作用: 每次打包时自动从该目录下复制HTML到出口, 同时自动引入js文件, 并添加defer属性
                // defer: 等页面资源加载完成后加载js文件
                template: './public/index.html'
            })
        ],
        module: { // 如何处理项目中不同模块文件
            rules: [ // 规则
                {
                    // . 表示除换行符以外的任意字符
                    // \ 转义符
                    test: /\.css$/, // 匹配所有的css文件
                    // loader的加载顺序是从右往左
                    // 先用css-loader让webpack能够识别css文件并打包
                    // 再用style-loader将样式插入到dom中
                    use: ["style-loader", "css-loader"]
                },
                {
                    test: /\.less$/, // 匹配.less结尾文件
                    // 使用less-loader让webpack能够识别less文件 
                    // 内置还会用less模块, 翻译less代码成css代码
                    // 然后再打包CSS文件,并将样式插入到dom中
                    use: ["style-loader", "css-loader", 'less-loader']
                },
                {
                    test: /\.(png|jpg|gif|jpeg)$/i, // 匹配图片文件
                    // asset
                    // 大于 8KB 不转 base64 直接复制
                    // 小于 8KB 转成 base64 插入到 js 中
                    type: 'asset',
                    // generator 就是定义打包输出的规则
                    generator: {
                        // [] 的内容当做内置的变量
                        // [name] 表示原先的文件名
                        // [hash:6] 表示使用哈希字符串, 长度6
                        // [ext] 表示后缀名 带 .
                        filename: 'imgs/[name].[hash:4][ext]'
                    }
                },
                {
                    test: /\.(eot|svg|ttf|woff|woff2)$/i, // 匹配字体文件
                    // asset/resource:不做base64转换, 无论多大多小都直接复制到出口
                    type: 'asset/resource',
                    generator: {
                        // [] 的内容当做内置的变量
                        // [name] 表示原先的文件名
                        // [hash:6] 表示使用哈希字符串, 长度6
                        // [ext] 表示后缀名 带 .
                        filename: 'fonts/[name].[hash:4][ext]'
                    }
                },
                {
                    // 强烈不建议大家手写, 容易出错
                    test: /\.m?js$/, // 匹配js结尾文件
                    exclude: /(node_modules|bower_components)/, // 不转换这2个文件夹里的js
                    use: {
                        loader: 'babel-loader', // 使用加载器处理
                        options: {
                            presets: ['@babel/preset-env'] // 预设转码规则(用bable开发环境)
                        }
                    }
                }
            ]
        }
    }
    
    1. 执行打包命令npm run build
  • **效果:**打包后观察dist/bundle.js文件, 自动变成普通函数

4、webpack开发服务器

(1)问题

  • 问题: 每次修改代码, 重新打包, 非常费时 (30s - 60s)
  • 原因:
    1. 再次找到入口并开始构建依赖关系图
    2. 磁盘读取对应文件到内存
    3. webpack用配置好的loader和plugin翻译和处理文件
    4. 再将处理后内容, 写入到磁盘出口位置
    5. 代码再变化,重复1~4步

(2)解决方案

  • 概要:

    • 下载webpack-dev-server,启动一个开发服务器, 用于快速开发应用程序
    • webpack-dev-server文档:https://webpack.docschina.org/configuration/dev-server/
      • 构建入口和所有模块依赖关系图
      • 磁盘读取对应的文件到内存, 才能加载
      • 用对应的 loader 进行处理和翻译
      • 将处理完的内容, 输出到内存里而非磁盘上
      • 以后代码变化, 自动更新打包变化的代码, 显示到浏览器上
  • 步骤:

    1. 创建项目文件夹webpack-server
    2. webpack-es6案例的文件复制一份进来
    3. 安装包webpack-dev-server
    npm install webpack-dev-server -D
    
    1. 修改package.json配置文件scripts节点
    scripts: {
    	"build": "webpack",
    	"serve": "webpack serve"
    }
    
    1. 修改webpack.config.js配置文件
    const path = require("path")
    
    // 引入自动生成 html 的插件
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
        entry: "./src/main.js", // 入口:可以是相对路径
        output: {
            path: path.join(__dirname, "dist"), // 出口:必须是绝对路径
            filename: "bundle.js" // 出口"文件"名
        },
        plugins: [
            // html 插件
            new HtmlWebpackPlugin({
                // 指定要复制的HTML文件位置
                // 可以使用相对路径
                // 作用: 每次打包时自动从该目录下复制HTML到出口, 同时自动引入js文件, 并添加defer属性
                // defer: 等页面资源加载完成后加载js文件
                template: './public/index.html'
            })
        ],
        module: { // 如何处理项目中不同模块文件
            rules: [ // 规则
                {
                    // . 表示除换行符以外的任意字符
                    // \ 转义符
                    test: /\.css$/, // 匹配所有的css文件
                    // loader的加载顺序是从右往左
                    // 先用css-loader让webpack能够识别css文件并打包
                    // 再用style-loader将样式插入到dom中
                    use: ["style-loader", "css-loader"]
                },
                {
                    test: /\.less$/, // 匹配.less结尾文件
                    // 使用less-loader让webpack能够识别less文件 
                    // 内置还会用less模块, 翻译less代码成css代码
                    // 然后再打包CSS文件,并将样式插入到dom中
                    use: ["style-loader", "css-loader", 'less-loader']
                },
                {
                    test: /\.(png|jpg|gif|jpeg)$/i, // 匹配图片文件
                    // asset
                    // 大于 8KB 不转 base64 直接复制
                    // 小于 8KB 转成 base64 插入到 js 中
                    type: 'asset',
                    // generator 就是定义打包输出的规则
                    generator: {
                        // [] 的内容当做内置的变量
                        // [name] 表示原先的文件名
                        // [hash:6] 表示使用哈希字符串, 长度6
                        // [ext] 表示后缀名 带 .
                        filename: 'imgs/[name].[hash:4][ext]'
                    }
                },
                {
                    test: /\.(eot|svg|ttf|woff|woff2)$/i, // 匹配字体文件
                    // asset/resource:不做base64转换, 无论多大多小都直接复制到出口
                    type: 'asset/resource',
                    generator: {
                        // [] 的内容当做内置的变量
                        // [name] 表示原先的文件名
                        // [hash:6] 表示使用哈希字符串, 长度6
                        // [ext] 表示后缀名 带 .
                        filename: 'fonts/[name].[hash:4][ext]'
                    }
                },
                {
                    // 强烈不建议大家手写, 容易出错
                    test: /\.m?js$/, // 匹配js结尾文件
                    exclude: /(node_modules|bower_components)/, // 不转换这2个文件夹里的js
                    use: {
                        loader: 'babel-loader', // 使用加载器处理
                        options: {
                            presets: ['@babel/preset-env'] // 预设转码规则(用bable开发环境)
                        }
                    }
                }
            ]
        },
        //webpackserver配置
        devServer: {
            port: 3000, // 端口号
            open: true // 自动打开浏览器
        }
    }
    
    1. 运行命令npm run serve启动webpack开发服务器
  • **效果:**修改src/public文件夹下的代码,自动打包更新到浏览器效果

(3)方案对比

  • webpack:
    1. 再次找到入口并开始构建依赖关系图
    2. 磁盘读取对应文件到内存
    3. webpack用配置好的loader和plugin翻译和处理文件
    4. 再将处理后内容, 写入到磁盘出口位置
    5. 代码再变化,重复1~4步
  • webpack-dev-server:
    1. 构建, 入口和依赖关系图
    2. 磁盘读取对应文件到内存
    3. webpack用配置好的loader和plugin翻译和处理文件
    4. 再将处理后内容, 放到内存
    5. 代码再变化, 只重新打包变化的代码, 自动更新到页面

5、项目打包发布

(1)环境

  • 开发环境(development):开发的时候随时修改调试
  • 生产环境(production):开发完成之后,打包到dist,发布到线上

(2)版本发布

  • 开发完成,运行命令npm run build,生成打包到dist文件夹
  • dist文件夹的静态资源发布到生产环境目录

(3)部署

  • 使用node+express发布静态网站
const express = require('express')
const app = express()

app.use(express.static('./dist'))

app.listen(4005)

6、扩展功能

(1)webpack4-图片打包

  • 概要

  • 步骤

    1. 安装包url-loader,file-loader
    npm install url-loader file-loader -D
    
    1. 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,
          }
        }
      ]
    }
    

(2)webpack4-字体图标

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

(3)devtool:source map

  • 概要:

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

    • 问题: 看浏览器控制台报错信息,发现看不出哪行代码报错了

      • 原因: 在生产环境下,webpack对代码压缩, 混淆, 减小文件的体积
        • 变量被替换成没有任何语义的名称
        • 空行和注释被剔除, 压缩到一行
    • 解决方案: 启用source map

  • 步骤:

    1. webpack.config.js - 配置

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

  • devtool值说明

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

image-20230627172336399

7、常见面试题

(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的不同?(必会)

  • 三者之间的区别

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

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

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

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

  • **对于知识背景来说:**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的不同?(必会)

  • 不同的作用

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

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

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

      • Plugin在plugins中单独配置。 类型为数组,每一项是一个plugin的实例,参数都通过构造函数传入。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Webpack详解 的相关文章

随机推荐

  • 前端基础知识之SVG&Canvas之间的区别与简单应用

    tip canvas 常用API fillRect x y width height 实心矩形 strokeRect x y width height 空心矩形 fillText Hello world 200 200 实心文字 strok
  • 8. R语言绘图系统介绍、高级绘图与低级绘图、【绘图参数】、绘图函数包

    b站课程视频链接 https www bilibili com video BV19x411X7C6 p 1 腾讯课堂 最新 但是要花钱 我花99 元买了 感觉讲的没问题 就是知识点结构有点乱 有点废话 https ke qq com co
  • HTML 个人简历源码

  • 使用HAL库开发STM32:系统时间基础及进阶使用

    文章目录 目的 基础使用 进阶使用 总结 目的 HAL库默认提供了系统时间 系统时间默认情况下由SysTick定时器计数产生 系统时间一方面用于HAL库自身调用 另一方面用户也可以使用 为开发带来便利 本文提到的相关使用主要应用于未使用OS
  • 5G赋能智慧城市白皮书 附下载地址

    随着经济社会的快速发展和加速转型 传统城市管理模式的局限性日益显现 随着全球城市化 进程的加快 为了应对人口 资源 环境等对城市发展的挑战 全球各国都以 智慧城市 建 设作为全新的城市发展理念和实践路径 而传统智慧城市建设中 由于细分智慧应
  • 应用层——电子邮件(SMTP、POP3、IMAP)

    目录 1 电子邮件系统及组成结构 1 1 电子邮件 1 2 电子邮件系统的组件 2 SMTP 邮件发送协议 2 1 SMTP的特征 2 2 SMTP的基本操作 2 3 SMTP协议的基本流程 2 4 SMTP交互与应答 2 5 SMTP与H
  • 预测性维护

    1 预测性维护 1 1 介绍 预见性维护 PdM 承诺在工厂车间达到前所未有的效率和安全水平 目前已建立的系统和流程的最佳实践 机器停机是生产线上最大的挑战之一 目前的MRO 维护 维修 操作 方法远未达到最佳生产水平 通过预测性维护 一旦
  • kettle对接hive

    kettle没有自带hive的驱动 如果在界面上直接选Hadoop Hive 2 3会报找不到驱动的错误 按照网上的解决方案修改了plugins文件夹里的配置文件后仍然无法解决 还是需要把驱动jar放入kettle里才可以 docker c
  • C++:多线程的正确打开姿势

    目的 本例简介c 11中thread库如何创建与停止线程 实现 如下的实例中 通过ThreadWrapper start 方法启动线程 通过ThreadWrapper stop 方法停止线程 线程的主体函数为Thread run 方法 in
  • Servlet 基础知识及操作

    一 什么是servlet Servlet Server Applet 是Java Servlet的简称 称为小服务程序或服务连接器 用Java编写的服务器端程序 具有独立于平台和协议的特性 主要功能在于交互式地浏览和生成数据 生成动态Web
  • [POI2008]CLO-Toll

    题目链接 本题有个小点需要注意 如果说它是多个相互不连通的图 也有可能形成一个可行解 多个环嘛 然后剩下的 就是dfs去跑 如果跑出了返祖边 那么这个返祖边抵达的点 将改变原来的方向 剩下的就都是正方向 dfs直接跑就是了 include
  • 【回溯法】n皇后问题并输出每种解的情况 C语言版

    问题描述 在n n的方格棋盘上 放置n个皇后 要求 个皇后两两不在一行 不在一列 不在同一对角线上 PS 行不用检测 因为皇后本身就是一行一行往下放的 并且一行只能放一个 所以当放好一个皇后后 只需检测列及对角线的位置有无皇后 如下图这些位
  • 报告论文:手写数字识别

    手写数字识别 简单手写数字识别系统 我们对VC比较熟悉 采用VC开发 数字的类别只有十种 笔划又简单 其识别问题似乎不是很困难 但事实上 一些测试结果表明 数字的正确识别率并不如印刷体汉字识别正确率高 甚至也不如联机手写体汉字识别率高 而只
  • 服务器的线路有很多

    服务器的线路有很多 大致的分为 CN2 CIA CDIA GIA等 首先简单介绍一下什么是IPLC专线 IPLC专线是国际私用出租线路 本质就是点对点内网 网络的入口在国内 所以不会受 国际链路影响 也不用走国家防火墙 IP地址可用率高 不
  • 怎么在外部类外访问内部类

    在外部类外访问内部类 Wai Nei wn new Wai new Nei 上式相当于 Wai w new Wai Wai Nei wn w new Nei package a class Wai class Nei int i 5 int
  • 【自然语言处理】利用TextRank算法提取关键词

    利用TextRank提取关键词 TextRank 是一种基于 PageRank 的算法 常用于关键词提取和文本摘要 在本文中 我将通过一个关键字提取示例帮助您了解 TextRank 如何工作 并展示 Python 的实现 使用 TextRa
  • MySQL按逗号拆分列为多行

    图一 图二 按逗号拆分列为多行 把 图一 的展示效果转换成 图二 的展示效果 1 创建用户表 sys user CREATE TABLE sys user id BIGINT NOT NULL auto increment COMMENT
  • 工厂方法模式与抽象工厂模式

    工厂方法模式与抽象工厂模式 一 工厂方法模式 Factory Method 解决的问题 案例 实现步骤 代码示例 比较冗余 只是看设计模式的思想 根据案例分析工厂方法模式 JDK源码中的工厂方法模式 二 抽象工厂模式 Abstract Fa
  • (附源码)vue3.0+.NET6实现聊天室(实时聊天SignalR)

    参考文章 搭建文章 gitte源码 在线体验 可以注册两个号来测试 演示图 一 整体介绍 介绍SignalR一种通讯模型Hub 中心模型 或者叫集线器模型 调用这个模型写好的方法 去发送消息 内容有 Hub模型的方法介绍 服务器端代码介绍
  • Webpack详解

    零 文章目录 Webpack详解 1 webpack基本概念 1 webpack是什么 静态模块打包工具 官网 https webpack docschina org 官网文档 https webpack docschina org con