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

html5特效网站个人网站备案麻烦吗

html5特效网站,个人网站备案麻烦吗,影视作品网站开发与设计,wordpress动效Webpack node、output.jsonpFunction 配置详解 最近尝试给一些用到 webpack 的项目升级到最新 webpack5 版本#xff0c;其中遇到了一些问题#xff0c;我挑了两个比较典型的问题#xff0c;其中主要涉及到了 webpack 的 node 属性跟 output.jsonpFunction #xff08;web…Webpack node、output.jsonpFunction 配置详解 最近尝试给一些用到 webpack 的项目升级到最新 webpack5 版本其中遇到了一些问题我挑了两个比较典型的问题其中主要涉及到了 webpack 的 node 属性跟 output.jsonpFunction webpack5 以前版本属性下面我们结合 webpack 的源码来分析一下这两个属性。 开始 这里使用的 webpack 版本为 webpack^4.46.0webpack^5.88.2 首先我们创建一个 webpack4 的项目 webpack-node1: mkdir webpack-node2 cd webpack-node2 npm init -y接着安装 webpack4 npm install -D webpack4.46.0 webpack-cli4.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 --modedevelopment可以看到因为我们的入口文件 src/index.js 是一个空文件所以打包后的 dist/main.js 文件除了一些 webpack 的辅助函数外入口文件里面为空。 最后我们创建一个 test.html 文件来测试 touch test.html!DOCTYPE html html langen headmeta charsetUTF-8titlewebpack4/titlescript src./dist/main.js/script /head body/body /htmlok项目我们就创建完了接下来我们看一下 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 objectwebpack.config.js module.exports {//...node: {global: false,__filename: false,__dirname: false,}, };从 webpack 3.0.0 开始node 选项可能被设置为 false以完全关闭 NodeStuffPlugin 插件。 node.global boolean warnTip 如果你正在使用一个需要全局变量的模块请使用 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 --modedevelopment浏览器打开 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 webpack5.88.2 webpack-cli5.1.4我们把 webpack4 项目的 src/index.js 文件的内容也复制一份 // 判断是浏览器环境 const isBrowser process.browser; console.log(isBrowser); console.log(__dirname); console.log(global);然后我们打包看效果 npx webpack build --modedevelopment可以看到直接报错了 因为在 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 isnt 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 isnt 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 isnt 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 --modedevelopment可以看到浏览器正常打印了执行结果。 我们看一下打包过后的 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 webpackChunkwebpackwebpack 用于加载 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 {NonNullableOutput[uniqueName]} */ (output.uniqueName))));总结 不得不说webpack5 修复了很多之前留下的坑配置变得更简单了如果可以的话建议升级一下项目的 webpack 版本可以带来很多性能的优化和避免一些程序异常的发生。 希望以上的分享能够给你带来一些小小的帮助。
http://wiki.neutronadmin.com/news/141357/

相关文章:

  • 网站建设与管理个人职业生涯规划书黑龙江建设局网站
  • 湖南手机版建站系统信息北京建设部网站官网
  • 蜘蛛云建站网站高端营销型网站
  • 重庆选科网站香河县做网站
  • 网站首页开发收费管城区-建设局门户网站
  • 莆田城市投资建设集团网站简道云crm管理系统
  • 分类门户网站开发团队wordpress比特币插件
  • 建设网站应该注意的地方网址导航app下载
  • 网站建设属于哪个税收服务编码百度推广方案怎么写
  • 网站维护优化做故障风的头像的网站
  • 网页版面设计包括什么内容吉林长春seo网络推广
  • 网站管理员后台wordpress网店插件
  • 网站开发 -(广告)网上怎么做网站
  • 手机网站建设视频建设银行官方网站认证
  • 孝感网站开发的公司电话无锡比较大的互联网公司
  • 做个什么样的网站比较好服装网页怎么制作
  • 帮人做网站收费合法吗cg资源网
  • 网站只做优化谷歌seo是什么意思
  • 宠物网站首页模板网站建设与制作培训通知
  • 中小企业门户网站建设策略长春财经学院
  • 网站模板框架cloud域名注册网站
  • 灌南县建设局网站手机站和网站有区别吗
  • 网站建设主流技术设计师培训 网站
  • 360全景网站建设最强的管理咨询公司
  • 网站搭建素材群网络销售怎么一直招人
  • 一个交易网站开发的成本是多少经典网页传奇
  • 佟年帮韩商言做网站是第几集紫网站建设
  • 大良营销网站建设流程微山网站建设公司
  • 门户网站如何制作网页设计师联盟qq
  • 网站开发报告做网站互联网公司有哪些