浅谈vite和webpack的性能优化和区别
性能优化概述
1.分包策略
Vite和Webpack都支持性能优化-分包策略,下面简要介绍一下它们的实现方法:
Vite分包策略
Vite是一款基于ESM的构建工具,Vite的分包策略主要通过动态引入实现,可以自动进行代码拆分,实现按需加载和运行时优化。在Javascript中,可以使用ES6的import()语法来实现动态引入:
const module = import('./module.js');
Vite还支持使用预构建Chunk来优化加载速度,可以在vite.config.js文件中设置rollupOptions项来实现预构建Chunk:
module.exports = { build: { rollupOptions: { output: { manualChunks: { react: ['react', 'react-dom'] } } } } };
除了动态引入和预构建Chunk,Vite还支持手动配置Chunk,以实现更细粒度的控制。可以使用 import.meta.glob() 函数来匹配文件对 Chunk 进行手动配置。
import.meta.glob('../components/*.js').then(modules => { Promise.all(modules.values()).then(components => { // ... }) })
Webpack分包策略
Webpack可以使用以下方式实现分包策略:
- 使用代码分割插件(Model Splitting)
通过代码分割插件在构建过程中实现自动化的代码分割。
const path = require('path'); module.exports = { entry: { app: './src/app.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js' }, optimization: { splitChunks: { chunks: 'all' } } };
- 使用动态导入(Dynamic Imports)
通过动态导入将代码拆分成多个小块,按需加载。
import('./module.js') .then((module) => { // ... }) .catch((err) => { // ... });
Webpack还支持使用webpackPrefetch和webpackPreload来实现预加载预取的功能,提高用户体验。
// webpackPreload const Component = () => import(/* webpackPreload: true */ './Component.js'); // webpackPrefetch const Component = () => import(/* webpackPrefetch: true */ './Component.js');
以上就是Vite和Webpack的分包策略实现方法和代码示例。
2.gzip压缩
Vite和Webpack都提供了Gzip压缩的功能,以便在前端性能优化中使用。
在Vite中,可以通过在vite.config.js中设置compress参数来开启Gzip压缩:
// vite.config.js export default { server: { compress: true } }
在Webpack中,可以通过在webpack.config.js中配置CompressionPlugin插件来开启Gzip压缩:
const CompressionPlugin = require('compression-webpack-plugin'); module.exports = { plugins: [ new CompressionPlugin({ algorithm: 'gzip' }) ] };
这些配置将为我们自动压缩生成的文件,并在传输到客户端时解压文件以提高性能。
值得注意的是,由于Gzip压缩需要花费一些CPU时间,建议在服务器端启用压缩。如果你正在使用CDN,你也可以在CDN端配置Gzip压缩。
3.动态引入
Webpack和Vite都支持使用动态引入来提高前端性能。动态引入的主要作用是延迟加载,只在需要的时候才加载相关的模块,减少了首次加载时的负担。
在Vite中,可以实现动态引入的几种方式:
使用ES6动态导入语法
import('./path/to/module').then(result => { // do something with the module }).catch(error => { // handle error });
这将以异步方式加载模块,可以在需要时动态引入。
在组件的setup函数中使用异步加载
import { defineComponent, ref, onMounted } from 'vue'; export default defineComponent({ setup() { const moduleRef = ref(null); onMounted(async () => { const result = await import('./path/to/module'); moduleRef.value = result; }); return { moduleRef, }; }, });
这种方式使用了Vue 3中的setup函数,使用Promise来异步加载模块,并将结果存储在ref中。
使用异步组件
const AsyncComponent = defineAsyncComponent(() => import('./path/to/module')); export default defineComponent({ components: { AsyncComponent, }, template: `<AsyncComponent />`, });
这里使用了Vue 3中的defineAsyncComponent函数,通过传入异步加载模块的路径来创建异步组件。这样组件的加载过程将会被延迟到当组件被使用时再进行。
需要注意的是,为了使动态引入能够真正发挥作用,还需要配置Vite的按需动态导入功能。在vite.config.js文件中,可以通过设置rollupOptions参数来开启此功能:
// vite.config.js export default { rollupOptions: { output: { manualChunks: {}, }, }, };
此配置将分离每个动态导入的文件,并生成一个独立的代码块。这样可以按需加载模块,从而提高性能。
在Webpack中,可以实现动态引入的几种方式:
使用ES6动态导入语法
import('./path/to/module').then(result => { // do something with the module }).catch(error => { // handle error });
这将以异步方式加载模块,可以在需要时动态引入。
在React懒加载组件中使用
const MyComponent = lazy(() => import('./path/to/module'));
使用了React.lazy()函数来实现懒加载。此函数接受一个返回动态加载模块的import()函数的参数。
使用webpack的内置require.ensure()
require.ensure(['./path/to/module'], function (require) { var result = require('./path/to/module'); // do something with the module });
这种方式使用了webpack的内置函数require.ensure(),可以将块(chunk)分离出来并延迟加载模块。
在使用动态引入时,还可以通过配置webpack的output.publicPath属性,将异步块的基础路径设置为CDN地址,以加快异步加载速度。例如:
output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', publicPath: 'https://cdn.example.com/' }
需要注意的是,在使用动态引入时,还需要配置webpack的代码分离和优化功能。可以通过在webpack.config.js文件中设置optimization.splitChunks来实现此目的:
optimization: { splitChunks: { chunks: 'async', minSize: 20000, maxSize: 0, minChunks: 1, maxAsyncRequests: 30, maxInitialRequests: 30, enforceSizeThreshold: 50000, cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, },
这样,webpack会自动分离出符合条件的模块,生成独立的代码块,在需要时进行加载。
值得注意的是,动态引入虽然可以优化首次加载时间,但在使用多个包时可能会导致过多的HTTP请求,这可能导致首屏渲染延迟。因此,需要根据实际情况选择何时使用动态引入。
补充:
为了避免这些问题,并且进一步提高性能,可以采用以下一些方法:
预加载和预取。在Webpack中,可以使用webpackPrefetch和webpackPreload注释,以启用自动预取和/或预加载。例如:
import(/* webpackPrefetch: true */ './path/to/module');
这将告诉浏览器提前下载此模块,以便在需要时立即加载。
按用户需求加载。如果你有一些模块是高频访问的,那么可以在页面加载时先加载这些模块,而将其他模块延迟加载。这样可以防止不必要的HTTP请求,并加快页面响应速度。
避免过多的动态引入。虽然动态引入可以解决代码分离的问题,但是如果不加以控制,也可能导致模块的数量过于庞大,进而导致过多的HTTP请求和降低性能的可能。因此,在使用动态引入时,必须注意模块数量的把握,避免过度动态引入。
4.CDN加速
Vite和Webpack都支持使用CDN加速来优化前端性能。使用CDN可以将静态资源放置在离用户更近、更容易访问的地方,这样可以减少网络延迟,加快资源加载速度。
在Vite中,可以通过以下方式来使用CDN资源加速:
在 vite.config.js 文件中设置 base 属性
export default { base: 'https://cdn.example.com/', // ... }
设置 base 属性后,资源的 baseURL 将会被设置为此处的值,JavaScript、CSS、图片等静态资源都将从这个地址加载。
在 index.html 文件中手动引入 CDN 资源
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My App</title> <link rel="stylesheet" href="https://cdn.example.com/path/to/main.css" rel="external nofollow" > </head> <body> <div id="app"></div> <script type="module" src="/src/main.js"></script> </body> </html>
这种方式可以手动指定要加载的静态资源,并从CDN加载,但需要注意的是,这种方式可能会增加HTML文件的大小和复杂度。
在 vite.config.js 文件中使用 CDN 插件
import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { VitePluginCdn } from 'vite-plugin-cdn'; export default defineConfig({ plugins: [ vue(), VitePluginCdn({ modules:[ { name: 'vue', var: 'Vue', path: 'vue/dist/vue.min.js' }, { name: 'vue-router', var: 'VueRouter', path: 'vue-router/dist/vue-router.min.js' }, { name: 'chart.js', var: 'Chart', path: 'chart.js/dist/Chart.min.js' } ], prodUrl: 'https://cdn.example.com/{{module}}/{{version}}/{{path}}', // 以下配置可以是 CDN 来加速引入的资源。 // 必须是数组形式,且选项都必须包含 `test` 和 `method` 属性。 // 具体可选项请参考 `preload-webpack-plugin` 的 `include` 参数。 allowList: [ { test: /bootstrap-vue/(.*?).(js|css|woff|woff2|ttf|svg|png|jpe?g|gif)$/, method: 'GET', //可选的扩展加载,vue使用 ext: 'js' } ] }) ] })
使用 vite-plugin-cdn 插件可以方便地自动将指定的模块从CDN加载。需要注意的是,这个插件需要按照指定规则的方式来定义模块和版本。具体用法可以参考 vite-plugin-cdn 的官方文档。
以上这些方法都可以实现CDN资源加速,根据实际使用场景可以灵活选择。
在Webpack中,可以通过以下方式来使用CDN资源加速:
使用 HtmlWebpackPlugin 插件
在 webpack.config.js 文件中使用 HtmlWebpackPlugin 插件,在 template 配置中引入CDN地址
const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // ... plugins: [ new HtmlWebpackPlugin({ template: 'public/index.html', cdn: { js: [ 'https://cdn.example.com/jquery.min.js', 'https://cdn.example.com/bootstrap.min.js' ], css: [ 'https://cdn.example.com/bootstrap.min.css' ] } }) ], // ... };
在 HTML 模板文件中,将 js 和 css 链接插入到模板中:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My App</title> <% for (var i in htmlWebpackPlugin.options.cdn.css) { %> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="external nofollow" rel="stylesheet"> <% } %> </head> <body> <div id="app"></div> <% for (var i in htmlWebpackPlugin.options.cdn.js) { %> <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> <% } %> </body> </html>
这种方式可以将静态资源链接插入到运行 HTML 模板源文件中,以指定CDN地址加载。
在 output.publicPath 中设置 CDN 地址
在 webpack.config.js 文件中设置 output.publicPath 属性:
module.exports = { output: { publicPath: 'https://cdn.example.com/', }, // ... }
这样设置后,通过Webpack打包后的静态资源将从指定的CDN地址加载,比如JS、CSS、图片等静态资源。
以上这些方法都可以实现CDN资源加速,根据实际使用场景可以灵活选择。
vite和webpack的区别
1. 开发模式下的运行方式不同
Vite在开发模式下使用 Rollup 进行打包,并提供了一个内置的 HTTP 服务器来提供服务。它使用 ES modules 作为默认的模块系统,可以快速地进行热更新和快速构建。
Webpack在开发模式下使用自己的开发服务器进行工作,支持热更新,但通常需要使用一些插件来实现一些高级功能,如HMR(热模块替换)。
以下是一个使用Vite的示例代码,index.html 文件中直接引用模块,浏览器通过 Vite 内置的 HTTP 服务器加载模块:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My App</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.js"></script> </body> </html>
以下是一个使用Webpack的示例代码,webpack-dev-server通过监听文件变化来触发热更新:
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'development', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'main.js', }, devServer: { contentBase: './dist', hot: true, }, plugins: [ new HtmlWebpackPlugin({ title: 'My App', }), ], };
2. 构建方式和性能
Vite在开发模式下使用Rollup进行构建,支持按需编译和充分利用现代浏览器的原生ES模块,所以它的速度更快,比如热刷新延时更短、构建速度更快等。但在实际项目中,如需要自定义构建方式和高级功能的话,需要对Rollup的运行机制有一定的了解。
Webpack基于模块化思想和依赖分析,在生产模式下可以更好地实现代码压缩、分离、图片压缩等复杂的构建操作。同时Webpack还内置了一些优化策略,如启用多线程并发构建、使用Tree shaking技术等,因此Webpack在处理大型项目时更具优势。
以下是一个使用Vite的示例代码,build 命令会通过 Rollup 进行构建:
// vite.config.js export default { build: { outDir: 'dist', assetsDir: 'assets', rollupOptions: { input: 'src/main.js', }, }, }
以下是一个使用Webpack的示例代码,npm run build 命令会通过 Webpack 进行构建:
// webpack.config.js const path = require('path'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { mode: 'production', entry: './src/index.js', output: { filename: 'main.js', path: path.resolve(__dirname, 'dist'), }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: 'My App', }), ], };
3. 配置方式
Vite使用ES modules进行导入和导出,而配置文件也是一个ES module,可以直接使用ES6语法,简易直观。此外,Vite还提供了一个内置的插件管理系统和一些现成的插件,方便用户管理和使用。
Webpack使用CommonJS方式来导入和导出模块,配置文件是一个CommonJS模块,使用的是Node.js的API,需要一定的配置经验,但也更加灵活,可以满足
4. 支持的语言
Vite除了支持JavaScript和CSS,还支持以.vue文件为代表的单文件组件,这种组件可以将HTML、CSS和JavaScript打包到一个文件中。Vue.js等框架也积极支持Vite,称其是其未来的构建工具。
Webpack虽然可以支持JavaScript和CSS,但是它的打包方式更加灵活,支持Sass、Less等CSS预处理器,同时也可以使用Babel来支持ES6以上的JavaScript语法。
以下是一个使用Vite的示例代码,.vue文件包含HTML、CSS和JavaScript等三种代码:
<template> <div> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'HelloWorld', data() { return { msg: 'Welcome to Your Vue.js App - Vite', } }, } </script> <style> h1 { color: #00f; } </style>
以下是一个使用Webpack的示例代码,.scss文件包含CSS代码和变量:
$primary-color: #00f; body { background-color: lighten($primary-color, 50%); color: darken($primary-color, 30%); }
5. 插件生态和拓展性
Webpack的插件生态很丰富,提供了很多社区开发的插件,可以满足各种需求,可以针对性的选择安装,非常方便。同时Webpack还支持自定义插件,可以非常灵活地拓展其功能。
Vite的插件生态相对较少,但其特有的打包方式和内置的插件系统可以对项目开发提供很好的支持。Vite的开发团队也计划在未来增加更多的插件,支持更多浏览器和应用场景。
到此这篇关于浅谈vite和webpack的性能优化和区别的文章就介绍到这了,更多相关vite和webpack区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
vue使用element-resize-detector监听元素宽度变化方式
这篇文章主要介绍了vue使用element-resize-detector监听元素宽度变化方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-12-12Vue3新特性Suspense和Teleport应用场景分析
本文介绍了Vue2和Vue3中的Suspense用于处理异步请求的加载提示,以及如何在组件间实现动态加载,同时,Teleport技术展示了如何在DOM中灵活地控制组件的渲染位置,解决布局问题,感兴趣的朋友跟随小编一起看看吧2024-07-07Vue局部组件数据共享Vue.observable()的使用
随着组件的细化,就会遇到多组件状态共享的情况,今天我们介绍的是 vue.js 2.6 新增加的 Observable API ,通过使用这个 api 我们可以应对一些简单的跨组件数据状态共享的情况,感兴趣的可以了解一下2021-06-06vue.js分页中单击页码更换页面内容的方法(配合spring springmvc)
下面小编就为大家分享一篇vue.js分页中单击页码更换页面内容的方法(配合spring springmvc),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2018-02-02
最新评论