前端构建工具webpack&vite

298 阅读7分钟

背景

在前端开发中,面对以下两个主要问题:

  1. 浏览器兼容性问题:随着 JavaScript 新特性的不断推出,如箭头函数、Promiseasync/await 等,开发者往往希望能够使用这些新特性来提高代码的简洁性和可维护性。然而,旧版浏览器(如 Internet Explorer 及一些老版本的 Chrome 和 Firefox)对这些新特性的支持并不好,可能导致一些功能在用户的浏览器上无法正常运行。因此,开发者需要一种工具,将这些现代 JavaScript 特性转译成旧浏览器能够理解和执行的代码。这就是所谓的跨浏览器兼容性处理。
  2. 文件多问题:在现代 Web 开发中,应用往往由多个模块、库和第三方依赖构成,可能会生成大量的独立文件。在没有打包工具的情况下,浏览器会逐个加载这些文件,造成网络请求次数过多,影响页面加载速度和用户体验。因此,如何将多个文件合并成一个或者几个文件,并进行合理优化,是解决性能瓶颈的关键之一。

为了解决这些问题,前端打包工具应运而生,它的主要目标是:

  • 兼容性处理:将现代 JavaScript 代码通过转译(例如使用 Babel)转成浏览器能够识别的旧版 JavaScript,确保应用在各种浏览器上都能正常运行。
  • 性能优化:通过将多个模块合并成一个或几个文件,并进行压缩、去除冗余代码等优化措施,减少网络请求次数和文件大小,从而提升页面加载速度。

前端的打包工具,如 WebpackVite,正是为了满足这些需求而设计的。它们不仅能将代码打包、压缩,还能处理多种资源类型(如 JavaScript、CSS、图片等),并通过插件和配置灵活支持各种功能。

简单来说,打包工具的核心作用就是:将开发者编写的多个模块和资源文件,经过编译、压缩和优化处理后,打包成浏览器能够高效加载和运行的最终文件。

一、webpack

本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个依赖图,然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

image.png

1.核心配置

接下来介绍下webpack的一些核心配置:

  • 入口(entry)
    入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。默认值是 ./src/index.js,可以通过在webpack.config.js中配置 entry 属性,来指定一个(或多个)不同的入口起点。
    module.exports = {
      	entry: './path/to/my/entry/file.js',
    };
  • 输出(output)
    output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是./dist/main.js,其他生成文件默认放置在./dist文件夹中。你可以通过在配置中指定一个 output 字段,来配置这些处理过程:

    const path = require('path');
    module.exports = {
      entry: './path/to/my/entry/file.js',
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js',
      },
    };
    
  • loader
    webpack只能理解JavaScriptJSON文件,这是webpack开箱可用的自带能力。loaderwebpack能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。
    接下来列举一些常用loader
    babel-loaderJS代码转换为浏览器可识别的,比如有一些浏览器不支持ES6。可以结合browserslist(设置要兼容哪些浏览器)。

	安装:npm install -D babel-loader @babel/core @babel/preset-env 
    //其中babel-loader为加载器,把babel和webpack连接到一起,@babel/core为babel的核心,@babel/preset-env为babel的预设环境,把常用插件准备好
	使用:
    module: {
      rules: [
        {
          test: /\.m?js$/,
          exclude: /(node_modules|bower_components)/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env'],
            },
          },
        },
      ];
    }
	// 在package.json中定义支持哪些浏览器 
    "browserslist": [
          "defaults"
     ]
  • 图片
    module: {
        rules: [
            {
                test: /\.(png|jpg|svg|jpeg|gif)$/i,
                type: 'assets/resource'
            }
        ]
    }
    
    // 其中type的值有以下几种 (https://www.webpackjs.com/guides/asset-modules/#resource-assets)。
    // 1、type: 'assets/resource' 会将资源(图片)放在打包后的文件夹里;
    // 2、type: 'assets/inline' 对资源进行格式转换(base64),将编码后的源码直接放在打包后的js文件中;
    // 3、type: 'assets' 可以通过配置设置什么时候采用上面哪种方法,比如小文件使用'assets/inline'。
    

下图用于对type: 'assets'举例说明:

image.png

  • css-loader、style-loader
    css-loader是将css写入JS文件中,style-loader才是执行,他们俩有先后顺序。
module: {
    rules: [
        {
            test: /\.css$/i,
            use: ["style-loader", "css-loader"]
        }
    ]
}
  • plugin
    插件目的在于解决loader无法实现的其他事,为Webpack拓展功能。Webpack提供很多开箱即用的插件。
    html-webpack-plugin:这个插件可以在打包代码后,自动在打包目录生成 html 页面。
    (1)安装依赖
    (2)配置插件 plugins: [ new HTMLPlugin({ template: "./src/index.html" }) ]

2.webpack-dev-server

Webpack开发服务器,将代码运行到启动的服务上,能够实时监听代码变化、打包并刷新界面,是在服务器打包运行,并不会打包本地代码,开发完成后需手动打包。

  安装:   npm add -D webpack-dev-server
  启动:   npm webpack serve --open

3.sourceMap

把构建后的代码和源码做映射,方便开发时在浏览器中查看、调试。

    devtool:"inline-source-map" 

4.Webpack打包流程

(1)初始化参数:从配置文件 和 Shell 语句中读取与合并参数,得出最终的参数;
(2)开始编译:用上一步得到的参数初始化 Compiler 对象、加载所有配置的 Plugin 插件、执行对象的 run 方法开始执行编译;
(3)编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,递归此步骤直到所有依赖的文件也都处理过;
(4)输出资源:根据入口和模块之间的依赖关系,组装成一个包含多个模块的 Chunk。再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
(5)输出完成:在确定好输出内容后,根据output确定输出的路径和文件名,输出文件夹。
其中:
Module:webpack 里一个概念性内容,每个文件都可以看为一个 module。 js、css、图片等都可以看作 module。
Chunk:代码块,webpack 处理代码时候的一个中间态,它表示有一组功能相关的模块的集合。一个 Chunk 可以由多个模块(module)组成;
Bundle:是 Webpack 构建结果的输出,由一个或多个 Chunk 的合并优化后的结果,最终以文件形式输出,用于在浏览器中加载和执行。

二、vite

npm i vite //在已有项目安装vite
npm create vite //使用命令构建vite项目
vite //直接在浏览器运行ESM代码,不打包
vite preview //预览打包后的代码

vite常见配置:

1.plugin

使用插件扩展vite功能。

// vite.config.js
import { defineConfig } from "vite" //使用这个时,编写配置时有提示
import legacy from "@vitejs/plugin-legacy"

export default defineConfig({
    plugins: [
        legacy({
            targets: ["defaults"] //配置需要兼容的浏览器版本,vite打包后会生成两个js文件,一个兼容版一个原来版,通过判断运行浏览器版本判断使用不同版本
        })
    ]
})

三、webpack VS vite

  • 运行方式:webpack先打包,在运行,开发效率低,vite在开发时不对代码打包,直接采用ESM方式运行项目;
  • 配置:webpack需要配置loaderplugin等,vite开箱即用;
  • 底层:vite使用GO编写的,webpacknode编写的。

未完。。。

参考:

一文带你梳理Webpack面试题(2024年版)
前端构建工具(webpack&vite)教程 李立超