面试屡屡被问到 webpack:痛定思痛

215 阅读4分钟

一、问题引入

  1. 场景:开发完的网站,文件很多,体积很大。
  2. 问题:如何缩小网站代码的体积呢?

二、webpack 基础

  1. webpack 是什么? 静态模块打包工具
  2. 为什么使用 webpack? (1)减少文件数量,缩减代码体积 (2)提高网页打开速度
  3. webpack 的作用是什么? 分析、压缩、打包代码

三、webpack 使用步骤

1.webpack 使用前的环境准备

第一步:找一块风水宝地,新建文件夹 my-webpack

第二步:初始化包环境,得到 package.json 文件

法1:手动初始化(一路回车,可以全部默认)

yarn init 或 npm init 

法2:自动初始化(一键生成 package.json)

yarn init -y 或 npm init -y

image.png

第三步:安装依赖包 webpack 和 webpack-cli

yarn add webpack@5.31.2 webpack-cli@4.6.0 -D

image.png

第四步:配置 scripts 自定义命令,为打包做准备 package.json

 "scripts": {
    "build":"webpack"
  }

image.png

2.webpack 的基础使用

(1)需求:把多个 js 文件,打包成一个 js 文件

(2)分析:

  • 新建src下的文件夹 tools
  • tools/add.js – 定义求和函数并按需导出
  • tools/decrease.js – 定义求差函数并默认导出
  • tools/none.js – 定义 console.log('只导出功能')
  • src/index.js – 引入add模块和decrease模块并使用函数输出结果
  • 执行 yarn build 自定义命令, 进行打包 (确保终端路径在src的父级文件夹)
  • 打包后默认生成 distmain.js , 观察其中代码

image.png

add.js

// 按需导出 add
export const add=(a,b)=>{
   return a+b
}

decrease.js

// 默认导出 decrease
export default decrease=(m,n)=>{
    return m-n
}

none.js

console.log('只导出功能123')

index.js

// ◆按需导入 add 函数并调用
import { add } from './tools/add'
console.log(add(2, 8))

// ◆默认导入 decrease 函数并调用
import decrease from './tools/decrease'
decrease(8, 4)

// ◆只导入功能,不导入模块
import './tools/none'

终端执行 yarn build 命令:生成 dist 和 main.js

image.png

dist/main.js:看打包结果(说实话,我也看大不懂的样子,因为三个一起导入打包的。你可以一个个导入打包再看)

(()=>{var o={566:()=>{console.log("只导出功能123")}},r={};function e(s){var t=r[s];if(void 0!==t)return t.exports;var n=r[s]={exports:{}};return o[s](n,n.exports,e),n.exports}(()=>{"use strict";const o=decrease=(o,r)=>o-r;e(566),console.log(10),o(8,4)})()})();

image.png

四、webpack 的配置

(1)问题引入:

由上可见,webpack 打包时,默认的入口文件是 src/index.js、出口文件是 dist/main.js那我们如何更改默认的入口和出口呢?

(2)修改入口和出口

  1. 新建 webpack.config.js (与 src 平级)

image.png

  1. webpack.config.js填入配置 webpack 是基于 node 的工具,所以这里的代码都要遵守 CoommonJS 规范。

所谓的配置文件就是对外暴露一个对象,对象中写配置信息,具体要写什么配置可以查 官方文档

const path =require('path')
module.exports={
    // 1.入口,可以是相对路径
    entry:'./src/main.js',
    // 2.出口,必须是绝对路径
    output:{
        path:path.resolve(__dirname,'dist'),
        filename:'bundle.js'
    }
}
  1. 修改入口文件名 为 main.js

image.png 4. yarn build 一下打包观察效果

image.png

(3)yarn build 之后发生了什么

image.png

五、其他配置

webpack.config.js

// 引入内置路径
const path = require('path')
// 引入自动生成html插件
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // 模式: 取值范围只有两个单词: production / development
  // webpack 把打包分成了两种模式, 一种是线上生产环境的模式, 另一种是开发环境的模式
  // production: 生产模式, 会对代码进行压缩混淆
  // development: 开发模式, 不会对代码进行压缩混淆, 速度非常快
  // 只要修改了 webpack 的配置文件, 都需要重新启动开发服务器
   /* devServer 修改代码后不会刷新浏览器就直接更新页面了, 代码热更新, 
   只打包修改了的部分, 以打补丁的形式替换到浏览器上 */
  // HMR: Hot Moudle Replacement 热模块替换, 简称热更新
  // ◆10.模式
  mode: 'production',
  // ◆9.开发服务器
  devServer: {
    port: 3000, // 端口号
    open: true // 启动后自动打开浏览器
  },

  // ◆1.入口,可以是相对路径
  entry: './src/main.js',
  // ◆2.出口,必须是绝对路径
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  // ◆3.插件,自动生成DOM树(不需要手动复制母板)
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    })
  ],
  // 配置 loader
  // 如何处理项目中不同模块文件
  module: {
    rules: [
      // 一个对象表示一条匹配规则
      // ◆4.配置css
      {
        test: /\.css$/i, // 匹配所有的css文件
        // use数组里从右向左运行
        // 先用 css-loader 让webpack能够识别 css 文件的内容并打包
        // 再用 style-loader 将样式, 把css插入到dom中
        use: ["style-loader", "css-loader"]
      },
      // ◆5.配置less
      {
        test: /\.less$/i,
        use: ["style-loader", "css-loader", "less-loader"]
      },
      // ◆6.配置图片
      {
        test: /\.(png|jpg}jpeg|gif|bmp)$/i,
        type: 'asset',
        generator: {
          filename: 'imagess/[name][ext]'
        }
      },
      // ◆7.配置字体图标
      {
        test: /\.(eot|ttf|woff|woff2|svg)$/i,
        type: 'asset/resource',
        generator: {
          // 占位符: 
          // [name] 原文件名, 表示以前叫什么名字现在就原样输出
          // [ext] 原后缀名(包含.), 原来的后缀名, 包括 ., 例如 .eot
          // [hash] 生成 hash 值, 唯一的标识, 避免重名覆盖
          filename: 'fonts/[name]-[hash:6].[ext]'
        }
      },
      // ◆8.降级,匹配版本
      {
        test: /\m?.js$/, // 匹配js结尾文件
        exclude: /(node_modules|bower_components)/, // 不转换这2个文件夹里的js
        use: {
          loader: 'babel-loader', // 使用加载器-处理
          options: {
            presets: ['@babel/preset-env'] // 预设:转码规则(用bable开发环境本来预设的)
          }
        }
      }
    ]
  }
}