webpack和vite笔记

153 阅读15分钟

1、什么是webpack

  • Webpack 是一个现代的 JavaScript 应用程序的静态模块打包工具。它主要用于处理 JavaScript 文件,但也能够处理 CSS、图片以及其他资源。Webpack 会将这些文件视作模块,并生成对应的静态资源,这些资源最终用于在浏览器中加载运行。Webpack 的主要功能包括代码打包、模块化管理、依赖分析、代码压缩、代码拆分等,使得开发者能够更高效地管理和组织复杂的前端项目。webpack 配置文件提供了灵活的配置选项,可以根据项目的需求进行定制化配置。Webpack 在现代 Web 开发中得到了广泛的应用,并成为了前端开发工具链中的重要一环。

2、什么是Webpack Dev Server?

  • 它是一个用于开发环境的轻量级服务器,它与 webpack 结合使用,可以实现在开发过程中的快速开发、实时预览和热模块替换(Hot Module Replacement,HMR)等功能。

  • Webpack Dev Server 的主要作用包括四点:

    • 1、实时预览: 它能够在开发过程中实时地将编译后的代码部署到一个临时的服务器上,并自动刷新浏览器,使开发者可以实时看到修改后的效果。

    • 2、热模块替换(HMR): Webpack Dev Server 还支持热模块替换,即在不刷新整个页面的情况下,只替换修改的模块,从而加快开发速度,提升开发体验。

    • 3、自动刷新: 当源代码发生改变时,Webpack Dev Server 会自动重新编译代码,并刷新浏览器,使开发者能够实时查看最新的修改效果。

    • 4、支持代理: 它支持代理服务器,可以将请求代理到其他服务器上,用于解决跨域等问题。

3、什么是Webpack的Chunk?

  • Chunk 是 Webpack 打包过程中的一个单位,它表示被拆分后的代码块。这个拆分可以是根据项目的配置,也可以是根据代码中的动态导入语句(如 import())自动进行的。通常情况下,一个 Chunk 会包含多个模块,这些模块可能在逻辑上有一定的关联性

  • 在 Webpack 中,你可以通过配置控制代码的拆分行为,从而决定如何生成 Chunk。这包括使用 Webpack 提供的内置插件(如 SplitChunksPlugin)来自定义拆分策略,或者通过代码中的动态导入语句来实现按需加载。所以说,Chunk 并不仅仅表示将一个代码文件切割成多个小模块,而是表示拆分后的代码块,其中可能包含一个或多个模块。

  • Webpack在打包过程中会将源代码分割成多个 Chunk,每个 Chunk 包含了一组相关联的模块。这样做的好处包括:

    • 提高加载速度: 将代码分割成多个 Chunk 可以减少单个文件的大小,从而减少了首次加载的时间,提高了网页的加载速度。

    • 提升缓存利用率: 如果代码发生变化,只需重新加载发生更改的 Chunk,而不需要重新加载所有的代码,从而提高了缓存的利用率。

    • 按需加载: 可以根据需要动态加载特定的 Chunk,从而实现按需加载,减少了初始加载时的资源消耗。

4、如何使用Webpack进行代码分割?

  • 使用动态 import(): 在代码中使用动态 import() 语法来实现按需加载。当 Webpack 检测到动态 import() 语句时,会自动生成一个单独的 Chunk,并在需要时异步加载该 Chunk。

  • 使用Webpack内置插件: Webpack 提供了一些内置的插件来实现代码分割,最常用的是 SplitChunksPlugin。该插件可以根据配置将公共模块拆分成单独的 Chunk,以减少重复加载的代码量。

    • Webpack中,splitChunks 有三种主要的模式,它们分别是:
      • async: 该模式仅将异步加载的模块(通过动态 import() 或者按需加载的模块)进行拆分。这意味着只有异步加载的模块才会生成新的 Chunk。

      • initial: 这个模式将同步导入的模块进行拆分,也就是入口模块(entry module)。入口模块是指在入口文件中直接导入的模块。这种模式适用于将一些基础模块提取到公共的 Chunk 中。

      • all: 这个模式结合了 async 和 initial 两种模式的行为,即同时拆分异步加载的模块和同步导入的模块。这是默认的模式。

  • 使用 magic comment: 可以在代码中使用特殊的注释来指定生成的 Chunk 的名称。

5、如何在Webpack中处理静态资源?

  • Webpack 处理静态资源的方案通常是通过使用 loader 插件来处理文件。
  • 在Webpack中处理静态资源通常涉及加载、压缩、优化和输出这些资源,主要包括图片、字体、样式表等。以下是一些常见的处理静态资源的方法:
    • 加载图片和字体: 使用Webpack的file-loader或url-loader加载图片和字体文件。file-loader会将文件复制到输出目录并返回文件路径,而url-loader可以将小于指定大小的文件转换为 base64 编码的 Data URL,减少HTTP请求。

    • 处理样式表: 使用Webpack的css-loader加载CSS文件,并使用style-loader将样式注入到页面中。

    • 优化图片: 使用Webpack的image-webpack-loader来优化图片,包括压缩、转换等。

6、如何优化Webpack的构建时间?

  • 优化Webpack的构建时间可以通过多种方式实现,以下是一些常见的优化方法:
    • 合理配置Webpack:

      • 使用合适的 loader 和 plugin:选择适合项目的 loader 和 plugin,并且尽可能减少不必要的 loader 和 plugin。
      • 合理配置模块解析路径:通过配置 resolve.modules、resolve.extensions、resolve.alias 等选项来优化模块解析路径,减少不必要的文件搜索。
      • 使用缓存:通过启用缓存选项,如babel-loader的cacheDirectory选项,可以减少重复工作,提高构建性能。
    • 使用多进程或多实例构建:

      • 使用 Webpack 的多进程模式或者使用 parallel-webpack 等工具,可以利用多核 CPU 来并行构建,加速构建过程。 按需加载:

      • 通过动态 import() 等方式实现按需加载,避免一次性加载所有代码,从而减少构建时间。

    • 分割代码:

      • 使用代码分割(code splitting)技术,将代码拆分成多个 Chunk,从而减少每次构建需要处理的代码量,提高构建速度。
    • 压缩优化:

      • 合理配置压缩选项,如使用 TerserPlugin 压缩 JavaScript 代码、使用 optimize-css-assets-webpack-plugin 压缩 CSS 代码等,可以减小构建输出体积,加快构建速度。
    • 使用高性能的 loader 和 plugin:

      • 使用性能较高的 loader 和 plugin,如使用 babel-loader 的 cacheDirectory 选项、使用 terser-webpack-plugin 替代 UglifyJSPlugin 等。
    • 减少文件数量:

      • 减少不必要的文件数量,如合并小文件、删除无用文件等,可以减少构建时间。
    • 监控构建性能:

      • 使用 Webpack-bundle-analyzer 等工具来分析构建产物,查找构建过程中的性能瓶颈,并优化相关配置。

7、Webpack Hot Module Replacement是什么?

  • Webpack Hot Module Replacement 热更新(HMR)是Webpack提供的一个强大的功能,它允许在应用程序运行时更新、添加或删除模块,而无需重新加载整个页面。这意味着在开发过程中,当你编辑代码时,应用程序的状态会被保留,只有修改的部分会被实时更新,从而大大提高了开发效率和体验。

  • 具体来说,HMR 提供了以下功能:

    • 模块热替换: 当代码发生变化时,Webpack会通知客户端(通常是浏览器)有关更改,并且只会更新更改的模块,而不是整个页面。

    • 保持应用程序状态: 在代码更新时,应用程序的状态会被保留,不会丢失。这意味着你不需要重新加载页面或者重新执行应用程序的状态设置代码。

    • 快速更新: HMR的速度非常快,因为它只更新发生更改的模块,而不是整个应用程序。

8、Webpack的工作原理是什么?

  • Webpack 的工作原理可以概括为以下几个步骤:

    • 解析和构建依赖图: Webpack 从指定的入口文件开始,递归地解析该文件依赖的所有模块(包括 JavaScript、CSS、图片等资源),并构建出完整的依赖图。

    • 加载和转换模块: 对于每个模块,Webpack 根据配置的规则(如 loader)将其加载并进行相应的转换。例如,对于 JavaScript 文件,可能需要使用 Babel 进行转译;对于 CSS 文件,可能需要使用 css-loader 进行加载;对于图片等资源,可能需要使用 file-loader 进行加载。

    • 优化和打包代码: Webpack 在加载和转换完所有模块后,会对模块进行优化处理,包括代码压缩、去除无用代码、合并重复代码等。然后,Webpack 将所有模块打包成一个或多个 bundle 文件。

    • 输出打包文件: 打包完成后,Webpack 将生成的 bundle 文件输出到指定的目录中,供浏览器加载和运行。

  • 在这个过程中,Webpack 还提供了许多功能和特性,如代码分割、模块热替换(Hot Module Replacement)、Tree Shaking 等,以帮助开发者更高效地管理和构建前端项目。

9、Webpack的常见配置文件是什么?

  • Webpack 的常见配置文件是 webpack.config.js。这个文件是一个 JavaScript 模块,用于配置 Webpack 的各种选项和参数,包括入口输出loaderplugin 等。在这个配置文件中,我们可以定义项目的入口文件输出文件位置和名称、处理不同类型资源loader优化插件等。除了 webpack.config.js 外,有时候也会使用 webpack.base.js, webpack.prod.js, webpack.dev.js 等分割的配置文件来组织配置选项,分别用于不同环境下的配置

webpack 的优化方案

1、优化打包速度

  • 1.1、使用缓存

    • 持久化缓存:通过 cache 选项,开启持久化缓存,提高二次构建速度。
    module.exports = {
      cache: {
        type: 'filesystem', // 使用文件系统缓存
      },
    }; 
    
  • 1.2、多进程/多实例构建

    • Parallel-webpack:使用 parallel-webpack 提升构建速度,适用于多配置的项目。
    • Thread-loader:使用 thread-loader 让某些 loader 在单独的 worker 池中运行,提升构建速度。
    module: {
      rules: [
        {
          test: /\.js$/,
          use: ['thread-loader', 'babel-loader'],
        },
      ],
    }; 
    
  • 1.3、缩小打包范围

    • Include/Exclude:在 loader 中通过 include 和 exclude 限制处理范围,减少不必要的处理。
    module: {
      rules: [
        {
          test: /\.js$/,
          include: path.resolve(__dirname, 'src'),
          exclude: /node_modules/,
          use: 'babel-loader',
        },
      ],
    }; 
    
    • Resolve.alias:通过 alias 缩短路径解析时间。
    resolve: {
      alias: {
        '@': path.resolve(__dirname, 'src'),
      },
    }; 
    

2、优化包体积

  • 2.1、Tree Shaking

    • 使用 ES6 模块:确保使用 ES6 模块语法(import 和 export),以便 Webpack 进行 Tree Shaking。

    • 配置 optimization:在 webpack.config.js 中配置 optimization 以启用 Tree Shaking。

    module.exports = {
      optimization: {
        usedExports: true,
      },
    };
    
  • 2.2、代码分割

    • SplitChunksPlugin:通过 SplitChunksPlugin 进行代码分割,减少单个文件的体积。
    module.exports = {
      optimization: {
        splitChunks: {
          chunks: 'all',
        },
      },
    };
    
  • 2.3、动态导入

    • 动态导入(Dynamic Import):使用 import() 动态加载模块,实现按需加载
    // Example.js
    import('./module').then(module => {
      // 使用加载的模块
    });
    
  • 2.4、压缩代码

    • TerserPlugin:使用 TerserPlugin 压缩 JavaScript 代码。
    const TerserPlugin = require('terser-webpack-plugin');
    
    module.exports = {
      optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()],
      },
    };
    
    • CSS 压缩:使用 css-minimizer-webpack-plugin 压缩 CSS。
    const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
    
    module.exports = {
      optimization: {
        minimize: true,
        minimizer: [new CssMinimizerPlugin()],
      },
    };
    

3、优化开发体验

  • 3.1、使用 Source Map

    • 配置 Source Map:在开发环境中使用 Source Map,方便调试。
    module.exports = {
      devtool: 'source-map',
    };
    
  • 3.2、热模块替换(HMR)

    • 开启 HMR:通过 HotModuleReplacementPlugin 实现模块热替换,提高开发效率。
    const webpack = require('webpack');
    
    module.exports = {
      plugins: [
        new webpack.HotModuleReplacementPlugin(),
      ],
      devServer: {
        hot: true,
      },
    };
    

4、其他优化

  • 4.1、分析包体积
    • webpack-bundle-analyzer:使用 webpack-bundle-analyzer 分析包体积,找出体积较大的模块进行优化。
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    
    module.exports = {
      plugins: [
        new BundleAnalyzerPlugin(),
      ],
    };
    

10、 Vite 和 Rollup 的作用和特点

  • Vite

    • Vite 主要用于快速开发现代 Web 应用程序。它是一个基于 ES Module 的构建工具,专注于提供开发服务器构建功能,以加快现代 Web 应用的开发速度。

    • 快速启动: Vite 利用浏览器原生ES Module (ESM) 支持,在开发环境下使用原生 ES Module 作为开发服务器模块解析规则,因此启动速度非常快

    • 按需编译: Vite 支持按需编译,只编译需要的文件,而不是像传统的打包工具一样将整个应用打包成一个或多个文件

    • 支持多种语言: Vite 支持 VueReactSvelte 等多种前端框架,并且可以使用 TypeScriptJavaScriptCSSSCSSLESSJSONGraphQL 等多种语言。

    • 模块热更新: Vite 内置了模块热更新 (HMR) 功能,可以在不刷新页面的情况下实时更新代码变化,加快开发效率。

  • Rollup

    • Rollup 是一个 JavaScript 模块打包器,用于将 JavaScript 模块打包成一个或多个输出文件,以便在浏览器中使用。它主要用于构建库和工具,提供了更高级的优化和定制功能。

    • Tree-shaking: Rollup 以模块为单位进行构建,可以识别并移除未使用的代码,从而减小最终打包文件的体积。

    • 插件化: Rollup 支持插件系统,允许开发人员通过插件来扩展其功能,实现各种自定义的优化和定制需求。

    • 输出多种格式: Rollup 可以将 JavaScript 模块打包成多种格式,包括 CommonJS、ES Module、UMD 等,以适应不同的使用场景和环境。

    • 定制化配置: Rollup 的配置相对于其他打包工具来说更加简洁和灵活,可以根据项目的实际需求进行定制化配置。

11、vue.config.js、next.config.js、vite.config.js和webpack.config.js这四个文件有什么区别?

  • vue.config.js

    • 适用:Vue
    • 主要特点:
      • 自定义 webpack 配置:通过 configureWebpack 或 chainWebpack 属性。
      • 配置开发服务器(dev server)。
      • 配置 CSS(例如是否使用 CSS Modules)。
      • 设置路径别名。
      • 配置生产环境和开发环境的特定设置。
  • next.config.js

    • 适用:Next
    • 主要特点:
      • 自定义 Webpack 配置。
      • 配置静态文件路径。
      • 配置 API 路由和国际化(i18n)。
      • 设置环境变量
      • 配置特定于 Next.js 的功能(如图片优化、静态站点生成)。
  • vite.config.js

    • 适用:Vite(支持 Vue、React 等框架)
    • 主要特点:
      • 配置开发服务器。
      • 配置插件。
      • 设置路径别名。
      • 配置构建选项(如输出目录、rollup 配置)。
      • 支持多框架:Vue、React、Svelte 等。
  • webpack.config.js

    • 适用:通用(适用于任何使用 Webpack 的项目)
    • 主要特点:
      • 配置模块解析、加载器和插件。
      • 配置开发服务器。
      • 设置路径别名和输出目录。
      • 配置优化选项(如代码分割、压缩)。
      • 高度灵活,可自定义任意 Webpack 配置。

12、vite 比 webpack 速度更快,体现在哪几个方面。

1. 初始启动速度

  • Vite初始启动速度显著快于 Webpack 。这是因为 Vite 在启动时不需要预先打包整个应用程序,而是直接利用浏览器的 ES模块 支持。
    • Vite 在开发环境中利用了 ES模块 使用, <script type="module"> 标签来加载 JS 文件。这意味着浏览器可以直接解析执行这些模块,而不需要像传统工具那样先进行打包。
    • 利用 ES模块 特性:
      • 模块化每个文件都是一个独立模块,浏览器可以独立处理缓存这些模块。
      • 按需加载:只有在需要时才会加载执行模块,这减少初始加载时间
      • 静态依赖解析ES 模块的依赖关系在静态分析阶段就可以确定,这使得模块之间的关系更清晰准确
  • Webpack 在启动时通常需要解析和构建整个依赖图,这个过程在大型项目中可能非常耗时

2. 模块热替换(HMR)速度

  • ViteHMR 速度也比 Webpack 快。具体原因包括:
    • 精准更新Vite 可以精确单个模块进行更新,而 Webpack 通常需要重新构建依赖树的较大部分
    • 更少的重编译Vite 依赖于按需编译的策略,只有变更的模块会被重新编译加载,避免了不必要重新编译

3. 按需编译

  • Vite 仅在浏览器请求模块才进行编译,而不是在启动时一次性编译所有代码。这种按需编译大大减少初始加载时间不必要的编译工作,从而提升了整体开发体验

4. 预构建依赖

  • Vite 使用 esbuild 预构建第三方依赖(如 npm 包),esbuild 是一个用 Go 语言编写的超快速构建工具,其性能远超传统的 JS 构建工具。预构建依赖减少了每次开发时需要重新解析打包工作量

5. 即时反馈

  • Vite 直接使用浏览器提供开发工具原生 ESM,开发者在进行代码修改时可以即时看到结果
  • Webpack 则需要重新打包重新加载,这个过程可能会有显著的延迟

6. 资源加载优化

  • Vite 利用浏览器的 HTTP/2 多路复用特性优化资源加载。这种方式允许多个文件通过单个连接并行加载,从而减少等待时间加载时间