前端工程化之手搓webpack5 --【elpis全棧項目】

前端工程化之手搓webpack5 --【elpis全棧項目】

導讀


?
基本流程:輸入 – 編譯 – 輸出

被引擎讀取
打包
輸入--業務文件:pages
編譯--引擎編譯
輸出--產物文件:dist

?
我們要做的就是:

  1. 配置引擎自動讀取業務文件夾pages(比如一些xxx.vue文件);
  2. 對業務代碼進行編譯、分包、壓縮等操作;
  3. 得到一個dist文件夾(包含html\css\js等)

最后將dist部署到服務器就行了,這應該是任何一個工程化工具實現的最基本邏輯了吧。

所以,以webpack為例我們有必要認識一些基本配置屬性:
在這里插入圖片描述
?
以我的項目為例,我們來一步步配置出一個適合自己的webpack腳手架。以下是目錄:

以下目錄都在app文件夾下:|-- pages 				業務文件夾: 存放vue等文件
|-- public				產出文件夾: 打包后輸出的dist文件會生成在這里
|-- webpack				|-- config			webpack不同環境配置|-- webpack.base.js|-- webapck.dev.js|-- webapck.prod.js|-- dev.js      	啟動 開發 環境的的入口文件|-- prod.js			啟動 生產 環境的的入口文件
  • 這是我的pages文件夾,用以實現一個項目多頁面入口;(這個js就簡單的認為他是個一般的SPA項目的mian.js
    ? 在這里插入圖片描述
  • 最后prod環境要實現這樣一個效果:將代碼分割、分包、壓縮、提取公共方法、樹搖…等等。在這里插入圖片描述
  • dev環境要實現這樣一個效果:本地起一個服務,將dist放到本地的服務器上、實現HRM(熱更新)在這里插入圖片描述

?

一、 基本配置: webpack.base.js


我們將公共配置,集中提取放置到這個base文件中,避免重復配置。
基本思路:

  1. entry:配置入口文件的路徑
const pageEntries = {};
// 生成一個絕對路徑,例如:/user/elpis/app/pages/**/entry.*.js
const entryList = path.resolve(process.cwd(), './app/pages/**/entry.*.js');
// glob.sync是一個同步方法,會返回一個包含所有匹配文件路徑的數組。
glob.sync(entryList).forEach(file => {// file會輸出:'/user/elpis/app/pages/page1/entry.page1.js'const entryName = path.basename(file, '.js');  // 會提取文件名并去掉 .js, 例如:entry.page1pageEntries[entryName] = file;
})module.exports = {// entry: {entry.page1: '/user/elpis/app/pages/page1/entry.page1.js', ...}entry: pageEntries  
}
  1. module:規定不同的文件,分別需要用什么loader去解析。用test屬性配置文件的匹配規則;用include指定范圍;用use指定使用哪個loaderoptions則是對loader的配置。
 module.exports ={...module: {rules: [{test: /\.css$/,use: ['style-loader', 'css-loader']},{test: /\.js$/,include: [ path.resolve(process.cwd(), '/app/pages')], // 只對業務代碼進行babel,加快打包速度use: { loader: 'babel-loader' }},{test: /\.(png|jpe?g|gif)(\?.+)?$/,use: { loader: 'url-loader',options: {limit: 300,  esMoule: false }   // 小于300kb的圖片會被轉成base64編碼、禁用esModule}}]}...}
  1. resolve: 配置一些解析時候的具體行為,是個優化項,看個人需要配置。例如
module.exports ={...resolve: {// 定義別名,方便引入業務代碼: import { xxx } from '$common/xxx';alias: { $common: path.resolve(process.cwd(), './app/pages/common') }}...
}
  1. plugins: 使用插件。
module.exports ={...plugins: [new VueLoaderPlugin()  // 處理 .vue 文件,這個插件是必須的...]...
}
  1. optimization: 輸出優化。代碼分割,模塊分割,緩存,treeShaing,壓縮等優化策略
module.exports ={...optimization: {splitChunks:{...}, // 代碼分割, 具體的看下文runtimeChunk: true 	// 將 webpack 運行時生成的代碼打包到 runtime.js}...
}

由此我們得到了一個完整的 base.js 的配置:

const glob = require('glob')
const path = require('path')
const webpack = require('webpack')
const { VueLoaderPlugin } = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')const pageEntries = {};
const htmlWebpackPluginList = [];// 獲取 app/pages 目錄下的所有頁面入口文件(entry.xx.js)
const entryList = path.resolve(process.cwd(), './app/pages/**/entry.*.js');
glob.sync(entryList).forEach(file => {const entryName = path.basename(file, '.js');// 構造 entrypageEntries[entryName] = file;// 構造最終渲染的頁面文件htmlWebpackPluginList.push(new HtmlWebpackPlugin({// 產物最終模版filename: path.resolve(process.cwd(), './app/public/dist/', `${entryName}.tpl`),// 指定模版文件template: path.resolve(process.cwd(), './app/view/entry.tpl'),// 要注入的代碼塊chunks: [entryName]}))
})/*** webpack 基礎配置*/
module.exports = {// 入口配置entry: pageEntries,// 模塊解析配置module: {rules: [{test: /\.vue$/,use: {loader: 'vue-loader'}},{test: /\.js$/,include: [path.resolve(process.cwd(), '/app/pages') // 只對業務代碼進行babel,加快打包速度],use: {loader: 'babel-loader'}},{test: /\.(png|jpe?g|gif)(\?.+)?$/,use: {loader: 'url-loader',options: {limit: 300, // 小于300kb的圖片會被轉成base64編碼esMoule: false // 禁用esModule}}}, {test: /\.css$/,use: ['style-loader', 'css-loader']}, {test: /\.less$/,use: ['style-loader', 'css-loader', 'less-loader']},{test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/, // 例如:file.woff2?v=abc&opt=1use: 'file-loader'}]},// 產物輸出路徑, 因為開發和生產環境輸出不一致,所以在各自環境中進行配置output: {},// 配置模塊解析的具體行為(定義 webpack 在打包時,如何找到并解析具體模塊的路徑)resolve: {// 嘗試按順序解析這些后綴名。如果有多個文件有相同的名字,但后綴名不同,webpack 會解析列在數組首位的后綴的文件 并跳過其余的后綴// 能夠使用戶在引入模塊時不帶擴展:import File from '../path/to/file';extensions: ['.js', '.vue', '.less', '.css'],// 配置別名: import { xxx } from '$common/xxx';alias: {$page: path.resolve(process.cwd(), './app/pages'), // 定義別名,方便引入業務代碼$common: path.resolve(process.cwd(), './app/pages/common'),$widgets: path.resolve(process.cwd(), './app/pages/widgets'),$store: path.resolve(process.cwd(), './app/pages/store'),}},// 配置 webpack 插件plugins: [// 處理 .vue 文件,這個插件是必須de// 它的職能是將定義過的其他規則復制并應用到 .vue 文件中// 例如,如果有一條匹配規則 /\.js$/ 的規則, 那么他會應用到 .vue 文件中的 script 板塊中new VueLoaderPlugin(),// 把第三方庫暴露到 window context 下 // 任何文件都可以直接使用 Vue,Webpack 會自動將其映射為 require('vue')。// 例如 new Vue( { el: '#app', render: h => h(App) } );new webpack.ProvidePlugin({ Vue: 'vue' }),// 定義全局常量new webpack.DefinePlugin({__VUE_OPRIONS_API__: 'true', // 禁用選項式 API 支持__VUE_PRO_DEVTOOLS: 'false', // 禁用 vue 調試工具__VUE_PRO_HYDRATION_MISMATCH_DETAILS__: 'false' // 禁用生產環境構建下激活 (hydration) 不匹配的詳細警告}),// 顯示打包進度new webpack.ProgressPlugin(),// 每次 build 前清空 public/dist 目錄new CleanWebpackPlugin(['public/dist'], {root: path.resolve(process.cwd(), './app/'),exclude: [],verbose: true,dry: false}),// 構造最終渲染的頁面模版...htmlWebpackPluginList,],// 配置打包輸出優化(代碼分割,模塊分割,緩存,treeShaing,壓縮等優化策略)optimization: {/*** 把 js 文件打包成3種類型* 1. verdor: 第三方 lib 庫, 基本不會改動, 除非依賴版本升級* 2. common: 業務組件代碼的公共部分抽取出來, 改動較少* 3. ebnty.{page}:  不同頁面 entry 里的業務組件代碼的差異部分,會經常改動* 目的: 把改動和引用頻率不一樣的 js 區分出來,已達到更好利用瀏覽器緩存的效果*/splitChunks: {chunks: 'all', // 對同步和異步模塊都進行分割maxAsyncRequests: 10, // 每次異步加載的最大并行請求數maxInitialRequests: 10, // 入口點的最大并行請求數cacheGroups: {vendor: { // 第三方庫test: /[\\/]node_modules[\\/]/, // 打包node_modules 目錄下的模塊name: 'vendor', //模塊名稱priority: 20, // 優先級,數字越大越優先enforce: true, // 強制執行reuseExistingChunk: true, // 復用已有的公共 chunk},common: { // 業務組件公共代碼name: 'common',minChunks: 2, // 被兩處引用即被歸為公共模塊minSize: 1024 * 1, // 最小分割文件大小 priority: 10, // 優先級reuseExistingChunk: true, // 復用已有的公共 chunk}},},// 將 webpack 運行時生成的代碼打包到 runtime.jsruntimeChunk: true},
}

?

二、 生產環境配置:webpack.prod.js + prod.js


生產環境的配置主要集中在打包優化上,比如:代碼分割、壓縮、分包、樹搖等等。
基本思路:

  1. 基于base.js,合并配置
const baseConfig = require('./webpack.base.js');
const webpackConfig = merge.smart(baseConfig, {mode:'',output:''...
})
  1. mode:指定模式,為生產環境。指定生產環境之后會默認開啟一些配置,比如 tree sharking。
mode:'production'
  1. output: 配置產物輸出路徑。屬性path 指定的是 Webpack 打包后文件輸出的物理路徑, 屬性publicPath 指定的文件在服務器上的訪問路徑
 output: {filename: 'js/[name]_[chunkhash:8].bundle.js', // 具體看 文檔output/#template-stringspath: path.join(process.cwd(), './app/public/dist/prod'),publicPath: '/dist/prod', // 輸出目錄的公共 URLcrossOriginLoading: 'anonymous' // 允許跨域加載}
  1. module: 對每個模塊要使用的loader等配置。使用thread-loader實現多線程打包
module: {rules: [{test: /\.js$/,include: [path.resolve(process.cwd(), './app/pages')],use: [{loader: 'thread-loader', // 多線程編譯loaderoptions: {workers: os.cpus().length, // 使用 CPU 核心數}},{loader: 'babel-loader',options: {presets: ['@babel/preset-env'], // 用于語法轉換和按需引入 polyfill (處理舊版本瀏覽器兼容,填補 API/新特性 缺失)plugins: ['@babel/plugin-transform-runtime'] // 用于復用輔助代碼和模塊化 polyfill。}}]}]}
  1. plugins: 插件配置。使用MiniCssExtractPlugin插件,提取css公共部分等等。
  2. optimization: 優化配置。使用TerserWebpackPlugin提升壓縮階段的性能
  3. 最后將webpack.prod.js的配置傳入prod.js,prod.js通過webpack()方法啟動打包
const webpackProdConfig = require('./config/webpack.prod.js');
webpack(webpackProdConfig, (err, stats) => {...做一些執行打包的回調處理}))

?

生產環境全量配置:wbepack.prod.js

const path = require('path');
const merge = require('webpack-merge');
const os = require('os');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CSSMinimizerPlugin = require('css-minimizer-webpack-plugin')
const HtmlWebpackInjectAttributesPlugin = require('html-webpack-inject-attributes-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')// 基類配置
const baseConfig = require('./webpack.base.js');const webpackConfig = merge.smart(baseConfig, {// 指定生產環境mode: 'production',// 生產環境的 out put 配置output: {filename: 'js/[name]_[chunkhash:8].bundle.js',path: path.join(process.cwd(), './app/public/dist/prod'),publicPath: '/dist/prod', // 輸出目錄的公共 URLcrossOriginLoading: 'anonymous' // 允許跨域加載},module: {rules: [{test: /\.css$/,use: [MiniCssExtractPlugin.loader, "thread-loader"]}, {test: /\.js$/,include: [path.resolve(process.cwd(), './app/pages')],use: [{loader: 'thread-loader', // 多線程編譯loaderoptions: {workers: os.cpus().length, // 使用 CPU 核心數}},{loader: 'babel-loader',options: {presets: ['@babel/preset-env'], // 用于語法轉換和按需引入 polyfill (處理舊版本瀏覽器兼容,填補 API/新特性 缺失)plugins: ['@babel/plugin-transform-runtime'] // 用于復用輔助代碼和模塊化 polyfill。}}]}]},// performance 用于控制性能提示信息, 默認為 warning; 文件體積過大, 入口過多, 資源加載方式等情況下會提示警告performance: {hints: false},plugins: [// 提取 css 的公共部分, 有效利用緩存new MiniCssExtractPlugin({chunkFilename: 'css/[name]_[contenthash:8].bundle.css'}),// 優化并壓縮 cssnew CSSMinimizerPlugin(),// 瀏覽器在請求資源時不發送用戶的身份憑證new HtmlWebpackInjectAttributesPlugin({crossorgin: 'anonymous'})],optimization: { // 優化配置// 使用 TerserWebpackPlugin 的并發和緩存,提升壓縮階段的性能minimize: true,minimizer: [new TerserWebpackPlugin({cache: true, // 啟用緩存來加速構建過程parallel: true, // 利用多核 CPU 并行壓縮terserOptions: {compress: {drop_console: true // 移除 console.log}}})]}
});module.exports = webpackConfig;

生產環境啟動配置:prod.js

const webpack = require('webpack');
const webpackProdConfig = require('./config/webpack.prod.js');console.log('\nbuilding... \n');// 如果你不向 webpack 傳入可執行的回調函數, 它會返回一個 webpack Compiler 實例并在其中進行操作
// const compiler = webpack(webpackProdConfig);
// 區別在于compiler.run()更具靈活性、控制粒度等適合多次打包, 直接傳入一個回調函數 (err, stats)=>{} 則只會執行一次打包, 更適用于生存環境的場景
webpack(webpackProdConfig, (err, stats) => {// 配置文件錯誤if (err) {console.log('?err: \n', err)return}// stats.hasErrors()判斷缺失的 module,語法錯誤等, 還有個 stats.hasWarnings() 方法,可以用來判斷是否有警告信息if (stats.hasErrors()) {const info = stats.toJson()console.error(info.errors);}// process.stdout.write 更高效,適合大量數據輸出 (console.log 是基于它實現的)process.stdout.write(`? ${stats.toString({colors: true,// 在控制臺輸出色彩信息modules: false, // 不顯示每個模塊的打包信息children: false, // 不顯示子編譯任務的信息chunks: false, // 不顯示每個代碼塊的信息chunkModules: false // 顯示代碼塊中模塊的信息})}\n`)
});

?

三、 開發環境配置:webpack.dev.js + dev.js


開發環境則需要,配置 HMR 實現熱更新

  1. 通過merge合并base和dev的配置
 const webpackConfig = merge.smart(baseConfig,{mode:'',....
})
  1. 通過修改base.js的entry來配置HRM
const baseConfig = require('./webpack.base.js');// 開發階段的 entry 配置需要加入 hmr
Object.keys(baseConfig.entry).forEach(v => {// 第三方包不作為 hmr 的入口if (v !== 'vendor') {baseConfig.entry[v] = [baseConfig.entry[v], // 主入口文件// hmr 更新入口,官方指定的 hmr 路徑`webpack-hot-middleware/client?path=http://${host}:${port}/${hmrPath}&timeout=${timeout}`,]}
})
  1. 指定mode 等于 ’development‘
  2. devtool: 等于 eval-cheap-module-source-map時。 soure-map 配置 便于開發時調試
  3. output: 配置產物輸出路徑。與生產環境不同的是,開發環境的產物需要放到本地服務器上。通過設置 globalObject: 'this', Webpack 會根據運行環境自動選擇正確的全局對象。
 output: {filename: 'js/[name]_[chunkhash:8].bundle.js',path: path.resolve(process.cwd(), './app/public/dist/dev/'),publicPath: `http://${host}:${port}/public/dist/dev/`, // 輸出目錄的公共 URLglobalObject: 'this'}
  1. plugins: 通過配置webpack.HotModuleReplacementPlugin插件實現熱模塊替換
 plugins: [ new webpack.HotModuleReplacementPlugin({ multiStep: false }) ]
  1. 自定義一個服務,將產物文件放到本地服務器上。主要是用到兩個中間件: 用devMiddleware監控文件改動,用hotMiddleware實現熱更新,通知瀏覽器刷新
const { webpackConfig, DEV_SERVER_CONFIG } = require('./config/webpack.dev');
const app = express();
const compiler = webpack(webpackConfig)app.use(devMiddleware(compiler, {}))
app.use(hotMiddleware(compiler, {}))
app.listen(DEV_SERVER_CONFIG.PORT, () => {})

?

開發環境打包配置:webpack.dev.js

const path = require('path');
const merge = require('webpack-merge');
const webpack = require('webpack')// 基類配置
const baseConfig = require('./webpack.base.js');// dev-server 配置
const DEV_SERVER_CONFIG = {HOST: '127.0.0.1',PORT: 9200,HMR_PATH: '__webpack_hmr',TIMEOUT: 20000,
}
const { HOST: host, PORT: port, HMR_PATH: hmrPath, TIMEOUT: timeout } = DEV_SERVER_CONFIG;// 開發階段的 entry 配置需要加入 hmr 
Object.keys(baseConfig.entry).forEach(v => {console.log('--------v-------', v)// 第三方包不作為 hmr 的入口  有時候可能會手動配置第三方庫 entry: { vendor: ['vue', 'lodash']} 將其打包到一個單獨的文件中// 與 splitChunks 的區別: 自動從 node_modules 中提取第三方庫。更靈活,適用于復雜的項目。if (v !== 'vendor') {baseConfig.entry[v] = [baseConfig.entry[v], // 主入口文件// hmr 更新入口,官方指定的 hmr 路徑`webpack-hot-middleware/client?path=http://${host}:${port}/${hmrPath}&timeout=${timeout}`,]}
})const webpackConfig = merge.smart(baseConfig, {// 指定開發環境mode: 'development',// soure-map 配置 便于開發時調試devtool: 'eval-cheap-module-source-map',// 開發環境的 out put 配置output: {filename: 'js/[name]_[chunkhash:8].bundle.js',path: path.resolve(process.cwd(), './app/public/dist/dev/'),publicPath: `http://${host}:${port}/public/dist/dev/`, // 輸出目錄的公共 URLglobalObject: 'this' // 用于指定 Webpack 打包代碼時引用的全局對象。配置成 'this' Webpack 會根據運行環境自動選擇正確的全局對象。},// 開發階段插件plugins: [// HotModuleReplacementPlugin 用于實現熱模塊替換 (Hot Module Replacement - HMR)// 模塊熱替換允許在應用程序運行時替換模塊// 極大的提升開發效率, 因為能讓應用程序一直保持運行狀態new webpack.HotModuleReplacementPlugin({ multiStep: false }),]
});module.exports = {webpackConfig,  // webpack 配置DEV_SERVER_CONFIG // devServer 配置, 暴露給dev.js使用
};

開發環境啟動配置:dev.js

// 本地開發啟動devServer
const express = require('express');
const path = require('path');
const webpack = require('webpack');
const devMiddleware = require('webpack-dev-middleware');
const hotMiddleware = require('webpack-hot-middleware');// 從 webpack.dev.js 獲取 webpack 配置 和 devServer 配置
const { webpackConfig, DEV_SERVER_CONFIG } = require('./config/webpack.dev');const app = express();const compiler = webpack(webpackConfig)// 指定靜態文件目錄
app.use(express.static(path.join(__dirname, '../public/dist')));// 引用 devMiddleware 中間件 (監控文件改動)
app.use(devMiddleware(compiler, {writeToDisk: (filPath) => filPath.endsWith('.tpl'), // 落地文件publicPath: webpackConfig.output.publicPath, // 資源路徑// headers 配置headers: {'Access-Control-Allow-Origin': '*','Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS','Access-Control-Allow-Headers': 'X-Requested-With, contnet-type, Authorization'},stats: {colors: true}
}))// 引用 hotMiddleware 中間件 (熱更新)
app.use(hotMiddleware(compiler, {path: `/${DEV_SERVER_CONFIG.HMR_PATH}`,log: () => { }
}))console.info('請等待webpack初次構建完成...')const port = DEV_SERVER_CONFIG.PORT;
app.listen(port, () => {console.log("🚀 ~ app.listening on port:", port)
})

?

四、 配置npm啟動打包


pagkage.json:

?在這里插入圖片描述

因為開發環境下,產物文件都放在本地服務器上,所以需要通過配置--max_old_space_size分配好足夠的內存。

    "build:dev": "node --max_old_space_size=4096 ./app/webpack/dev.js","build:prod": "node ./app/webpack/prod.js"

更多參考:wbepack中文文檔

全文特別鳴謝: 抖音“哲玄前端”,《全棧實踐課》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/65137.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/65137.shtml
英文地址,請注明出處:http://en.pswp.cn/web/65137.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue3使用setup語法糖組件基礎傳值

(1):defineProps:傳入要使用的props定義自定義屬性,傳遞過來的值具有響應式,和props一樣; (2):defineEimts:傳入要自定義的事件,emit實例去傳入自定義事件的值,和$emit或…

S7-200可用的modbus RTU完成位輪詢

網上的信息比較散,官方說明也不充分,尤其是涉及主站按需寫入的部分沒有見到現成案例。 以下記錄完成位輪詢讀取,同時按需寫入的程序。 初始化主站,初始化塊的完成位M9.3通過上升沿觸發一個M9.4,用于后面啟動輪詢。 第…

特征點檢測與匹配——MATLAB R2022b

特征點檢測與匹配在計算機視覺中的作用至關重要,它為圖像處理、物體識別、增強現實等領域提供了堅實的基礎。 目錄 Harris角點檢測 SIFT(尺度不變特征變換) SURF(加速穩健特征) ORB(Oriented FAST and Rotated BRIEF) 總結 特征點檢測與匹配是計算機視覺中的一項基…

Vue3實現PDF在線預覽功能

?🌈個人主頁:前端青山 🔥系列專欄:Vue篇 🔖人終將被年少不可得之物困其一生 依舊青山,本期給大家帶來Vue篇專欄內容:Vue3現PDF在線預覽功能 前言 在開發中,PDF預覽和交互功能是一個常見的需求。無論是管理…

常用的EDA 工具

1) 邏輯設計: Cadence 的Verilog XL ? 模擬電路設計: Mentor 的Viewdraw ? 電路合成: Synopsys 的Design Compiler ? 電路仿真: Synopsys 的Hsim 和Hspice ? 人工布局: Cadence 的Virtuso ? 自動布局…

基于ESP32的桌面小屏幕實戰[5]:PCB下單

1. 焊接調試前準備 PCB下單 點擊“PCB下單” 檢查一下DRC 確認無錯誤之后,確認下單 然后就會跳轉到下面的網頁 基本上保持默認選項即可。可以看到“焊盤噴鍍”有3個選項。 在選擇表面處理工藝時,應綜合考慮產品的具體需求、環保法規以及成本等因素。例…

云原生架構的演變與實踐

云原生架構的演變與實踐 在現代軟件開發的時代背景下,云原生架構日益成為推動業務轉型的關鍵。它以云為中心的應用架構和開發思維,不僅包括了容器化的基本形式,更涉及全方位的應用管理及優化。本文將圍繞云原生的特征、遷移步驟以及模式展開…

探索現代 Web 開發中的流行技術:深入學習 Vite 的使用

在前端開發的世界中,構建工具扮演著越來越重要的角色。從 Webpack 到 Parcel,再到 Rollup,每個工具都有自己的獨特定位和目標。而今天,我們要討論的是一款近年來迅速崛起并受到廣泛歡迎的構建工具— Vite。 本文將從基本原理到實…

如何通過 6 種方式將照片從 iPhone 傳輸到戴爾 PC?

“你知道如何將iPhone上的照片轉移到電腦上嗎?我的iPhone上有很多照片,所以我想將這些照片從iPhone轉移到電腦上。請給我一些建議,謝謝!” - Nirenling 在戴爾社區中發布 您的iPhone是否被各種精彩的照片和視頻占滿而存儲空間不…

『SQLite』表達式操作

摘要:表達式是一個或多個值、運算符和計算值的 SQL 函數的組合。SQL 表達式與公式類似,都寫在查詢語言中。 基本語法 SELECT column1, column2, columnN FROM table_name WHERE [CONTION | EXPRESSION];布爾表達式 SQLite 的布爾表達式在匹配單個值的…

升級 Spring Boot 3 配置講解 —— 支持斷點傳輸的文件上傳和下載功能

學會這款 🔥全新設計的 Java 腳手架 ,從此面試不再怕! 在現代 Web 應用中,文件上傳和下載是非常常見的需求。然而,當文件較大時,傳統的上傳下載方式可能會遇到網絡不穩定或傳輸中斷的問題。為了解決這些問題…

框架Tensorflow2

深度學習框架之Tensorflow2 Tensorflow2版本的介紹 Tensorflow(簡稱tf)是深度學習框架,大大簡化了建模的方法和步驟,把Keras Api當作核心,使用非常簡單,跨平臺,集成各種現成模型,eager mode使得調試起來不…

SpringBoot3-深入理解自動配置類的原理(尚硅谷SpringBoot3-雷神)

文章目錄 目錄了解自動配置 一、導入對應場景的Mean依賴:1、引入依賴**找到自動配置類的所有配置都存放在哪里** 二、編寫主程序:SpringBootApplication觀察源碼時所需要知道的幾個核心注解:1、觀察SpringBootApplication源碼都做了什么 三、…

Mongo高可用架構解決方案

Mongo主從復制哪些事(僅適用特定場景) 對數據強一致性要求不高的場景,一般微服務架構中不推薦 master節點可讀可寫操作,當數據有修改時,會將Oplog(操作日志)同步到所有的slave節點上。那么對于從節點來說僅只讀,所有slave節點從master節點同步數據,然而從節點之間互相…

商業領域 - 競標極簡理解

競標極簡理解 競標是一種投標過程,指參與者(通常是企業或個人)為了獲得某個項目或合同的執行權,向招標人(通常是采購方或項目發起方)提交報價和方案,并爭取獲得招標人的認可 競標是一種常見的招…

C#Halcon跨窗口顏色識別

機器視覺是一門讓計算機模擬人類視覺功能的學科。顏色識別在其中扮演著重要的角色,它旨在通過對圖像中的顏色信息進行分析,從而識別出圖像中的目標物體或者區域。例如,在水果分揀系統中,可以根據水果的顏色(如蘋果的紅…

01:C語言的本質

C語言的本質 1、ARM架構與匯編2、局部變量初始化與空間分配2.1、局部變量的初始化2.1、局部變量數組初始化 3、全局變量/靜態變量初始化化與空間分配4、堆空間 1、ARM架構與匯編 ARM簡要架構如下:CPU,ARM(能讀能寫),Flash(能讀&a…

Transformer知識梳理

Transformer知識梳理 文章目錄 Transformer知識梳理什么是Transformer?語言模型遷移學習 Transformer結構注意力層原始結構 總結 什么是Transformer? 語言模型 Transformer模型本質上都是預訓練語言模型,大部分采用自監督學習(S…

第29天:PHP應用弱類型脆弱Hash加密Bool類型Array數組函數轉換比較

#知識點: 1、安全開發-原生PHP-弱類型脆弱 2、安全開發-原生PHP-函數&數據類型 3、安全開發-原生PHP-代碼審計案例 1、 和 兩個等號是弱比較,使用進行對比的時候,php解析器就會做隱式類型轉換,如果兩個值的類型不相等就會把兩…

STM32F1學習——編碼器接口

一、編碼器接口 編碼器接口可以接收正交編碼器的信號,根據編碼器旋轉產生的正交信號脈沖,通過硬件自動控制CNT值的自增或自減,從而指出編碼器的位置、旋轉方向和旋轉速度。 每個高級定時器和通用定時器都有一個編碼器接口,他們會占…