当前位置: 首页 > news >正文

河南建筑业城乡建设网站查询免费微信微网站模板下载

河南建筑业城乡建设网站查询,免费微信微网站模板下载,遵义页面设计制作,个人网站可以做百度推广吗在现代开发中一般各公司都有自己的监控平台#xff0c;对前端而言如果浏览器报错的话就可以通过埋点收集错误日志#xff0c;再结合sourcemap文件可以帮助我们定位到错误代码#xff0c;帮助我们排查问题。这里就记录一下之前在webpack和vite两个环境中的插件开发#xff0…在现代开发中一般各公司都有自己的监控平台对前端而言如果浏览器报错的话就可以通过埋点收集错误日志再结合sourcemap文件可以帮助我们定位到错误代码帮助我们排查问题。这里就记录一下之前在webpack和vite两个环境中的插件开发可以在生产构建时将sourcemap上传到内部的文件服务器配合后续的监控日志来一起使用 Webpack插件开发 Compiler 和 Compilation 在插件开发中有两个概念比较重要分别是Compiler和Compilation他们是Plugin和Webpack之间的桥梁。他们的含义如下 Compiler对象包含了Webpack环境所有的配置信息包含options、loaders、plugins等这些所有的信息这个对象在Webpack启动的时候被实例化是全局唯一的可以把他看成是Webpack的实例Compilation 对象包含了当前模块资源以及编译生成资源还有变化的文件等相关信息。在webpack以开发模式运行时每当检测到一个文件变化一个新的Compilation就会被创建。Compilation对象提供了很多事件回调给插件做扩展通过Compilation也能读取到Compiler对象 两者的区别在于Compiler代表了整个Webpack从启动到关闭的生命周期而Compilation只是代表了一次新的编译。 事件流 Webpack 就像一条生产线要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的多个流程之间有存在依赖关系只有完成当前处理后才能交给下一个流程去处理。 插件就像是一个插入到生产线中的一个功能在特定的时机对生产线上的资源做处理。 Webpack 通过 Tapable 来组织这条复杂的生产线。 Webpack 在运行过程中会广播事件插件只需要监听它所关心的事件就能加入到这条生产线中去改变生产线的运作。 Webpack 的事件流机制保证了插件的有序性使得整个系统扩展性很好。 Webpack 的事件流机制应用了观察者模式和 Node.js 中的 EventEmitter 非常相似。 Compiler 和 Compilation 都继承自 Tapable可以直接在 Compiler 和 Compilation 对象上广播和监听事件。 webpack 插件钩子 每个webpack插件都是一个class,其中最终要的两个内容一个是constructor可以接受一个option参数这个就是用户在使用这个插件时传入的参数第二个就是apply方法接受一个compiler这个实例在webpack初始化时会调用每个插件执行其中的apply方法我们就可以在apply这个方法中使用接受到的Compiler实例上提供的各种hook来监听我们需要的事件在整个流水线工程中有很多事件钩子如下图所示 我们可以监听我们需要的时机参考地址Webpack插件钩子 在这里我们需要在webpack打包结束的时候将构建结果中的.map文件上传到自己的文件服务器所以需要订阅done这个事件钩子在每次compilation完成时执行。 插件调用方式 在webpack插件中一共有同步和异步两种调用方式同步调用是直接使用tap异步调用使用tapAsync还有一种是tapPromise简单代码展示如下 apply(compiler) {// 同步钩子compiler.hooks.compilation.tap(MyPlugin, (compilation) {// 同步处理console.log(同步处理);}); }apply(compiler) {// 异步钩子使用回调函数compiler.hooks.done.tapAsync(MyPlugin, (stats, callback) {// 异步处理setTimeout(() {console.log(异步处理完成);callback();}, 1000);}); }apply(compiler) {// 异步钩子返回 Promisecompiler.hooks.done.tapPromise(MyPlugin, (stats) {return new Promise((resolve) {setTimeout(() {console.log(Promise 异步处理完成);resolve();}, 1000);});}); }这里我们需要将文件上传所以明显是一个异步的调用采用的是tapAsync的调用方式具体代码如下 const fs require(fs); const path require(path); const axios require(axios); const FormData require(form-data);// 将打包文件中的.map文件上传到指定服务器 class UploadSourceMapPlugin {constructor(options) {this.options options;if (!this.options.uploadUrl) {throw new Error(uploadUrl is required);}}apply(compiler) {compiler.hooks.done.tapAsync(UploadSourceMapPlugin, async (stats, callback) {try {const outputPath compiler.options.output.path;// 递归读取目录中的所有文件function getAllFiles(dir) {const files fs.readdirSync(dir);let fileList [];files.forEach(file {const filePath path.join(dir, file);const stat fs.statSync(filePath);if (stat.isDirectory()) {fileList fileList.concat(getAllFiles(filePath));} else {fileList.push(filePath);}});return fileList;}// 获取所有文件const allFiles getAllFiles(outputPath);// 过滤出 .map 文件const sourceMapFiles allFiles.filter(file file.endsWith(.map)).map(file ({name: path.basename(file),path: file}));// 上传所有的 source map 文件for (const file of sourceMapFiles) {const filePath file.path;if (fs.existsSync(filePath)) {await this.uploadFile(filePath, file.name);// 如果配置了上传后删除if (this.options.deleteAfterUpload) {fs.unlinkSync(filePath);console.log(Deleted ${file.name} after upload);}}}// 通知 webpack 异步操作已完成// webpack 可以继续执行后续步骤// 如果不调用 callbackwebpack 的构建过程会一直等待callback();} catch (error) {console.error(Error in UploadSourceMapPlugin:, error);callback();}});}async uploadFile(filePath, fileName) {try {const formData new FormData();formData.append(sourcemap, fs.createReadStream(filePath), fileName);const response await axios.post(this.options.uploadUrl, formData, {headers: {...formData.getHeaders(),Authorization: this.options.token || // 可选的认证token}});console.log(Successfully uploaded ${fileName});return response.data;} catch (error) {console.error(Failed to upload ${fileName}:, error.message);throw error;}}}module.exports UploadSourceMapPlugin; 这里有个小小的坑就是在compiler中有个state对象也是文件列表但是这里面只能获取到经过Webpack编译之后的文件所以最保险的还是自己递归遍历一下结果文件进行过滤。这里callback是上传结束之后的回调告诉webpack已近完成否则webpack就会一直在这里等待 使用 最终使用这个插件也很简单我们一般主需要再生产环境使用开发环境一般是没有必要将sourcemap上传上去的。通过下面的配置就可以使用我们开发的插件了 // 只在生产环境使用...(process.env.NODE_ENV production ? [new UploadSourceMapPlugin({uploadUrl: https://file-server.com/upload,token: auth-token, // 可选的认证tokendeleteAfterUpload: true // 是否在上传后删除本地文件})] : []),Vite Vite 是一个现代的前端构建工具因其快速、简单的配置和优化的开发体验而广受欢迎。Vite是基于Rollup来的速度非常快如果开发的插件不带Vite特有的钩子一般都可以在Rollup中兼容使用。 Vite中的每个插件一般都是一个返回一个对象的函数其中有name字段表插件名称以及对应的钩子函数在Vite中有通用钩子和Vite专属钩子。 参考地址Vite插件钩子 这里我们在每次生产环境构建结束时调用这个插件。我们可以用apply: ‘build’, 表示只在构建时调用这个插件日常开始npm run dev时处于开发状态就不会调用这个插件。 具体代码如下 import fs from fs import path from pathexport default function UploadSourceMapPlugin(options {}) {const {uploadUrl , // 上传服务器地址headers {}, // 自定义请求头deleteAfterUpload true // 上传后是否删除本地map文件} optionsif (!uploadUrl) {throw new Error(uploadUrl is required for UploadSourceMapPlugin)}return {name: vite-plugin-upload-sourcemap,apply: build, // 仅在构建时应用async closeBundle() {const distDir path.resolve(dist)const sourcemaps []// 递归查找所有.map文件function findSourceMaps(dir) {const files fs.readdirSync(dir)files.forEach(file {const fullPath path.join(dir, file)const stat fs.statSync(fullPath)if (stat.isDirectory()) {findSourceMaps(fullPath)} else if (file.endsWith(.map)) {sourcemaps.push(fullPath)}})}findSourceMaps(distDir)// 上传所有sourcemap文件for (const mapFile of sourcemaps) {const formData new FormData()formData.append(file, fs.createReadStream(mapFile))try {const response await fetch(uploadUrl, {method: POST,body: formData,headers: {...headers}})if (!response.ok) {throw new Error(Upload failed for ${mapFile})}console.log(Successfully uploaded: ${mapFile})// 如果配置了上传后删除则删除本地map文件if (deleteAfterUpload) {fs.unlinkSync(mapFile)console.log(Deleted local file: ${mapFile})}} catch (error) {console.error(Error uploading ${mapFile}:, error)}}}} } 其中的代码逻辑其实和webpack中基本保持一致。至此我们就开发了一个上传soucemap的两套插件可以分别在Webpack和Rollup中使用了。 参考文件 Webpack插件钩子 Vite插件钩子 Vite插件开发
http://www.hkea.cn/news/14309179/

相关文章:

  • 工商核名在哪个网站长沙网站seo技术厂家
  • 网页制作网站首页龙华建网站多少钱
  • 必应搜索网站代码运行框wordpress
  • 网站负责人 备案网站开发 后端服务
  • wordpress开启子域名多站点模式微网站 小程序 区别
  • 百度站长验证网站失败重庆的网站建设公司
  • 用树莓派做网站服务器网站备案为什么要闭站
  • 北京网站建设公司 北京网站设计 网页设计制作 高端网站建设 分形科技菏泽建设企业网站
  • 网站怎么做图片动态图片不显示不出来的专做负面的网站
  • 协会网站制作好用的ppt模板网站
  • 网站开发技术选型网站策划建设方案书
  • 注册了域名 网站怎么做万网域名注册信息查询
  • 网站如何搭建开发一个电商app软件多少钱
  • 山东省建设厅网站查网站建设规划模板
  • 范县网站建设电话全椒县城乡规划建设局网站
  • 软件it网站建设方案wordpress的支付插件
  • 重庆旅游seo整站优化安徽安庆属于南方还是北方
  • 公众号做视频网站会封吗异次元wordpress模板
  • 怎么申请域名建网站做模拟人生比较有名的网站
  • 阳谷网站建设费用南充做网站电话
  • 峰峰做网站泰国网站建设
  • 优秀网站设计平台asp.net做网站步骤
  • 网站静态生成目录 名称 建议广东十大网站建设品牌
  • 企业网站建设多长时间安顺住房和城乡建设部网站
  • 南通优化网站排名企业网站php源码
  • 四川省建设厅门户网站校园网络拓扑图及网络方案
  • 网站 建设 汇报贵州十大广告公司
  • 电子网站建设价格平阴网站建设费用
  • 高校网站建设彩票网站制作
  • 网站建设调查广告设计与制作的课程