webpack與vite
- 一、了解 webpack
- 入口(entry)
- 輸出(output)
- loader
- 插件(plugin)
- 模式(mode)
- 二、項目中使用webpack
- vue項目
- react項目
- 三、了解vite
- 構建選項(build)
- 模塊解析(Resolve)
- 模塊處理(Module)
- 服務器選項(Dev Server)
- 依賴優化選項(Optimization)
- 插件 (Plugins)
- 公共路徑配置(Base)
- 四、項目中使用vite
- 五、關于webpack與vite的面試題
- 1.webpack 執行原理?
- 2.為什么 Vite 速度? Webpack 快?
- 3.vite構建項目 開發環境和生成環境有什么區別?
- 4.vite 底層原理?
一、了解 webpack
本質上,webpack 是一個用于現代 JavaScript 應用程序的 靜態模塊打包工具。
入口(entry)
入口起點(entry point) 指示 webpack 應該使用哪個模塊,來作為構建其內部 依賴圖(dependency graph) 的開始。進入入口起點后,webpack 會找出有哪些模塊和庫是入口起點(直接和間接)依賴的。
默認值是 ./src/index.js
,但你可以通過在 webpack configuration 中配置 entry 屬性,來指定一個(或多個)不同的入口起點。
module.exports = {entry: './path/to/my/entry/file.js',};
輸出(output)
output 屬性告訴 webpack 在哪里輸出它所創建的 bundle,以及如何命名這些文件。主要輸出文件的默認值是 ./dist/main.js
,其他生成文件默認放置在 ./dist
文件夾中。
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 只能理解 JavaScript 和 JSON 文件,這是 webpack 開箱可用的自帶能力。loader 讓 webpack 能夠去處理其他類型的文件,并將它們轉換為有效 模塊,以供應用程序使用,以及被添加到依賴圖中。
在更高層面,在 webpack 的配置中,loader 有兩個屬性:
test 屬性,識別出哪些文件會被轉換。
use 屬性,定義出在進行轉換時,應該使用哪個 loader。
const path = require('path');module.exports = {output: {filename: 'my-first-webpack.bundle.js',},module: {rules: [{ test: /\.txt$/, use: 'raw-loader' }],},
};
插件(plugin)
loader 用于轉換某些類型的模塊,而插件則可以用于執行范圍更廣的任務。包括:打包優化,資源管理,注入環境變量。
想要使用一個插件,你只需要 require()
它,然后把它添加到 plugins
數組中。多數插件可以通過選項(option)自定義。你也可以在一個配置文件中因為不同目的而多次使用同一個插件,這時需要通過使用 new 操作符來創建一個插件實例。
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 用于訪問內置插件module.exports = {module: {rules: [{ test: /\.txt$/, use: 'raw-loader' }],},plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};
在上面的示例中,html-webpack-plugin 為應用程序生成一個 HTML 文件,并自動將生成的所有 bundle 注入到此文件中。
模式(mode)
通過選擇 development, production 或 none 之中的一個,來設置 mode 參數,你可以啟用 webpack 內置在相應環境下的優化。其默認值為 production
。
module.exports = {mode: 'production',
};
參考官網webpack
二、項目中使用webpack
vue項目
在vue項目中一般會新建一個vue.config.js 進行擴展配置(當然也可以手動創建 webpack.config.js 并配置)
// vue.config.js
module.exports = {// 入口文件配置(默認是 src/main.js)pages: {index: {entry: 'src/main.js', // 主入口template: 'public/index.html',filename: 'index.html'}// 多頁面配置:可添加其他頁面入口// subpage: { entry: 'src/subpage/main.js', ... }},// 其他常用配置outputDir: 'dist', // 打包輸出目錄publicPath: process.env.NODE_ENV === 'production' ? '/prod-path/' : '/', // 公共路徑devServer: {port: 8080, // 開發服務器端口open: true, // 自動打開瀏覽器proxy: { // 接口代理(解決跨域)'/api': {target: 'http://api.example.com',changeOrigin: true,pathRewrite: { '^/api': '' }}},// 鏈式修改 Webpack 配置(通過 webpack-chain)chainWebpack: config => {// 添加別名config.resolve.alias.set('@', path.resolve(__dirname, 'src')).set('components', path.resolve(__dirname, 'src/components'));// 修改圖片加載規則config.module.rule('images').use('url-loader').tap(options => ({limit: 10240, // 小于10kb的圖片轉為base64name: 'img/[name].[hash:8].[ext]'}));},// 直接修改 Webpack 配置(合并方式)configureWebpack: {plugins: [// 添加自定義插件],optimization: {// 配置代碼分割等}}}
};
react項目
創建 webpack.config.js 并配置
修改 package.json
"scripts": {"start": "webpack serve --mode development","build": "webpack --mode production"
}
三、了解vite
Vite 憑借基于原生 ESM 的開發服務器實現極速啟動與熱更新
,同時通過 Rollup
優化生產構建,兼具簡潔配置與強大擴展性,為前端開發提供高效流暢的體驗。
構建選項(build)
通過 build 配置項控制生產環境打包輸入與輸出
export default {build: {outDir: 'dist', // 輸出目錄assetsDir: 'assets', // 靜態資源存放目錄assetsInlineLimit: 4096, // 小于此值的資源將內聯為 base64//sourcemap: false, // 是否生成 sourcemapminify: env.VITE_APP_ENV == 'prod' ? 'terser' : 'esbuild', //開發、測試環境使用esbuild,它比 terser 快 20-40 倍,壓縮率只差 1%-2%;生產環境使用terserrollupOptions: { // 傳遞給 Rollup 的輸出配置output: {chunkFileNames: 'js/[name]-[hash].js', // 用于命名代碼拆分時創建的共享塊的輸出命名entryFileNames: 'js/[name]-[hash].js', // 用于從入口點創建的塊的打包輸出格式[name]表示文件名,[hash]表示該文件內容hash值assetFileNames: "[ext]/[name].[hash].[ext]", // 用于輸出靜態資源的命名,[ext]表示文件擴展名}},lib: { //打包為庫文件entry: 'src/index.js',name: 'MyLibrary',formats: ['es', 'umd'],fileName: (format) => `my-lib.${format}.js` // 輸出文件的名稱}}
}
模塊解析(Resolve)
配置模塊查找規則和路徑別名
import { resolve } from "path"; // 主要用于alias文件路徑別名
function pathResolve (dir) {return resolve(__dirname, ".", dir);
}
export default {resolve: {alias: { // 路徑別名"@": pathResolve("src"),"@scss": pathResolve("src/assets/scss"),"@img": pathResolve("src/assets/img"), "@com": pathResolve("src/components"),'@config': pathResolve('src/config') },extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'], // 導入時想要省略的擴展名列表}
}
模塊處理(Module)
CSS 處理:內置支持 CSS、CSS Modules 及預處理器
export default {css: {modules: { // CSS Modules 配置scopeBehaviour: 'local',localsConvention: 'camelCaseOnly'},preprocessorOptions: { // 預處理器配置scss: {additionalData: `@import "./src/styles/vars.scss";`}},devSourcemap: true // 開發環境 CSS sourcemap}
}
服務器選項(Dev Server)
提供快速的開發環境服務
export default {server: {port: 8080, // 端口號open: true, // 自動打開瀏覽器proxy: { // 接口代理配置'/api': {target: 'http://localhost:8080',changeOrigin: true,rewrite: path => path.replace(/^\/api/, '')}},hmr: true, // 開啟熱更新cors: true, // 允許跨域請求host: '0.0.0.0' // 指定服務器應該監聽哪個 IP 地址,如果設置為 0.0.0.0 或者 true 將監聽所有地址,包括局域網和公網地址。 }
}
依賴優化選項(Optimization)
依賴預構建提升開發性能
export default {optimizeDeps: {include: ['lodash-es', 'axios'], // 強制預構建的依賴exclude: ['custom-package'], // 不預構建的依賴esbuildOptions: { // esbuild 配置target: ['es2020', 'edge88']}}
}
插件 (Plugins)
Vite 可以使用插件進行擴展,這得益于 Rollup 優秀的插件接口設計和一部分 Vite 獨有的額外選項。
import vue from '@vitejs/plugin-vue'
import react from '@vitejs/plugin-react'
import AutoImport from "unplugin-auto-import/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";export default {plugins: [vue(), // Vue 支持// react(), // React 支持AutoImport({ // 自動導入 Vue 相關函數,如:ref, reactive, toRef 等imports: ["vue"],extensions: ["vue", "md"],include: [/\.vue$/, /\.vue\?vue/, /\.md$/], resolvers: [ElementPlusResolver()],}),]
}
具體插件可以看這里
插件
公共路徑配置(Base)
開發或生產環境服務的公共基礎路徑。
export default {base: process.env.NODE_ENV === 'production' ? '/app/' : '/'
}
參考vite中文網
四、項目中使用vite
import { defineConfig } from 'vite'// import vue from '@vitejs/plugin-vue'
// import react from '@vitejs/plugin-react'
function pathResolve (dir) {return resolve(__dirname, ".", dir);
}
export default defineConfig({// 根據框架類型啟用// plugins: [vue()], // Vue 項目啟用// plugins: [react()], // React 項目啟用// 項目基礎路徑base: '/',server: {port: 8080, // 開發端口open: false, // 自動打開瀏覽器hot: true, // 啟用熱更新host: env.VITE_APP_HOST, // 指定服務器應該監聽哪個 IP 地址,如果設置為 0.0.0.0 或者 true 將監聽所有地址,包括局域網和公網地址。 proxy: { // 接口代理(解決跨域)'/api': {target: 'http://localhost:8080',changeOrigin: true,rewrite: (path) => path.replace(/^\/api/, '')}}},build: {outDir: 'dist', // 輸出目錄assetsDir: 'assets',// 靜態資源目錄sourcemap: false, // 不生成 sourcemap(生產環境) rollupOptions: {output: {// 靜態資源分類輸出assetFileNames: '[ext]/[name]-[hash].[ext]',chunkFileNames: 'js/[name]-[hash].js',entryFileNames: 'js/[name]-[hash].js'}}},resolve: {alias: {'@': pathResolve('src'), 'components': pathResolve('src/components'),'@scss': pathResolve('src/assets/scss')},extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue', '.json'] // 導入時想要省略的擴展名列表},css: {devSourcemap: true, // 開發環境啟用 CSS sourcemapmodules: {// CSS Modules 基礎配置scopeBehaviour: 'local'}},
})
五、關于webpack與vite的面試題
1.webpack 執行原理?
從入口模塊出發,遞歸解析所有依賴模塊并構建依賴關系圖,然后將這些模塊按一定規則打包成一個或多個瀏覽器可識別的輸出文件,整個過程包括解析、編譯轉換、代碼拆分、優化等步驟,最終生成優化后的靜態資源。
參考官網Under The Hood
2.為什么 Vite 速度? Webpack 快?
- 開發模式的差異
在開發環境中, Webpack 是先打包再啟動開發服務器,? Vite 則是直接啟動,然后再按需編譯
依賴?件。(可以啟動項?后檢查源碼 Sources 那?看到)
這意味著,當使? Webpack 時,所有的模塊都需要在開發前進?打包,這會增加啟動時間和構建時
間。
? Vite 則采?了不同的策略,它會在請求模塊時再進?實時編譯,這種按需動態編譯的模式極?地縮短了編譯時間,特別是在?型項?中,?件數量眾多, Vite 的優勢更為明顯。 - 對ES Modules的?持
現代瀏覽器本?就?持 ES Modules ,會 主動發起 請求去獲取所需?件。Vite充分利?了這?點,
將開發環境下的模塊?件直接作為瀏覽器要執?的?件,?不是像 Webpack 那樣 先打包 ,再交給瀏
覽器執?。這種?式減少了中間環節,提?了效率。
什么是ES Modules?
通過使? export 和 import 語句,ES Modules 允許在瀏覽器端導?和導出模塊。
當使? ES Modules 進?開發時,開發者實際上是在構建?個 依賴關系圖 ,不同依賴項之間通過導?
語句進?關聯。
主流瀏覽器(除IE外)均?持ES Modules,并且可以通過在 script 標簽中設置 type=“module” 來
加載模塊。默認情況下,模塊會延遲加載,執?時機在?檔解析之后,觸發DOMContentLoaded事件前。 - 底層語?的差異
Webpack 是基于Node.js
構建的,? Vite 則是基于esbuild
進?預構建依賴。esbuild
是采
?Go
語?編寫的,Go 語?是納秒
級別的,? Node.js 是毫秒
級別的。因此,Vite 在打包速度上
相?Webpack 有 10-100 倍的提升。
什么是預構建依賴?
預構建依賴通常指的是在項? 啟動或構建 之前,對項?中所需的依賴項進?預先的 處理或構建 。這
樣做的好處在于,當項?實際運?時,可以 直接使? 這些已經預構建好的依賴,??需再進?實時的編譯或構建,從?提?了應?程序的運?速度和效率。 - 熱更新的處理
在 Webpack 中,當?個模塊或其依賴的模塊內容改變時,熱更新是基于?件級別的,需要重新構建并刷新整個??。
在 Vite 中,當某個模塊內容改變時,只需要讓瀏覽器重新請求該模塊即可,不需要刷新整個??,這??減少了熱更新的時間。
總結
總的來說,Vite 之所以? Webpack 快,主要是因為它采?了 不同的開發模式 、 充分利?了現代瀏覽器的 ES Modules ?持 、 使?了更?效的底層語?, 并優化了熱更新的處理 。這些特點使得Vite在?型項?中具有顯著的優勢,能夠快速啟動和構建,提?開發效率。
3.vite構建項目 開發環境和生成環境有什么區別?
開發環境:基于瀏覽器原生 esbuild 模塊運行,無需預打包,通過開發服務器實時響應請求并處理依賴,實現毫秒級啟動和即時熱更新(HMR),優先保證開發效率。
生產環境:使用 Rollup 進行預打包,會對代碼進行壓縮、分割、 tree-shaking 等優化,生成高度優化的靜態資源,優先保證輸出產物的性能和體積。
esbuild ?于開發服務器階段,通過實時編譯和提供模塊來實現快速的冷啟動和熱模塊替換。? Rollup ?于?產構建階段,將源代碼打包為最終可發布的?件,以?于部署到?產環境。
- esbuild: esbuild 是?個快速、可擴展的 JavaScript 打包器,它被?作 Vite 的默認構建?具。
esbuild 的主要任務是將源代碼轉換為瀏覽器可以理解的代碼,同時還?持壓縮、代碼分割、按需
加載等功能。esbuild 利?其?性能的構建能?,實現了快速的開發服務器和熱模塊替換。 - Rollup: Rollup 是?個 JavaScript 模塊打包?具,也是 Vite 的另?個基礎依賴。在 Vite 中,
Rollup 主要?于?產構建階段。它通過靜態分析模塊依賴關系,將多個模塊打包為?個或多個最終
的輸出?件。Rollup ?持多種輸出格式,如 ES 模塊、CommonJS、UMD 等,可以根據項?的需要進?配置。
4.vite 底層原理?
- ES 模塊:Vite 使?了 ES 模塊來管理和加載模塊。ES 模塊是 JavaScript 的標準模塊系統,相?于
傳統的 CommonJS 或 AMD,ES 模塊具有更好的靜態分析能?和更?的性能。Vite 通過使?瀏覽器原?的 ES 模塊加載器,可以實現按需加載和快速構建。 - HTTP/2:Vite 借助于現代瀏覽器的 HTTP/2 ?持來實現更?效的資源加載。HTTP/2 ?持多路復?,可以同時請求多個資源,避免了傳統的 HTTP/1 中的隊頭阻塞問題,加快了資源加載速度。
- 編譯器:Vite 使?了?定義的編譯器來處理開發時的模塊解析和轉換。它能夠識別模塊的依賴關
系,并將模塊轉換為瀏覽器可直接執?的代碼。Vite 的編譯器?持熱模塊替換(HMR),可以在代碼修改時?動更新瀏覽器中的??,提?開發效率。 - 中間件:Vite 使?了基于 Koa 框架的中間件來處理開發服務器。通過中間件,Vite 可以攔截和處理
開發時的 HTTP 請求,并根據請求的路徑返回相應的模塊?件。中間件還可以處理各種開發時的特殊需求,如代理 API 請求、路由轉發等。
Things you said