Webpack node、output.jsonpFunction 配置详解
Webpack node、output.jsonpFunction 配置详解
最近尝试给一些用到 webpack
的项目升级到最新 webpack5
版本,其中遇到了一些问题,我挑了两个比较典型的问题,其中主要涉及到了 webpack
的 node
属性跟 output.jsonpFunction
(webpack5 以前版本)属性,下面我们结合 webpack
的源码来分析一下这两个属性。
开始
这里使用的 webpack
版本为:
- webpack@^4.46.0
- webpack@^5.88.2
首先我们创建一个 webpack4
的项目:
webpack-node1:
mkdir webpack-node2 && cd webpack-node2 && npm init -y
接着安装 webpack4
:
npm install -D webpack@4.46.0 webpack-cli@4.10.0
创建创建一个 src/index.js
入口文件:
mkdir src && touch src/index.js
在项目根目录 webpack-node1
目录下创建一个 webpack 配置文件 webpack.config.js
:
cd .. && touch webpack.config.js
// webpack.config.js
module.exports = {output: {publicPath: "./dist/",},devtool: false, // 关闭 source-map 功能
};
ok,我们在项目根目录 webpack-node1
下执行一下 webpack 打包命令看效果:
npx webpack build --mode=development
可以看到,因为我们的入口文件 src/index.js
是一个空文件,所以打包后的 dist/main.js
文件除了一些 webpack 的辅助函数外,入口文件里面为空。
最后我们创建一个 test.html
文件来测试:
touch test.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>webpack4</title><script src="./dist/main.js"></script>
</head>
<body></body>
</html>
ok,项目我们就创建完了,接下来我们看一下 webpack.node
配置。
Node 配置
我们先看一下 webpack官网 对它的介绍:
这些选项可以配置是否 polyfill 或 mock 某些 Node.js 全局变量。
此功能由 webpack 内部的
NodeStuffPlugin
插件提供。Warning
从 webpack 5 开始,你只能在
node
选项下配置global
、__filename
或__dirname
。如果需要在 webpack 5 下的 Node.js 中填充fs
,请查阅 resolve.fallback 获取相关帮助。node
boolean: false` `object
webpack.config.js
module.exports = {//...node: {global: false,__filename: false,__dirname: false,}, };
从 webpack 3.0.0 开始,
node
选项可能被设置为false
,以完全关闭NodeStuffPlugin
插件。node.global
boolean` `'warn'
Tip
如果你正在使用一个需要全局变量的模块,请使用
ProvidePlugin
替代global
。关于此对象的准确行为,请查看Node.js 文档。
选项:
true
: 提供 polyfill.false
: 不提供任何 polyfill。代码可能会出现ReferenceError
的崩溃。'warn'
: 当使用global
时展示一个警告。node.__filename
boolean` `'mock' | 'warn-mock' | 'eval-only'
选项:
true
: 输入文件的文件名,是相对于context
选项。false
: webpack 不会更改__filename
的代码。在 Node.js 环境中运行时,出文件的文件名。'mock'
: value 填充为'index.js'
。'warn-mock'
: 使用'/index.js'
但是会展示一个警告。'eval-only'
node.__dirname
boolean` `'mock' | 'warn-mock' | 'eval-only'
选项:
true
: 输入 文件的目录名,是相对于context
选项。false
: webpack 不会更改__dirname
的代码,这意味着你有常规 Node.js 中的__dirname
的行为。在 Node.js 环境中运行时,输出 文件的目录名。'mock'
: value 填充为'/'
。'warn-mock'
: 使用'/'
但是会显示一个警告。'eval-only'
以上是 webpack5
的 node
配置的描述。
webpack4
ok,看完了官网的描述,我们来用一下这个 node
配置。
我们修改一下 src/index.js
文件:
// 判断是浏览器环境
const isBrowser = process.browser; // 使用 nodejs 的 process 对象
console.log(isBrowser);
console.log(__dirname); // 使用 nodejs 的 __dirname 全局属性
console.log(global); // 使用 nodejs 全局对象 global
我们重新执行打包命令看效果:
npx webpack build --mode=development
浏览器打开 test.html
文件:
可以看到,即使是 nodejs
环境中的变量,我们在浏览器中仍然可以访问,这是为什么呢?
因为 webpack
提前给我们注入了这些 nodejs
的全局变量,我们来找一下 webpack4
的源码。
node_modules/webpack/lib/node/NodeSourcePlugin.js
:
/*MIT License http://www.opensource.org/licenses/mit-license.phpAuthor Tobias Koppers @sokra
*/
"use strict";
const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
const ParserHelpers = require("../ParserHelpers");
const nodeLibsBrowser = require("node-libs-browser");module.exports = class NodeSourcePlugin {constructor(options) {this.options = options;}apply(compiler) {const options = this.options;// 当 webpack.node 配置为 false 的时候关闭该插件if (options === false) {// allow single kill switch to turn off this pluginreturn;}// 获取 nodepollyfill 的依赖地址const getPathToModule = (module, type) => {// 配置成 true 的话就去找到对应的 pollyfill 库if (type === true || (type === undefined && nodeLibsBrowser[module])) {if (!nodeLibsBrowser[module]) {throw new Error(`No browser version for node.js core module ${module} available`);}return nodeLibsBrowser[module];// 配置成 mock 就简单模拟一下} else if (type === "mock") {return require.resolve(`node-libs-browser/mock/${module}`);// 配置成 empty 就返回 undeifned} else if (type === "empty") {return require.resolve("node-libs-browser/mock/empty");} else {return module;}};// 修改变量为依赖引入const addExpression = (parser, name, module, type, suffix) => {suffix = suffix || "";parser.hooks.expression.for(name).tap("NodeSourcePlugin", () => {if (parser.state.module &&parser.state.module.resource === getPathToModule(module, type))return;const mockModule = ParserHelpers.requireFileAsExpression(parser.state.module.context,getPathToModule(module, type));return ParserHelpers.addParsedVariableToModule(parser,name,mockModule + suffix);});};compiler.hooks.compilation.tap("NodeSourcePlugin",(compilation, { normalModuleFactory }) => {const handler = (parser, parserOptions) => {if (parserOptions.node === false) return;let localOptions = options;if (parserOptions.node) {localOptions = Object.assign({}, localOptions, parserOptions.node);}// 对 global 变量进行替换if (localOptions.global) {parser.hooks.expression.for("global").tap("NodeSourcePlugin", () => {const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(parser.state.module.context,require.resolve("../../buildin/global"));return ParserHelpers.addParsedVariableToModule(parser,"global",retrieveGlobalModule);});}// 对 process 变量进行替换if (localOptions.process) {const processType = localOptions.process;addExpression(parser, "process", "process", processType);}//...};normalModuleFactory.hooks.parser.for("javascript/auto").tap("NodeSourcePlugin", handler);normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("NodeSourcePlugin", handler);});// 替换 nodejs-pollyfill 依赖为第三方库compiler.hooks.afterResolvers.tap("NodeSourcePlugin", compiler => {for (const lib of Object.keys(nodeLibsBrowser)) {if (options[lib] !== false) {compiler.resolverFactory.hooks.resolver.for("normal").tap("NodeSourcePlugin", resolver => {new AliasPlugin("described-resolve",{name: lib,onlyModule: true,alias: getPathToModule(lib, options[lib])},"resolve").apply(resolver);});}}});}
};
代码有点多,看着估计有点晕,我们先看一下我们的入口文件 src/index.js
:
// 判断是浏览器环境
const isBrowser = process.browser;
console.log(isBrowser);
console.log(__dirname);
console.log(global);
再看一下打包过后的 dist/main.js
文件:
/******/ (function(modules) { // webpackBootstrap//...
/******/ })
/************************************************************************/
/******/ ({/***/ "./node_modules/process/browser.js":
/*!*****************************************!*\!*** ./node_modules/process/browser.js ***!\*****************************************/
/*! no static exports found */
/***/ (function(module, exports) {// shim for using process in browser
var process = module.exports = {};
//...
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
//.../***/ "./src/index.js":
/*!**********************!*\!*** ./src/index.js ***!\**********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {/* WEBPACK VAR INJECTION */(function(process, __dirname, global) {// 判断是浏览器环境
const isBrowser = process.browser;
console.log(isBrowser);
console.log(__dirname);
console.log(global);/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../node_modules/process/browser.js */ "./node_modules/process/browser.js"), "/", __webpack_require__(/*! ./../node_modules/webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js")))/***/ })/******/ });
可以看到:
__dirname
变量变成了/
字符串process
变量变成了node_modules/process/browser.js
模块导出内容global
变量变成了node_modules/webpack/buildin/global.js
模块导出内容
那么在 webpack4
中,除了我们用到的这些变量外,我们还可以默认使用哪些全局变量呢?
我们找到 node_modules/node-libs-browser/index.js
文件:
exports.assert = require.resolve('assert/');
exports.buffer = require.resolve('buffer/');
exports.child_process = null;
exports.cluster = null;
exports.console = require.resolve('console-browserify');
exports.constants = require.resolve('constants-browserify');
exports.crypto = require.resolve('crypto-browserify');
exports.dgram = null;
exports.dns = null;
exports.domain = require.resolve('domain-browser');
exports.events = require.resolve('events/');
exports.fs = null;
exports.http = require.resolve('stream-http');
exports.https = require.resolve('https-browserify');
exports.module = null;
exports.net = null;
exports.os = require.resolve('os-browserify/browser.js');
exports.path = require.resolve('path-browserify');
exports.punycode = require.resolve('punycode/');
exports.process = require.resolve('process/browser.js');
exports.querystring = require.resolve('querystring-es3/');
exports.readline = null;
exports.repl = null;
exports.stream = require.resolve('stream-browserify');
exports._stream_duplex = require.resolve('readable-stream/duplex.js');
exports._stream_passthrough = require.resolve('readable-stream/passthrough.js');
exports._stream_readable = require.resolve('readable-stream/readable.js');
exports._stream_transform = require.resolve('readable-stream/transform.js');
exports._stream_writable = require.resolve('readable-stream/writable.js');
exports.string_decoder = require.resolve('string_decoder/');
exports.sys = require.resolve('util/util.js');
exports.timers = require.resolve('timers-browserify');
exports.tls = null;
exports.tty = require.resolve('tty-browserify');
exports.url = require.resolve('url/');
exports.util = require.resolve('util/util.js');
exports.vm = require.resolve('vm-browserify');
exports.zlib = require.resolve('browserify-zlib');
可以看到,有这么些 nodejs
全局变量,我们可以正常的在浏览器端访问,以至于程序不会报错。
要关掉这些默认的 nodejs-pollyfill
也很简单,我们修改一下 webpack.config.js
配置:
module.exports = {output: {publicPath: "./dist/",},devtool: false,node: false, // 关闭 nodejs-polyfill
};
我们关掉后再次打包运行代码:
可以看到,程序第一行就报错了,说 process
变量不存在,因为 process
变量为 nodejs
中的全局变量。
ok,看完 webpack4 后,我们试一下 webpack5 看会有什么不一样?
webpack5
跟前面的 webpack4
项目创建一样,我们创建一个 webpack-node1
的项目。
安装 webpack
依赖的时候不一样,我们要安装 webpack5
版本,其它操作都一样,我就不一步一步演示了。
安装 webpack5
版本:
npm install -D webpack@5.88.2 webpack-cli@5.1.4
我们把 webpack4
项目的 src/index.js
文件的内容也复制一份:
// 判断是浏览器环境
const isBrowser = process.browser;
console.log(isBrowser);
console.log(__dirname);
console.log(global);
然后我们打包看效果:
npx webpack build --mode=development
可以看到,直接报错了!
因为在 webpack5
中,默认只给 global
、__filename
、__dirname
这三个全局变量添加了 polyfill
:
module.exports = {devtool: false,output: {publicPath: "./dist/"},// 默认 node 配置node: {global: true,__dirname: true,__filename: true,}
};
我们找到 webpack5
的 NodeStuffPlugin
插件。
node_modules/webpack/lib/NodeStuffPlugin.js
:
//...
class NodeStuffPlugin {/*** @param {NodeOptions} options options*/constructor(options) {this.options = options;}/*** Apply the plugin* @param {Compiler} compiler the compiler instance* @returns {void}*/apply(compiler) {const options = this.options;compiler.hooks.compilation.tap(PLUGIN_NAME,(compilation, { normalModuleFactory }) => {//...// 替换 global 变量if (localOptions.global !== false) {const withWarning = localOptions.global === "warn";parser.hooks.expression.for("global").tap(PLUGIN_NAME, expr => {const dep = new ConstDependency(RuntimeGlobals.global,/** @type {Range} */ (expr.range),[RuntimeGlobals.global]);dep.loc = /** @type {DependencyLocation} */ (expr.loc);parser.state.module.addPresentationalDependency(dep);// TODO webpack 6 removeif (withWarning) {parser.state.module.addWarning(new NodeStuffInWebError(dep.loc,"global","The global namespace object is a Node.js feature and isn't available in browsers."));}});parser.hooks.rename.for("global").tap(PLUGIN_NAME, expr => {const dep = new ConstDependency(RuntimeGlobals.global,/** @type {Range} */ (expr.range),[RuntimeGlobals.global]);dep.loc = /** @type {DependencyLocation} */ (expr.loc);parser.state.module.addPresentationalDependency(dep);return false;});}/*** @param {string} expressionName expression name* @param {(module: NormalModule) => string} fn function* @param {string=} warning warning* @returns {void}*/const setModuleConstant = (expressionName, fn, warning) => {parser.hooks.expression.for(expressionName).tap(PLUGIN_NAME, expr => {const dep = new CachedConstDependency(JSON.stringify(fn(parser.state.module)),/** @type {Range} */ (expr.range),expressionName);dep.loc = /** @type {DependencyLocation} */ (expr.loc);parser.state.module.addPresentationalDependency(dep);// TODO webpack 6 removeif (warning) {parser.state.module.addWarning(new NodeStuffInWebError(dep.loc, expressionName, warning));}return true;});};// 替换 __filename 变量const setConstant = (expressionName, value, warning) =>setModuleConstant(expressionName, () => value, warning);const context = compiler.context;if (localOptions.__filename) {switch (localOptions.__filename) {case "mock":setConstant("__filename", "/index.js");break;case "warn-mock":setConstant("__filename","/index.js","__filename is a Node.js feature and isn't available in browsers.");break;case true:setModuleConstant("__filename", module =>relative(compiler.inputFileSystem, context, module.resource));break;}parser.hooks.evaluateIdentifier.for("__filename").tap(PLUGIN_NAME, expr => {if (!parser.state.module) return;const resource = parseResource(parser.state.module.resource);return evaluateToString(resource.path)(expr);});}// 替换 __filename 变量if (localOptions.__dirname) {switch (localOptions.__dirname) {case "mock":setConstant("__dirname", "/");break;case "warn-mock":setConstant("__dirname","/","__dirname is a Node.js feature and isn't available in browsers.");break;case true:setModuleConstant("__dirname", module =>relative(compiler.inputFileSystem, context, module.context));break;}parser.hooks.evaluateIdentifier.for("__dirname").tap(PLUGIN_NAME, expr => {if (!parser.state.module) return;return evaluateToString(parser.state.module.context)(expr);});}parser.hooks.expression.for("require.extensions").tap(PLUGIN_NAME,expressionIsUnsupported(parser,"require.extensions is not supported by webpack. Use a loader instead."));};normalModuleFactory.hooks.parser.for(JAVASCRIPT_MODULE_TYPE_AUTO).tap(PLUGIN_NAME, handler);normalModuleFactory.hooks.parser.for(JAVASCRIPT_MODULE_TYPE_DYNAMIC).tap(PLUGIN_NAME, handler);});}
}module.exports = NodeStuffPlugin;
可以看到,webpack5
的 NodeStuffPlugin
插件比 webpack4
的 NodeSourcePlugin
插件简单多了,默认只给 global
、__filename
、__dirname
这三个全局变量添加了 polyfill
。
那有些小伙伴要说了,我要使用 process
全局变量的话该怎么用呢?官网也说了,如果要使用这三个全局变量外的全局变量的话,你可以使用查阅 resolve.fallback 获取相关帮助。
官方这种解释也不太对,因为 process
是一个全局变量,又不是一个依赖库,resolve.fallback
是当依赖找不到的时候会进行 fallback
替换。所以我们只能通过 DefinePlugin
插件去替换掉 process.browser
这种方式去实现我们的需求了,或者重写一个 webpack4
的 NodeSourcePlugin
插件,或者还可以扩展一下webpack5
的 NodeStuffPlugin
插件。
哈哈,其实完全没必要去做额外的一些扩展了,既然 webpack5
默认只给 global
、__filename
、__dirname
这三个全局变量添加了 polyfill
,说明经过长时间的项目经验来看,其它的变量很少用到,所以干脆去掉得了,既然这样做了还是有它自己的道理的,如果实在要用其它变量的话,可以尝试一下我上面提到的几个方法哦!
output.jsonpFunction 配置
webpack
处理异步依赖声明的全局变量名称。
我们还是拿我们项目来说明一下吧。
webpack4
我们在 webpack4
项目 webpack-node2/src
目录下创建一个 hello.js
:
touch ./src/hello.js
然后简单导出一个默认 hello 函数:
export default function (name){console.log(`hello ${name}!`);
}
可以看到,我们在入口文件 index.js
中异步导入了 hello.js
,然后执行了导出的 hello
方法。
ok,我们重新打包运行看效果:
npx webpack build --mode=development
可以看到,浏览器正常打印了执行结果。
我们看一下打包过后的 dist/main.js
文件:
// ....
/******/
// window 中声明一个全局 webpackJsonp 用来存储异步依赖
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
/******/ jsonpArray.push = webpackJsonpCallback;
/******/ jsonpArray = jsonpArray.slice();
/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
/******/ var parentJsonpFunction = oldJsonpFunction;
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js");
/******/ })
/************************************************************************/
/******/ ({/***/ "./src/index.js":
/*!**********************!*\!*** ./src/index.js ***!\**********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {// 异步导入该 hello 函数
__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./hello */ "./src/hello.js")).then(({default: hello})=>{// 执行异步函数hello("小虫");
});/***/ })/******/ });
可以看到,webpack4
在全局 window 中声明一个全局 webpackJsonp 变量用来存储异步依赖。
有小伙伴要说了,这有什么问题呢?
如果你导入的是一个第三方依赖,它在全局 window 中声明一个全局 webpackJsonp 变量用来存储异步依赖,而你的项目中也是一样的操作,那么这个全局 webpackJsonp 变量就会被污染了,程序就会出现异常情况。
所以为了避免这种异常情况的发生,当我们开发一个第三方依赖库给别人用的时候,如果我们的库中有异步模块,我们就需要修改一下这个默认全局 webpackJsonp 变量的名称。
修改起来也是很简单,我们直接修改一下 webpack.config.js
配置:
module.exports = {output: {publicPath: "./dist/",jsonpFunction: "webpackJsonp_webpack_node2", // 替换全局 webpackJsonp 变量的名称,名字最好能唯一},devtool: false,node: false, // 关闭 nodejs-polyfill
};
这样打包出来后,就不会出现全局 webpackJsonp 变量污染的情况了,小伙伴可以试试哦!
webpack5
正因为全局 webpackJsonp 变量经常被污染,webpack5 去除了 jsonpFunction
配置,换成了 output.chunkLoadingGlobal
配置:
output.chunkLoadingGlobal
string = 'webpackChunkwebpack'
webpack 用于加载 chunk 的全局变量。
webpack.config.js
module.exports = {//...output: {//...chunkLoadingGlobal: 'myCustomFunc',}, };
默认为 webpackChunk
+(package.json 中的 name 属性值),在我们 webpack-node1
项目中, 全局 webpackJsonp 变量的名称为 webpackChunkwebpack_node1
,小伙伴可以试一下哦!
webpack5 源码 node_modules/webpack/lib/config/defaults.js
第 885 行:
F(output, "chunkLoadingGlobal", () =>Template.toIdentifier("webpackChunk" +Template.toIdentifier(/** @type {NonNullable<Output["uniqueName"]>} */ (output.uniqueName))));
总结
不得不说,webpack5 修复了很多之前留下的坑,配置变得更简单了,如果可以的话,建议升级一下项目的 webpack 版本,可以带来很多性能的优化和避免一些程序异常的发生。
希望以上的分享能够给你带来一些小小的帮助。
相关文章:

Webpack node、output.jsonpFunction 配置详解
Webpack node、output.jsonpFunction 配置详解 最近尝试给一些用到 webpack 的项目升级到最新 webpack5 版本,其中遇到了一些问题,我挑了两个比较典型的问题,其中主要涉及到了 webpack 的 node 属性跟 output.jsonpFunction (web…...

要跟静音开关说再见了!iPhone15新变革,Action按钮引领方向
有很多传言称iPhone 15 Pro会有很多变化,但其中一个变化可能意味着iPhone体验从第一天起就有的一项功能的终结。我说的是静音开关,它可以让你轻松地打开或关闭iPhone的铃声。 根据越来越多的传言,iPhone 15 Pro和iPhone 15 Pro Max将拆除静音…...

论文笔记 Graph Attention Networks
2018 ICLR 1 intro 1.1. GCN的不足 无法完成inductive任务 inductive任务是指: 训练阶段与测试阶段需要处理的graph不同。通常是训练阶段只是在子图上进行,测试阶段需要处理未知的顶点。GGN 的参数依赖于邻接矩阵A/拉普拉斯矩阵L,所以换了…...
看上去就很像的agree和degree有什么联系
“Agree”(同意)和 “degree”(程度)这两个词在语义上没有直接的联系,它们代表不同的概念。 “Agree” 意味着在意见、观点或立场上达成共识或一致。它表示同意或同意某人或某事。 例如: “We all agree…...
2023前端面试题第二弹(真实,一般人我还不给看)
为什么要初始化css? 避免浏览器差异,解决兼容问题 网格布局 display: grid; grid-template-columns: 1fr 1fr 1fr less的优点 可以兼容,可以嵌套,循环,运算,定义变量和继承样式(extendÿ…...

零基础如何学习 Web 安全,如何让普通人快速入门网络安全?
前言 网络安全现在是朝阳行业,缺口是很大。不过网络安全行业就是需要技术很多的人达不到企业要求才导致人才缺口大 【一一帮助安全学习(网络安全面试题学习路线视频教程工具)一一】 初级的现在有很多的运维人员转网络安全,初级…...

安全学习DAY18_信息打点-APP资产搜集
信息打点-APP资产&静态提取&动态抓包&动态调试 文章目录 信息打点-APP资产&静态提取&动态抓包&动态调试本节知识&思维导图本节使用到的链接&工具 如何获取目标APP从名称中获取APP从URL获取APP APP搜集资产信息APP提取信息分类信息提取方式信息…...
react 矩形波浪
"矩形波浪"(Square Wave)在信号处理和波形生成中是一种特殊类型的波形,通常由两个不同的值交替组成,一个是高电平,另一个是低电平,形成类似方波的波形。在 React 中创建一个矩形波浪的效果可以通…...

【GitHub】Pycharm本地项目打包上传到Github仓库的操作步骤
文章目录 1、Pycharm端的设置操作2、Github端的设置操作3、Pycharm上配置Github4、Git本地项目至GitHub仓库5、前往Github中查看确认6、常见报错 1、Pycharm端的设置操作 通过CtrlAltS快捷组合键的方式,打开设置,导航到版本控制一栏中的Git,…...

计算机网络基础
前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页:KC老衲爱尼姑的博客主页 博主的github,平常所写代码皆在于此 共勉:talk is cheap, show me the code 作者是爪哇岛的新手,水平很有限&…...

【图像分类】基于LIME的CNN 图像分类研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

回归预测 | MATLAB实现TSO-SVM金枪鱼群算法优化支持向量机多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现TSO-SVM金枪鱼群算法优化支持向量机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现TSO-SVM金枪鱼群算法优化支持向量机多输入单输出回归预测(多指标,多图)效果一览基…...

Pixar、Adobe 和苹果等成立 OpenUSD 联盟推行 3D 内容开放标准
导读Pixar、Adobe、Apple、Autodesk 与 NVIDIA 联手 Linux 基金会旗下的联合开发基金会(JDF)宣布建立 OpenUSD 联盟(AOUSD)以推行 Pixar 创建的通用场景描述技术的标准化、开发、进化和发展。 联盟寻求通过推进开放式通用场景描述…...

ansible剧本之role角色模块
role角色 一:Roles 模块1.roles 的目录结构:2.roles 内各目录含义解释3.在一个 playbook 中使用 roles 的步骤:(1)创建以 roles 命名的目录(2)创建全局变量目录(可选)&am…...
网络安全领域的常见攻击方式及防御手段
目录 重放攻击(Replay Attack)防御手段 SQL 注入(SQL Injection)防御手段 跨站脚本攻击(Cross-Site Scripting,XSS)防御手段 跨站请求伪造(Cross-Site Request Forgery,C…...

Python应用工具-Jupyter Notebook
工具简介 Jupyter Notebook是 基于 网页的用于交互计算的 应用程序,以网页的形式打开,可以在网页页面中直接编写代码和运行代码,代码的运行结果也会直接在代码块下 显示,文档是保存为后缀名为 . ipynb 的 JSON 格式文件。 操作指令…...
音视频 FFmpeg如何查询命令帮助文档
FFmpeg如何查询命令帮助文档 一、ffmpeg/ffplay/ffprobe区别二、ffmpeg命令查看帮助文档三、ffplay命令查看帮助文档四、ffprobe命令查看帮助文档注意 一、ffmpeg/ffplay/ffprobe区别 ffmpeg:超快音视频编码器ffplay:简单媒体播放器ffprobe:简单多媒体流分析器 二、ffmpeg命令…...

回归预测 | MATLAB实现CSO-SVM布谷鸟优化算法优化支持向量机多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现CSO-SVM布谷鸟优化算法优化支持向量机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现CSO-SVM布谷鸟优化算法优化支持向量机多输入单输出回归预测(多指标,多图)效果一…...
元宇宙电商—NFG系统:区块链技术助力商品确权。
在国内,以“数字藏品”之名崛起以来,其与NFT的对比就从未停歇。从上链模式到数据主权,从炒作需求到实际应用,从售卖形式到价值属性,在各种抽丝剥茧般的比较中,围绕两者孰优孰劣的讨论不绝于耳。 NFT的每一…...

【云原生】Docker基本原理及镜像管理
目录 一、Docker概述 1.1 IT架构的演进: 1.2 Docker初始 1.3 容器的特点 1.4 Docker容器与虚拟机的区别 1.5 容器在内核中支持2种重要技术 1.6 Docker核心概念 1)镜像 2)容器 3)仓库 二、安装Docker 2.1 Yum安装Docker…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...