webpack理解与使用

一、背景

webpack的最初目标是实现前端工程的模块化,旨在更高效的管理和维护项目中的每一个资源。

最早的时候,我们通过文件划分的方式实现模块化,也就是将每个功能及其相关状态数据都放在一个JS文件中,约定每个文件就是一个独立模块,再将这些JS文件以script标签引入到页面中。

<script src="module-a.js"></script>
<script src="module-b.js"></script>

但是这种方式弊端很明显,每个模块都是在全局中工作,大量模块成员污染环境,模块之前没有依赖、维护困难、没有私有空间等问题。项目越复杂,问题越明显。

后来出现了命名空间的方式,规定每个模块只暴露一个全局对象,模块的所有内容都挂载到这个对象上,但是这种方式也没有解决模块之间的依赖问题。

// module-a.js
window.moduleA = {method1: function () {console.log('moduleA#method1')}
}

理想的解决方式是,在页面中引入一个JS入口文件,其余用到的模块可以通过代码控制,按需加载进来。

与此同时,在前端开发历程中,从后端渲染的JSP,到原生JavaScript开发,再到JQuery开发,再到如今的三大框架vue、react、angular,开发方式也从JavaScript到es6,再到typeScript,包括css的预处理器less、sass等等,前端开发已经变得十分复杂,通常会遇到以下问题:

  1. 需要通过模块化的方式开发
  2. 需要使用一些高级特性来加快开发效率或者安全性,比如ES6+、typescript
  3. 需要监听文件的变化来反映到浏览器上,提升开发效率
  4. JavaScript、Css、Html文件都需要被模块化
  5. 开发完成后需要进行代码压缩、合并

此时,webpack刚好可以解除上面的问题。

二、webpack是什么

Webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。它能够将项目中的各种资源,如 JavaScript、CSS、图片、字体等,视为模块,并将这些模块按照依赖关系打包成一个或多个静态文件,以便在浏览器中加载和运行。

Webpack 的主要功能包括:

  1. 模块化打包:将项目中的多个模块打包成一个或多个文件,便于管理和传输。
  2. 代码分割:允许你将代码分割成多个小块,按需加载,提高应用性能。
  3. 加载器(Loaders):Webpack 使用加载器来预处理文件,例如将 ES6 编译为 ES5,或者将 CSS 和 SASS 文件转换为 JavaScript 模块。
  4. 插件(Plugins):Webpack 插件用于执行更广泛的任务,如打包优化、资源管理、环境变量注入等。
  5. 开发服务器:内置开发服务器,能够提供热重载功能,方便开发时调试代码。

三、webpack的构建流程

Webpack 的构建流程可以大致分为以下几个步骤:

  1. 初始化参数

    • 从命令行和配置文件(webpack.config.js)中读取并合并参数,形成最终的配置对象。这个配置对象包含了入口起点、输出配置、加载器规则、插件列表等信息。
  2. 开始编译

    • 根据配置中的入口起点,启动编译器。
    • 创建编译对象 Compiler,并调用 run 方法开始编译。
  3. 确定入口

    根据配置文件中的 entry 属性,确定入口文件。Webpack 支持单入口和多入口。
  4. 编译模块

    • 使用 Compiler 调用 buildModule 方法,从入口文件开始,递归地解析和编译模块。
    • 编译过程中,根据模块类型和配置的加载器(Loaders)进行相应的预处理。
    • 处理后的模块会被转换成抽象语法树(AST),进一步分析模块的依赖关系。
  5. 完成模块编译

    • 当所有模块及其依赖都被编译完成后,Webpack 会生成最终的模块图(Module Graph)。
    • 这个图描述了所有模块之间的依赖关系,为后续的优化和打包提供依据。
  6. 输出资源

    • 根据 Compiler 生成的模块图和配置的输出规则(output),开始生成最终的静态资源文件。
    • 输出资源的过程中,Webpack 会调用各种插件(Plugins)进行进一步的处理和优化。
  7. 插件优化

    • 在输出资源的过程中,Webpack 会调用插件进行优化,例如代码压缩、分片、注入环境变量等。
    • 插件可以在编译的不同阶段执行自定义的任务,包括在构建过程开始时、模块加载时、文件输出时等。
  8. 完成打包

    • 所有的资源文件生成完成后,Webpack 会将它们写入到指定的输出目录中。
    • 生成的文件可以被浏览器加载和运行,完成前端应用的构建。

四、常见的loader及其作用

在 Webpack 中,加载器(Loader)用于对不同类型的文件进行预处理。以下是一些常见的加载器及其解决的问题:

  1. babel-loader:将 ES6+ 代码转换为向后兼容的 JavaScript 代码,以便在旧版本的浏览器中运行。

    module: {rules: [{test: /\.js$/,exclude: /node_modules/,use: {loader: 'babel-loader',options: {presets: ['@babel/preset-env']}}}]
    }
    
  2. css-loader 和 style-loader:处理 CSS 文件,将 CSS 内容注入到 JavaScript 中,并通过 <style> 标签插入到 HTML 中。

    module: {rules: [{test: /\.css$/,use: ['style-loader', 'css-loader']}]
    }
    
  3. sass-loader 和 node-sass:将 Sass 或 SCSS 文件编译成 CSS 文件。

    module: {rules: [{test: /\.s[ac]ss$/i,use: ['style-loader', 'css-loader', 'sass-loader']}]
    }
    
  4. less-loader:将 Less 文件编译成 CSS 文件。

    module: {rules: [{test: /\.less$/,use: ['style-loader', 'css-loader', 'less-loader']}]
    }
    
  5. file-loader:处理文件(如图片、字体文件)的导入,将其复制到输出目录中,并返回文件的 URL。

    module: {rules: [{test: /\.(png|jpe?g|gif|svg|woff|woff2|eot|ttf|otf)$/,use: [{loader: 'file-loader',options: {name: '[name].[hash].[ext]',outputPath: 'images/'}}]}]
    }
    
  6. url-loader:类似于 file-loader,但它可以将小文件(如小于某个阈值的图片)转换为 Base64 编码的数据 URL,直接嵌入到代码中,减少 HTTP 请求。

    module: {rules: [{test: /\.(png|jpe?g|gif|svg)$/i,use: [{loader: 'url-loader',options: {limit: 8192, // 小于 8KB 的文件会被转换为 Base64name: '[name].[hash].[ext]',outputPath: 'images/'}}]}]
    }
    
  7. html-loader:处理 HTML 文件,将 HTML 中的 src 等属性值转换为模块导入路径。

    module: {rules: [{test: /\.html$/,use: [{loader: 'html-loader',options: {minimize: true}}]}]
    }
    
  8. ts-loader 或 awesome-typescript-loader:将 TypeScript 文件转换为 JavaScript 文件。

    module: {rules: [{test: /\.tsx?$/,use: 'ts-loader',exclude: /node_modules/}]
    }
    
  9. vue-loader:处理 Vue 单文件组件(.vue 文件),将模板、脚本和样式分别编译为对应的模块。

    module: {rules: [{test: /\.vue$/,loader: 'vue-loader'}]
    }
    

这些加载器帮助 Webpack 处理不同类型的文件,使得开发者可以更方便地使用现代 JavaScript 和 CSS 特性,同时简化了资源管理,提高了开发效率。

五、常见的plugin及其作用

在 Webpack 中,插件(Plugin)用于执行更广泛的任务,如打包优化、资源管理、环境变量注入等。它们会运行在 webpack 的不同阶段(钩子 / 生命周期),贯穿了webpack整个编译周期,目的在于解决loader 无法实现的其他事。

以下是一些常见的插件及其作用:

  1. HtmlWebpackPlugin:自动生成 HTML 文件,并将其注入打包后的 JavaScript 文件。

    const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {plugins: [new HtmlWebpackPlugin({template: './src/index.html', // 模板文件路径filename: 'index.html', // 输出文件名inject: 'body' // 将打包后的脚本注入到 body 标签中})]
    };
    
  2. CleanWebpackPlugin:每次构建前清理输出目录,确保输出目录中只有最新的构建结果。

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {plugins: [new CleanWebpackPlugin()]
    };
    
  3. MiniCssExtractPlugin:将 CSS 从 JavaScript 中分离出来,生成单独的 CSS 文件,便于缓存和管理。

    const MiniCssExtractPlugin = require('mini-css-extract-plugin');module.exports = {module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader, 'css-loader']}]},plugins: [new MiniCssExtractPlugin({filename: '[name].[contenthash].css'})]
    };
    
  4. DefinePlugin:定义全局常量,提供给代码中使用。这对于配置不同的环境变量非常有用。

    const webpack = require('webpack');module.exports = {plugins: [new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')})]
    };
    
  5. CopyWebpackPlugin:将项目中静态文件(如图片、字体文件等)复制到输出目录中

    const CopyWebpackPlugin = require('copy-webpack-plugin');module.exports = {plugins: [new CopyWebpackPlugin({patterns: [{ from: 'src/assets', to: 'assets' }]})]
    };
    
  6. HotModuleReplacementPlugin:在开发过程中实现模块热替换(HMR),允许在不刷新整个页面的情况下更新模块。

    const webpack = require('webpack');module.exports = {devServer: {hot: true},plugins: [new webpack.HotModuleReplacementPlugin()]
    };
    
  7. TerserPlugin:压缩和混淆 JavaScript 代码,减少文件体积,提高加载性能。

    const TerserPlugin = require('terser-webpack-plugin');module.exports = {optimization: {minimize: true,minimizer: [new TerserPlugin()]}
    };
    
  8. OptimizeCSSAssetsPlugin:压缩和优化 CSS 文件,减少文件体积。

    const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');module.exports = {optimization: {minimizer: [new TerserPlugin(),new OptimizeCSSAssetsPlugin()]}
    };
    
  9. ProvidePlugin:自动加载模块,无需在代码中显式导入。这对于使用 jQuery 或其他全局库非常有用。

    const webpack = require('webpack');module.exports = {plugins: [new webpack.ProvidePlugin({$: 'jquery',jQuery: 'jquery'})]
    };
    
  10. BundleAnalyzerPlugin:生成代码的体积报告,帮助分析和优化打包后的文件。

    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');module.exports = {plugins: [new BundleAnalyzerPlugin()]
    };

这些插件极大地扩展了 Webpack 的功能,使得构建过程更加灵活和高效。通过合理配置这些插件,开发者可以更好地管理项目资源和优化应用性能。

六、loader和plugin的区别

在 Webpack 中,Loader 和 Plugin 是两种不同的工具,它们在构建过程中扮演不同的角色。以下是它们的区别:

Loader
  1. 功能

    • 文件转换:Loader 主要用于处理和转换单个文件模块,例如将 ES6+ 代码转换为 ES5,或者将 Sass 文件编译为 CSS。
    • 预处理:Loader 在文件被添加到依赖图中之前对其进行预处理。
  2. 使用场景

    • 特定文件类型:当你需要对特定类型的文件(如 JavaScript、CSS、图片、字体等)进行处理时,使用 Loader。
    • 代码转换:将现代 JavaScript 代码转换为兼容性更好的代码,或者将其他语言(如 TypeScript、Sass 等)转换为 JavaScript/CSS。
  3. 配置

    • rules:在 webpack.config.js 文件中的 module.rules 数组中进行配置。
    • test:指定要处理的文件类型(例如 /\.js$/ 表示处理所有 JavaScript 文件)。
    • use:指定使用的 Loader。
Plugin
  1. 功能

    • 构建过程管理:Plugin 提供了更广泛的任务处理能力,例如打包优化、资源管理、环境变量注入等。
    • 构建阶段任务:Plugin 可以在构建过程的不同阶段(如编译开始、模块加载、文件输出等)执行自定义任务。
  2. 使用场景

    • 复杂任务:当你需要在构建过程中执行一些复杂任务,而不仅仅是文件转换时,使用 Plugin。
    • 自定义构建:例如生成 HTML 文件、清理输出目录、处理环境变量等。
  3. 配置

    • plugins:在 webpack.config.js 文件中的 plugins 数组中进行配置。
    • 实例化:每个 Plugin 都需要实例化后添加到 plugins 数组中。
总结
  • Loader

    • 专注于文件的转换和预处理。
    • 主要用于处理单个文件模块。
    • 配置在 module.rules 中。
    • 运行在打包文件之前
  • Plugin

    • 用于执行更广泛的任务。
    • 可以在构建过程的不同阶段执行自定义任务。
    • 配置在 plugins 数组中,并需要实例化。
    • 在整个编译周期都起作用

七、HMR热更新原理

Webpack 的热更新机制主要依赖于 WebSocket 协议和一些特殊的模块和插件。以下是 HMR 的详细原理:

  1. 初始构建

    • Webpack 启动时进行初始构建,生成一个完整的模块图(Module Graph),包括所有的模块及其依赖关系。
    • 这个模块图会被编译成 JavaScript 文件,并输出到指定的目录中。
    • Webpack Dev Server 启动,并通过 WebSocket 协议与浏览器建立连接。
  2. 文件监听

    • Webpack Dev Server 监听文件系统的变化。当检测到文件变化时,它会重新编译受影响的模块。
    • 例如,如果你修改了一个 CSS 文件,Dev Server 会重新编译这个 CSS 文件及其依赖的文件。
  3. 增量编译

    • Webpack 进行增量编译,只编译发生变化的模块及其依赖模块,而不是整个项目。
    • 增量编译生成一个新的模块图,并将更新的模块信息通过 WebSocket 发送到浏览器。
  4. 客户端接收更新

    • 浏览器通过 WebSocket 接收到更新的模块信息后,浏览器会请求新的模块代码,并执行这些代码来动态替换旧的模块。
  5. 依赖处理

    • HMR 不仅替换更新的模块,还会处理这些模块的依赖关系。
    • 如果一个模块的依赖模块也发生了变化,这些依赖模块也会被替换

优点

  • 提高开发效率:无需刷新整个页面即可看到代码的变化。
  • 保留应用状态:应用的状态不会因为页面刷新而丢失。
  • 减少重复操作:开发者可以更快地进行代码调整和测试。

八、webpack中proxy工作原理

Webpack Dev Server 提供了一个强大的代理功能(proxy),用于在开发过程中解决跨域请求的问题。这个代理功能基于 Node.js 的 http-proxy-middleware 库。

代理的基本原理

  1. 跨域问题

    • 在前端开发中,前端应用通常运行在 http://localhost:8080,而后端 API 可能运行在 http://api.example.com
    • 直接从前端请求后端 API 会导致跨域问题(CORS),因为浏览器会阻止这种跨域请求。
  2. 代理的作用:Webpack Dev Server会 启动一个本地开发服务器和一个代理服务器,代理服务通过中间件拦截请求,并将其转发到目标后端服务器,目标服务器响应后将数据返回代理服务器,最后由代理服务器响应给本地,此时代理服务器与本地浏览器同源,不存在跨域行为。而服务器之间不存在跨域,所以解决了开发模式下的跨域问题。

实现过程

  1. 配置代理

    • 在 webpack.config.js 文件中配置 devServer.proxy 属性,指定代理规则。
    • 代理配置可以是一个对象或一个函数,用于定义多个代理规则。
  2. 启动开发服务器

    • 使用 webpack-dev-server 启动开发服务器,并应用代理配置。
    • 开发服务器会监听前端应用的请求,并根据代理配置将其转发到相应的后端服务器。
  3. 拦截和转发请求

    • 当浏览器向开发服务器发送请求时,开发服务器会检查请求路径是否匹配代理配置中的规则。
    • 如果匹配,开发服务器会将请求拦截并转发到指定的后端服务器。
  4. 后端服务器响应

    • 后端服务器接收到代理请求后,处理请求并返回响应。
    • 响应会被传递回开发服务器。
  5. 响应传递给浏览器

    • 开发服务器将后端服务器的响应传递给浏览器。
    • 浏览器接收到响应并进行相应的处理。

九、webpack优化性能策略

借助 Webpack 可以有效地优化前端性能。以下是一些常见的优化策略和方法:

1. 文件压缩

  • JavaScript 压缩

    使用 TerserPlugin 压缩和混淆 JavaScript 代码,减少文件体积。
    const TerserPlugin = require('terser-webpack-plugin');module.exports = {optimization: {minimize: true,minimizer: [new TerserPlugin()],}
    };
    
  • CSS 压缩:使用 OptimizeCSSAssetsPlugin 压缩 CSS 文件。

    const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');module.exports = {optimization: {minimizer: [new OptimizeCSSAssetsPlugin()],}
    };
    

2. 使用代码分割(Code Splitting)

  • 动态导入:使用动态导入(import())实现代码分割,按需加载模块。

    if (someCondition) {import('./module').then(module => {module.default();});
    }
    
  • SplitChunksPlugin:使用 SplitChunksPlugin 自动分割代码,生成多个文件。

    module.exports = {optimization: {splitChunks: {chunks: 'all',}}
    };
    

3. 使用缓存(Caching)

  • 文件名哈希:为输出文件名添加哈希值,以便浏览器可以缓存文件,当文件内容变化时,生成新的哈希值,浏览器会重新下载文件。
    const path = require('path');module.exports = {output: {path: path.resolve(__dirname, 'dist'),filename: '[name].[contenthash].js',chunkFilename: '[name].[contenthash].js',}
    };
    

4. 使用 MiniCssExtractPlugin

  • 分离 CSS 文件:使用 MiniCssExtractPlugin 将 CSS 从 JavaScript 中分离出来,生成单独的 CSS 文件,便于缓存和管理。
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');module.exports = {module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader, 'css-loader']}]},plugins: [new MiniCssExtractPlugin({filename: '[name].[contenthash].css'})]
    };
    

5. 使用 Source Maps

  • 调试优化:在开发环境中使用 source-map 以便更好地调试代码。在生产环境中,使用 source-map 可能会暴露源代码,因此建议使用更安全的源映射选项,如 hidden-source-map 或 nosources-source-map

    module.exports = {devtool: 'hidden-source-map'
    };
    

6. 使用 Loader 进行文件优化

  • 文件压缩:使用 image-webpack-loader 压缩图片文件。

    module.exports = {module: {rules: [{test: /\.(png|jpe?g|gif|svg)$/i,use: [{loader: 'file-loader',options: {name: '[name].[hash].[ext]',outputPath: 'images/'}},{loader: 'image-webpack-loader',options: {mozjpeg: {progressive: true,quality: 65},// 其他配置选项}}]}]}
    };
    
  • 字体处理:使用 url-loader 处理小字体文件,将其转换为 Base64 编码的数据 URL。

    module.exports = {module: {rules: [{test: /\.(woff|woff2|eot|ttf|otf)$/i,use: [{loader: 'url-loader',options: {limit: 8192, // 小于 8KB 的文件会被转换为 Base64name: '[name].[hash].[ext]',outputPath: 'fonts/'}}]}]}
    };
    

8. 使用插件进行优化

  • CleanWebpackPlugin:在每次构建前清理输出目录,确保输出目录中只包含最新的构建结果。

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {plugins: [new CleanWebpackPlugin()]
    };
    
  • BundleAnalyzerPlugin:生成代码的体积报告,帮助分析和优化打包后的文件。

    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');module.exports = {plugins: [new BundleAnalyzerPlugin()]
    };
    

9. 使用 Webpack Dev Server 的 HMR

  • 模块热替换:在开发阶段使用 HMR 实现模块热替换,允许在不刷新整个页面的情况下更新模块。
    const webpack = require('webpack');module.exports = {devServer: {hot: true},plugins: [new webpack.HotModuleReplacementPlugin()]
    };
    

10. 使用 Tree Shaking 和 Scope Hoisting

  • Tree Shaking:Tree Shaking 是一种通过分析模块依赖关系来移除未使用的代码的技术。通过 ES6 模块语法和 sideEffects 属性,移除未使用的代码。

    // package.json
    {"sideEffects": false
    }
    
  • Scope Hoisting:使用 ModuleConcatenationPlugin 合并模块作用域,减少生成的代码体积。

    const webpack = require('webpack');module.exports = {plugins: [new webpack.optimize.ModuleConcatenationPlugin()]
    };
    

12. 使用 Preload 和 Prefetch

  • 资源预加载和预获取:使用 preload-webpack-plugin 和 prefetch-webpack-plugin 预加载和预获取资源,提高页面加载速度。
    const PreloadWebpackPlugin = require('preload-webpack-plugin');module.exports = {plugins: [new PreloadWebpackPlugin({rel: 'preload',as: 'script',include: 'allChunks'})]
    };
    

13. 使用 CDN

  • 资源分离:使用 CDN 加载第三方库和静态资源,减少服务器负载和提高加载速度。在 index.html 中通过 CDN 引入资源:
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
    

14. 使用优化插件

  • 其他优化插件:使用 CompressionPlugin 压缩生成的文件,减少传输大小。
    const CompressionPlugin = require('compression-webpack-plugin');module.exports = {plugins: [new CompressionPlugin({test: /\.js$|\.css$/,threshold: 10240,minRatio: 0.8})]
    };
    

十、webpack和vite的区别

webpack

1. 构建流程
  • 初始构建

    • Webpack 进行初始构建时,会解析项目中的所有模块及其依赖关系,生成一个完整的模块图。
    • 这个过程包括解析、转译、优化和输出多个文件。
    • 初始构建时间较长,尤其是在大型项目中。
  • 增量构建

    • 使用增量构建(Incremental Build)来加速开发过程中的文件变化。
    • Webpack 的增量构建机制通过缓存和模块热替换(HMR)来提高效率。
    • 但即便如此,在大型项目中,增量构建也可能比较慢。
2. 配置
  • 详细配置

    • Webpack 需要详细的配置文件(webpack.config.js),包括加载器(Loaders)、插件(Plugins)、入口(Entry)、输出(Output)等。
    • 配置相对复杂,需要对 Webpack 的内部机制有一定的了解。
  • 灵活性

    • 高度灵活,可以处理复杂的项目和多种文件类型。
    • 通过各种插件和加载器,可以扩展和定制构建过程。
3. 性能
  • 构建速度

    • 初始构建速度较慢,尤其是在大型项目中。
    • 增量构建速度有所提升,但仍然可能较慢。
  • 优化

    • 内置多种优化机制,如 Tree Shaking、代码分割(Code Splitting)、插件系统等。
    • 可以通过配置和插件进行深度优化,生成高效的代码。
4. 生态系统
  • 丰富的插件

    • Webpack 拥有非常丰富的插件生态系统,几乎可以处理前端开发中的所有任务。
    • 例如,HtmlWebpackPluginCleanWebpackPluginMiniCssExtractPlugin 等。
  • 社区支持

    • 拥有庞大的用户社区和丰富的文档支持。
    • 适用于各种规模的项目,从小型应用到大型复杂应用。
5. 适用场景
  • 复杂项目

    • 适合大型和复杂的 Web 应用,特别是那些需要处理多种文件类型和复杂依赖关系的项目。
  • 多入口项目

    • 适用于多入口项目和需要多种构建配置的场景。

Vite

1. 构建流程
  • 初始构建

    • Vite 使用 ES Module 原生支持,通过快速的开发服务器启动项目。
    • 初始构建速度非常快,因为 Vite 只需要启动开发服务器,不需要解析和处理所有模块。
  • 按需编译

    • Vite 在开发过程中按需编译模块。当浏览器请求某个模块时,Vite 动态地将其转换为 ES Module 并提供给浏览器。
    • 这种按需编译机制使得 Vite 的开发服务器启动和模块热替换(HMR)非常快速。
  • 生产构建

    • 在生产环境中,Vite 使用 Rollup 进行构建,生成高效的代码。
    • Rollup 的 Tree Shaking 和代码分割机制使得生成的代码体积较小,加载速度快。
2. 配置
  • 零配置

    • Vite 提供零配置的开发体验,启动时不需要复杂的配置文件。
    • 默认配置已经包含了大部分常见的开发需求,简化了配置过程。
  • 简单配置

    • 可以通过 vite.config.js 文件进行简单的配置,包括插件、别名、代理设置等。
    • 配置相对简单,易于上手。
3. 性能
  • 开发速度

    • Vite 的开发服务器启动非常快,尤其是在大型项目中。
    • 按需编译机制使得模块热替换(HMR)也非常快速,提高了开发效率。
  • 构建速度

    • 生产构建速度较快,由于使用 Rollup 的高效机制,生成的代码体积较小。
  • 优化

    • 内置 Tree Shaking 和代码分割机制,确保生成的代码高效。
    • 可以通过插件进行进一步的优化。
4. 生态系统
  • 丰富的插件

    • Vite 拥有自己的插件生态系统,虽然不如 Webpack 丰富,但也提供了许多常用的插件。
    • 例如,vite-plugin-vue@vitejs/plugin-react 等。
  • 社区支持

    • Vite 拥有活跃的社区支持和文档,特别是在 Vue 和 React 项目中。
    • 适用于现代前端项目,特别是那些使用 ES Module 的项目。
5. 适用场景
  • 现代前端项目

    • 适合现代前端项目,特别是使用 ES Module 的项目。
    • Vue 和 React 项目在 Vite 中的开发体验非常好。
  • 快速启动

    • 适用于需要快速启动开发环境的项目,特别是在大型项目中。

总结

  • 初始构建速度

    • Webpack:初始构建较慢,适合大型和复杂的项目。
    • Vite:初始构建非常快,适合现代前端项目,尤其是在大型项目中。
  • 开发服务器性能

    • Webpack:使用增量构建和模块热替换(HMR),但可能较慢。
    • Vite:使用按需编译机制,启动和 HMR 非常快速。
  • 生产构建

    • Webpack:通过 Rollup 和多种优化机制,生成高效的代码。
    • Vite:使用 Rollup 进行构建,生成高效的代码,适用于现代前端项目。
  • 配置复杂度

    • Webpack:需要详细的配置文件,配置复杂。
    • Vite:提供零配置或简单配置,配置简单。
  • 适用项目规模

    • Webpack:适合大型和复杂的项目,支持多种文件类型和多入口。
    • Vite:适合现代前端项目,特别是那些使用 ES Module 的项目,适用于快速启动和简单配置的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/76200.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rac环境下,增加一个控制文件controlfile

先关闭节点二&#xff0c;在节点一上操作 1、查看控制文件个数和路径 SQL> show parameter control 2、备份参数文件 SQL> create pfile/home/oracle/orcl.pfile20250417 from spfile; 3、修改控制文件参数 SQL> alter system set contr…

git安装(windows)

通过网盘分享的文件&#xff1a;资料(1) 链接: https://pan.baidu.com/s/1MAenYzcQ436MlKbIYQidoQ 提取码: evu6 点击next 可修改安装路径 默认就行 一般从命令行调用&#xff0c;所以不用创建。 用vscode&#xff0c;所以这么选择。

Spring Boot整合难点?AI一键生成全流程解决方案

在当今的软件开发领域&#xff0c;Spring Boot 凭借其简化开发流程、快速搭建项目的优势&#xff0c;成为了众多开发者的首选框架。然而&#xff0c;Spring Boot 的整合过程并非一帆风顺&#xff0c;常常会遇到各种难点。而飞算 JavaAI 的出现&#xff0c;为解决这些问题提供了…

Python批量处理PDF图片详解(插入、压缩、提取、替换、分页、旋转、删除)

目录 一、概述 二、 使用工具 三、Python 在 PDF 中插入图片 3.1 插入图片到现有PDF 3.2 插入图片到新建PDF 3.3 批量插入多张图片到PDF 四、Python 提取 PDF 图片及其元数据 五、Python 替换 PDF 图片 5.1 使用图片替换图片 5.2 使用文字替换图片 六、Python 实现 …

山东大学软件学院创新项目实训开发日志(15)之中医知识问答历史对话查看bug处理后端信息响应成功但前端未获取到

在开发中医知识问答历史对话查看功能的时候&#xff0c;出现了前后端信息获取异同的问题&#xff0c;在经过非常非常非常艰难的查询之后终于解决了这一问题&#xff0c;而这一问题的罪魁祸首就是后端没有setter和getter方法&#xff01;&#xff01;&#xff01;&#xff01;&a…

Arkts应用全局UI状态存储和持久化V2(AppStorageV2、PersistenceV2和@Type)

目录 应用全局UI状态存储和持久化V2版本 AppStorageV2 connect remove keys 示例 使用限制 PersistenceV2 connect remove keys save notifyOnError 示例 使用限制 Type 使用限制 应用全局UI状态存储和持久化V2版本 以下实例AppStorageV2、PersistenceV2和装饰…

最大子序和问题——动态规划/贪心算法解决

目录 一&#xff1a;问题描述 二&#xff1a;解决思路1——动态规划思想 三&#xff1a;C 语言代码实现 四&#xff1a;复杂度分析 五&#xff1a;解决思路2——贪心算法思想 六&#xff1a;具体步骤 七: C语言代码实现 八&#xff1a;复杂度分析 一&#xff1a;问题描述 …

【Python入门】文件读取全攻略:5种常用格式(csv/excel/word/ppt/pdf)一键搞定 | 附完整代码示例

大家好&#xff0c;我是唐叔&#xff01;今天给大家带来一篇Python文件读取的终极指南。无论是数据分析、办公自动化还是爬虫开发&#xff0c;文件读取都是Python程序员必须掌握的核心技能。本文将详细介绍Python处理5大常用文件格式的方法&#xff0c;包含完整可运行的代码示例…

四、小白如何用Pygame制作一款跑酷类游戏(页面暂停和主角跑步动作的实现)

四、小白如何用Pygame制作一款跑酷类游戏&#xff08;页面暂停和主角跑步动作的实现&#xff09; 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 四、小白如何用Pygame制作一款跑酷类游戏&#xff08;页面暂停和主…

《基于 RNN 的股票预测模型代码优化:从重塑到直接可视化》

在深度学习领域&#xff0c;使用循环神经网络&#xff08;RNN&#xff09;进行股票价格预测是一个常见且具有挑战性的任务。本文将围绕一段基于 RNN 的股票预测代码的改动前后差别展开&#xff0c;深入剖析代码的优化思路和效果。 原始代码思路与问题 原始代码实现了一个完整…

Lambda 函数与 peek 操作的使用案例

Lambda 函数和 peek 操作是 Java 8 Stream API 中非常有用的特性&#xff0c;下面我将介绍它们的使用案例。 Lambda 函数使用案例 Lambda 表达式是 Java 8 引入的一种简洁的匿名函数表示方式。 集合操作 List<String> names Arrays.asList("Alice", "B…

Docker私有仓库页面访问实现

通过 docker run -d -p 5000:5000 --name registry registry:2 命令搭建的Docker私有仓库默认不提供网页访问界面。它是一个基于API的后端服务&#xff0c;主要用于镜像的存储和管理。但可以通过以下两种方式实现网页访问&#xff1a; 一、通过第三方Web UI工具扩展 1. 使用 D…

[王阳明代数讲义]语言模型核心代码调研

语言模型核心代码调研 基于Consciciteation‌的才气张量持续思考综述将文本生成建模为才气张量网络扩散过程&#xff0c;实现非自回归推理通过才气张量的群-拓扑流形交叉注意力实现多模态推理&#xff0c;将输入压缩到低维空间持续迭代提出「条件计算提前终止」机制&#xff0c…

flink jobmanager离奇的heap oom

文章目录 现象描述开始分析1.初步分析dump文件2.AI分析引用关系分析方向2.1 flink BlobServer bug分析方向2.2 和运行环境有关分析方向2.3 和任务有关 回到问题本身&#xff0c;思考一下1. seatunnel到底有没有问题2.再次分析zipfile对象3.分析seatunnel es connector 源码4 怀…

APP动态交互原型实例|墨刀变量控制+条件判断教程

引言 不同行业的产品经理在绘制原型图时&#xff0c;拥有不同的呈现方式。对于第三方软件技术服务公司的产品经理来说&#xff0c;高保真动态交互原型不仅可以在开发前验证交互逻辑&#xff0c;还能为甲方客户带来更直观、真实的体验。 本文第三部分将分享一个实战案例&#…

AI 驱动下的后端开发架构革命:从智能协同体系

AI 驱动下的后端开发架构革命&#xff1a;从智能协同体系 一、引言&#xff1a;AI 重构后端开发范式 在 2025 年的企业级技术演进中&#xff0c;人工智能正从辅助工具升级为核心架构要素。根据 Gartner《2025 智能技术栈成熟度报告》&#xff0c;传统 "人力编码 硬规则…

安卓基础(生命周期)

创建阶段&#xff1a;onCreate方法被调用&#xff0c;用于初始化 Activity&#xff0c;如设置布局等。启动阶段&#xff1a;依次调用onStart和onResume方法&#xff0c;让 Activity 变得可见并可与用户交互。暂停与恢复阶段&#xff1a;当 Activity 失去焦点但可见时&#xff0…

Uniapp: 下拉选择框 ba-tree-picker

目录 1、效果展示2、如何使用2.1 插件市场2.2 引入插件 3、参数配置3.1 属性3.2 方法 4、遇见的问题4.1、设置下拉树的样式 1、效果展示 2、如何使用 2.1 插件市场 首先从插件市场中将插件导入到项目中 2.2 引入插件 在使用的页面引入插件 <view click"showPicke…

Spring Boot实战:基于策略模式+代理模式手写幂等性注解组件

一、为什么需要幂等性&#xff1f; 核心定义&#xff1a;在分布式系统中&#xff0c;一个操作无论执行一次还是多次&#xff0c;最终结果都保持一致。 典型场景&#xff1a; 用户重复点击提交按钮网络抖动导致的请求重试消息队列的重复消费支付系统的回调通知 不处理幂等的风…

如何恢复极狐GitLab?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 恢复极狐GitLab (BASIC SELF) 极狐GitLab 提供了一个命令行界面来恢复整个安装&#xff0c;足够灵活以满足您的需求。 恢复…