前端工程化之手搓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.mzph.cn/web/65137.shtml

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

相关文章

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预览和交互功能是一个常见的需求。无论是管理…

基于ESP32的桌面小屏幕实战[5]:PCB下单

1. 焊接调试前准备 PCB下单 点击“PCB下单” 检查一下DRC 确认无错误之后,确认下单 然后就会跳转到下面的网页 基本上保持默认选项即可。可以看到“焊盘喷镀”有3个选项。 在选择表面处理工艺时,应综合考虑产品的具体需求、环保法规以及成本等因素。例…

如何通过 6 种方式将照片从 iPhone 传输到戴尔 PC?

“你知道如何将iPhone上的照片转移到电脑上吗?我的iPhone上有很多照片,所以我想将这些照片从iPhone转移到电脑上。请给我一些建议,谢谢!” - Nirenling 在戴尔社区中发布 您的iPhone是否被各种精彩的照片和视频占满而存储空间不…

升级 Spring Boot 3 配置讲解 —— 支持断点传输的文件上传和下载功能

学会这款 🔥全新设计的 Java 脚手架 ,从此面试不再怕! 在现代 Web 应用中,文件上传和下载是非常常见的需求。然而,当文件较大时,传统的上传下载方式可能会遇到网络不稳定或传输中断的问题。为了解决这些问题…

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值的自增或自减,从而指出编码器的位置、旋转方向和旋转速度。 每个高级定时器和通用定时器都有一个编码器接口,他们会占…

网络安全的学习与实践经验(附资料合集)

学习资源 在线学习平台: Hack This Site:提供从初学者到高级难度的挑战任务,适合练习各种网络安全技术。XCTF_OJ:由XCTF组委会开发的免费在线网络安全网站,提供丰富的培训材料和资源。SecurityTube:提供丰…

行业商机信息付费小程序系统开发方案

行业商机信息付费小程序系统,主要是整合优质行业资源,实时更新的商机信息。在当今信息爆炸的时代,精准、高效地获取行业商机信息对于企业和个人创业者而言至关重要。 一、使用场景 日常浏览:用户在工作间隙或闲暇时间&#xff0c…

[Qt] 输入控件 | Line | Text | Combo | Spin | Date | Dial | Slider

目录 输入类控件 1、Line Edit 录入个人信息 使用正则表达式验证输入框的数据 验证两次输入的密码一致 切换显示密码 2、Text Edit 获取多行输入框的内容 验证输入框的各种信号 3、Combo Box 使用下拉框模拟麦当劳点餐 从文件中加载下拉框的选项 4、Spin Box 调整…

Flink CDC 自定义函数处理 SQLServer XML类型数据 映射 doris json字段方案

Flink CDC 自定义函数处理 SQLServer XML类型数据方案 1. 背景 因业务使用SQLServer数据库,CDC同步到doris 数仓。对于SQLServer xml类型,doris没有相应的字段对应, 可以使用json来存储xml数据。需要进行一步转换。从 flink 自定义函数入手…

JeeSite 快速开发平台:全能企业级快速开发解决方案|GitCode 光引计划征文展示

投稿人GitCode ID:thinkgem 光引计划投稿项目介绍 JeeSite 快速开发平台,不仅仅是一个后台开发框架,它是一个企业级快速开发解决方案,后端基于经典组合 Spring Boot、Shiro、MyBatis,前端采用 Beetl、Bootstrap、Admi…

2025/1/4期末复习 密码学 按老师指点大纲复习

我们都要坚信,道路越是曲折,前途越是光明。 --------------------------------------------------------------------------------------------------------------------------------- 现代密码学 第五版 杨波 第一章 引言 1.1三大主动攻击 1.中断…

Java 内存溢出(OOM)问题的排查与解决

在 Java 开发中,内存溢出(OutOfMemoryError,简称 OOM)是一个常见且棘手的问题。相比于数组越界、空指针等业务异常,OOM 问题通常更难定位和解决。本文将通过一次线上内存溢出问题的排查过程,分享从问题表现…