VUE2.7项目配置webpack打包-详细操作步骤

一、Webpack简介

  Webpack是一个打包工具,可以把JS、CSS、Node Module、Coffeescrip、SCSS/LESS、图片等都打包在一起,因此,现在几乎所有的SPA项目、JS项目都会用到Webpack。

官网:https://webpack.js.org  

GitHub为https://github.com/webpack/ webpack 

二、创建基于Webpack的Vue2.7.js项目

  Webpack+Vue.js的方式来做项目的,这样才可以做到“视图”“路由”“component”等的分离,以及快速打包、部署及项目上线。

1. Webpack 的相关命令,以及项目常用到的命令,我全部放这里,请务必按照版本安装!!!

"cross-env": "^7.0.2",

"vue-template-compiler": "^2.6.14",

"webpack": "^5.70.0",

"webpack-dev-server": "^4.7.4"

"compression-webpack-plugin": "^9.2.0",

"css-loader": "^4.1.0",

"friendly-errors-webpack-plugin": "^1.7.0",

"is-glob": "^4.0.3",

"monaco-editor": "^0.27.0",

"monaco-editor-webpack-plugin": "^4.2.0",

"process": "^0.11.10",

"style-loader": "^3.3.1",

"stylus-loader": "^6.2.0",

"vue-loader": "^15.11.1",

"vue-style-loader": "^4.1.0",

"webpack-bundle-analyzer": "^4.5.0",

"webpack-cli": "^4.10.0",

"webpack-merge": "^5.8.0",

"webpackbar": "^5.0.2"

"cross-env": "^7.0.2",

package.json代码:

 "scripts": {
    "build:private": "cross-env CONFIG_ENV=private  webpack --config build/webpack.prod.js",
    "start:private": "cross-env CONFIG_ENV=private  webpack-dev-server --open --hot --config ./build/webpack.dev.js"
  },

2. 文件配置 

看下文件目录结构:

1)build/config.js文件:

'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.

const path = require('path')

let env
switch (process.env.CONFIG_ENV) {
  case 'local':
    env = require('../config/local.env')
    break
  case 'dev':
    env = require('../config/dev.env')
    break
  case 'stage':
    env = require('../config/stage.env')
    break
  case 'pro':
    env = require('../config/prod.env')
    break
  case 'private':
    env = require('../config/private.env')
    break
  default:
    break
}

module.exports = {
  shouldAnalyzerBundle: false,
  shouldSplitChunks: false,
  shouldGzipResource: false,
  htmlWebpackConfig: {
    // author: 'AnbanTech@FrontendTeam',
    // license: 'Copyright © 2019-2022 Anban Inc. All Rights Reserved. 安般科技.',
    title: '报告'
    // keywords: 'webpack, vue',
    // descritpion: 'learn how to config webpack to build vue project'
  }
}


 2)build/webpack.base.js文件:(重点分析)

const path = require('path')
const { resolve } = path
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { htmlWebpackConfig, shouldSplitChunks } = require('./config')
const WebpackBar = require('webpackbar')
const { VueLoaderPlugin } = require('vue-loader')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')

const isDev = process.env.NODE_ENV !== 'production'
function genereateAssetsLoader(shouldSplitChunks) {
  if (shouldSplitChunks) {
    return [
      {
        test: /\.(woff|woff2|eot|otf|ttf)$/,
        type: 'asset',
        generator: {
          filename: 'font/[hash][ext][query]'
        }
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[hash][ext][query]'
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        type: 'asset/resource',
        generator: {
          filename: 'media/[hash][ext][query]'
        }
      }
    ]
  } else {
    return [
      {
        test: /\.(woff|woff2|eot|otf|ttf)$/,
        type: 'asset/inline'
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        type: 'asset/inline'
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        type: 'asset/inline'
      }
    ]
  }
}

module.exports = {
  target: 'web',
  stats: {
    chunks: false,
    chunkModules: false,
    modules: false,
    children: false,
    timings: false,
    assetsSort: 'name',
    performance: false
  },
  entry: {
    app: resolve('src/main.ts')
  },
  output: {
    path: resolve('dist'),
    filename: shouldSplitChunks ? 'lib/[name].[chunkhash:8].js' : 'lib/bundle.js',
    publicPath: './',
    clean: true
  },
  resolve: {
    extensions: ['.js', '.vue', '.json', '.ts'],
    alias: {
      '@': path.resolve('src'),
      vue$: 'vue/dist/vue.esm.js'
    }
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        loader: 'ts-loader',
        exclude: /node_modules/,
        options: {
          appendTsSuffixTo: [/\.vue$/],
          transpileOnly: true
        }
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true
        },
        exclude: /node_modules/
      },
      {
        test: /\.md/,
        type: 'asset/source'
      },
      {
        test: /\.styl(us)?$/,
        use:
          !shouldSplitChunks || isDev
            ? ['vue-style-loader', 'css-loader', 'stylus-loader']
            : [MiniCssExtractPlugin.loader, 'css-loader', 'stylus-loader']
      },
      {
        test: /\.css$/,
        use:
          !shouldSplitChunks || isDev
            ? ['vue-style-loader', 'css-loader']
            : [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ].concat(genereateAssetsLoader(shouldSplitChunks))
  },
  plugins: [
    new MonacoWebpackPlugin({
      languages: ['c']
    }),
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin(
      Object.assign({}, htmlWebpackConfig, {
        filename: 'index.html',
        title: 'webpack测试',
        template: path.resolve('public/index.html'),
        minify: {
          removeAttributeQuotes: true,
          collapseWhitespace: true,
          removeComments: true,
          collapseBooleanAttributes: true,
          collapseInlineTagWhitespace: true,
          removeRedundantAttributes: true,
          removeScriptTypeAttributes: true,
          removeStyleLinkTypeAttributes: true,
          minifyCSS: true,
          minifyJS: true,
          minifyURLs: true,
          useShortDoctype: true
        }
      })
    ),
    shouldSplitChunks &&
      new MiniCssExtractPlugin({
        filename: 'css/[name].[contenthash:8].css',
        chunkFilename: 'css/[name].[contenthash:8].css'
      }),
    new CopyWebpackPlugin({
      patterns: [
        {
          from: resolve('public'),
          globOptions: {
            ignore: ['**/index.html', '**/.DS_Store']
          }
        },
        {
          from: path.resolve(__dirname, '../static'),
          to: 'static',
          globOptions: {
            ignore: ['.*']
          }
        }
      ]
    }),
    
    new WebpackBar({
      name: '正在打包',
      color: '#fa8c16'
    }),
    new FriendlyErrorsWebpackPlugin({
      clearConsole: true
    }),
    // new BundleAnalyzerPlugin({
    //   analyzerHost: '127.0.0.1',
    //   //  将在“服务器”模式下使用的端口启动HTTP服务器。
    //   analyzerPort: 8888, 
    //   //  路径捆绑,将在`static`模式下生成的报告文件。
    //   //  相对于捆绑输出目录。
    //   reportFilename: 'report.html',
    //   defaultSizes: 'parsed',
    //   //  在默认浏览器中自动打开报告
    //   openAnalyzer: true,
    //   //  如果为true,则Webpack Stats JSON文件将在bundle输出目录中生成
    //   generateStatsFile: false, 
    //   //  如果`generateStatsFile`为`true`,将会生成Webpack Stats JSON文件的名字。
    //   //  相对于捆绑输出目录。
    //   statsFilename: 'stats.json',
    //   //  stats.toJson()方法的选项。
    //   //  例如,您可以使用`source:false`选项排除统计文件中模块的来源。
    //   //  在这里查看更多选项:https:  //github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21
    //   statsOptions: null,
    //   logLevel: 'info'  // 日志级别。可以是'信息','警告','错误'或'沉默'。
    // })
  ].filter(Boolean)
}

 2)build/webpack.dev.js文件:(重点分析)

const webpack = require('webpack')
const path = require('path')
const { default: merge } = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base')
const config = require('./config')

let env
switch (process.env.CONFIG_ENV) {
  case 'local':
    env = require('../config/local.env')
    break
  case 'dev':
    env = require('../config/dev.env')
    break
  case 'stage':
    env = require('../config/stage.env')
    break
  case 'pro':
    env = require('../config/prod.env')
    break
  case 'private':
    env = require('../config/private.env')
    break
  default:
    break
}

module.exports = merge(baseWebpackConfig, {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map',
  cache: true,
  devServer: {
    static: false,
    devMiddleware: {
      publicPath: '/'
    },
    historyApiFallback: {
      rewrites: [{ from: /.*/, to: path.posix.join('/', 'index.html') }]
    },
    hot: true,
    compress: true,
    host: 'localhost',
    // 配置开发服务器的端口,默认为8080
    port: 3000,
    open: true,
    proxy: {
      '/Arrgemnt': {
        target: 'http://192.168.5.32:8031',
        // target: 'http://192.168.50.94:9050',
        changeOrigin: true
      },
      '/files': {
        target: 'http://192.168.5.32:21101',
        // target: 'http://192.168.50.94:9050',
        changeOrigin: true,
        pathRewrite: { '^/files': '' }
      },
      '/yh': {
        target: 'http://192.168.5.57:9050',
        // target: 'http://192.168.50.94:9050',
        changeOrigin: true
      },
      '/yh/analysis': {
        target: 'http://192.168.5.57:9050',
        ws: true,
        changeOrigin: true
      },
      '/abfuzz/': {
        target: 'http://192.168.5.57:21101',
        changeOrigin: true
      },
    },
    client: {
      logging: 'warn',
      overlay: false,
      progress: true,
      reconnect: true
    }
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': env
    }),

    new webpack.ProvidePlugin({
      process: require.resolve('process/browser')
    })
    
  ]
})

 3)build/webpack.prod.js文件:

const webpack = require('webpack')
const { default: merge } = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base')
const CompressionPlugin = require('compression-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const { shouldAnalyzerBundle, shouldGzipResource, shouldSplitChunks } = require('./config')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')

let env
switch (process.env.CONFIG_ENV) {
  case 'local':
    env = require('../config/local.env')
    break
  case 'dev':
    env = require('../config/dev.env')
    break
  case 'stage':
    env = require('../config/stage.env')
    break
  case 'pro':
    env = require('../config/prod.env')
    break
  case 'private':
    env = require('../config/private.env')
    break
  default:
    break
}

console.log('process.env.CONFIG_ENV:', process.env.CONFIG_ENV)

module.exports = merge(baseWebpackConfig, {
  mode: 'production',
  devtool: 'nosources-source-map', // production
  cache: false,
  plugins: [
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new webpack.ProvidePlugin({
      process: require.resolve('process/browser')
    }),
    shouldGzipResource &&
    new CompressionPlugin({
      filename: '[path][base].gz',
      algorithm: 'gzip',
      test: /\.(js|css)$/
    }),
    shouldAnalyzerBundle &&
    new BundleAnalyzerPlugin({
      analyzerMode: 'server',
      analyzerHost: '127.0.0.1',
      analyzerPort: 8889,
      reportFilename: 'report.html',
      defaultSizes: 'parsed',
      openAnalyzer: true,
      generateStatsFile: false,
      statsFilename: 'stats.json',
      statsOptions: null,
      logLevel: 'info'
    })
  ].filter(Boolean),
  optimization: shouldSplitChunks
    ? {
      runtimeChunk: true,
      minimize: true,
      minimizer: [`...`, new CssMinimizerPlugin()],
      splitChunks: {
        chunks: 'all',
        minChunks: 1,
        maxInitialRequests: 6,
        maxAsyncRequests: 6,
        cacheGroups: {
          commons: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendors',
            chunks: 'all'
          }
        }
      }
    }
    : {}
})

 4)config/dev.env.js文件:

'use strict'
const { default: merge } = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '"user-test.cosec.tech"',
  BASE_IP: '"47.100.28.180"',
  CONFIG_ENV: '"dev"'
})

 5)config/local.env.js文件:

'use strict'
const { default: merge } = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '""',
  BASE_IP: '""',
  CONFIG_ENV: '"local"'
})

 6)config/poc.env.js文件:

'use strict'
const { default: merge } = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '""',
  BASE_IP: '""',
  CONFIG_ENV: '"private"'
})

 7)config/private.env.js文件:

const { default: merge } = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '""',
  BASE_IP: '""',
  CONFIG_ENV: '"private"'
})

 8)config/prod.env.js文件:

'use strict'
module.exports = {
  NODE_ENV: '"development"',
  BASE_API: '"www.fuzzing.tech"',
  BASE_IP: '"43.248.189.190"',
  CONFIG_ENV: '"pro"'
}

 9)config/stage.env.js文件:

'use strict'

module.exports = {
  NODE_ENV: '"development"',
  BASE_API: '"user-stage.cosec.tech"',
  BASE_IP: '"47.101.189.106"',
  CONFIG_ENV: '"stage"'
}

9)public/index.vue

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link type="image/x-icon" rel="shortcut icon" href="data:;">
    <link type="image/x-icon" rel="shortcut icon" href="../logo.png"> 
    <title>
        <%= htmlWebpackPlugin.options.title %>
    </title>
    <meta name="author" content="<%= htmlWebpackPlugin.options.author %>">
    <meta name="license" content="<%= htmlWebpackPlugin.options.license %>">
    <meta name="description" content="<%= htmlWebpackPlugin.options.descritpion %>">
    <meta name="keywords" content="<%= htmlWebpackPlugin.options.keywords %>">
    <script src=./lib/data.js></script>

</head>

<body>
    <div id="app"></div>
</body>

</html>

10) static 文件下有图片昂;

3.运行命令和打包命令:

npm run start:private

npm run build:private

完结撒花✿✿ヽ(°▽°)ノ✿

其实我写的过程,不断地出现报错,坚持住,不断地解决掉!!

当前配置有些冗余的代码文件,后续还需要优化

代码放在了gitee上: git@gitee.com:cathyli2021/vue2.7_webpack.git 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/698893.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Desoutter电动拧紧扳手控制器维修看看这里

马头拧紧工具控制器作为现代工业生产中的重要设备&#xff0c;其稳定性和可靠性对于生产线的连续运行至关重要。然而&#xff0c;在使用过程中&#xff0c;由于各种原因&#xff0c;可能会出现马头电动拧紧控制器故障。【选择子锐机器人维修服务&#xff0c;您将享受以下优势和…

【递归、搜索与回溯】穷举vs暴搜vs深搜vs回溯vs剪枝

穷举vs暴搜vs深搜vs回溯vs剪枝 1.全排列2.子集 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 管他什么深搜、回溯还是剪枝&#xff0c;画出决…

部署LVS-DR模式(附带详细实验)

目录 一.数据包流向分析 二.DR模式特点 三.ARP问题及解决办法 四.实验部署 1.配置负载调度器&#xff08;192.168.80.105&#xff09; 1.1.安装并启用ipvsadm 1.2.配置虚拟IP地址&#xff08;VIP&#xff1a;192.168.80.100&#xff09; 1.3.调整 proc 响应参数 1.4.配…

【C#】pdf按页分割文件,以及分页合并,效果还不错,你值得拥有

欢迎来到《小5讲堂》 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景效果单页分割文件合并多页分割插件说明相关文章 背景 最近遇到一…

MySQL视图教程(02):重命名视图

MySQL 重命名视图 在 MySQL 中&#xff0c; ALTER VIEW 语句用于重命名一个数据库视图&#xff08;View&#xff09;。 MySQL 是一种常用的关系型数据库管理系统&#xff0c;提供了丰富的功能和操作来管理数据库中的数据和对象。其中&#xff0c;重命名视图是 MySQL 中的一种…

Kettle根据分类实现Excel文件拆分

将整理好的一份供应商付款明细Excel文件&#xff0c;按供应商拆分成多个Excel文件。 实现思路 本文我们首先将供应商付款明细表&#xff0c;按照“名称”拆分成多份Excel文件。拆分Excel文件打算用两个转换实现&#xff0c;一个用来将Excel数据读取到参数中&#xff0c;另外一…

HBuilder X运行项目到微信开发者工具调试和发布Uniapp小程序

1.下载和安装 HBuilderX hbuilder首页&#xff1a;https://www.dcloud.io/hbuilderx.html 下载hbuilder编辑器,选择对应的系统,Windows和mac正式版即可,下载后免安装直接点击即可使用。 打开HBuilder之后&#xff0c;它会要求你注册一个用户&#xff0c;然后才可以使用。 …

25岁学plc还来的急嘛?

当然来得及&#xff01;25岁学习 PLC&#xff08;可编程逻辑控制器&#xff09;是完全可以的。我这里有一套plc入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习plc&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&…

PyTorch 维度变换-Tensor基本操作

以如下 tensor a 为例&#xff0c;展示常用的维度变换操作 >>> a torch.rand(4,3,28,28) >>> a.shape torch.Size([4, 3, 28, 28])view / reshape 两者功能完全相同: a.view(shape) >>> a.view(4,3,28*28) ## a.view(4,3,28,28) 可恢复squeeze…

红黑树的基本原理

目录 一.概念与性质 二.基本操作 1.建树 2.插入 情况一 情况二 3.查找 4.验证 三.红黑树与AVL树的比较 一.概念与性质 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根…

Java(蓝桥杯)一维二维数组应用

介绍&#xff1a; 一维数组&#xff0c;用来熟悉代码&#xff0c;主要考察二维数组&#xff1a; 二维数组存储行、列数据&#xff0c;遍历&#xff0c;输出结果 二维数组的旋转 二维数组数据的找规律。等等 二维数组问题&#xff0c;不难&#xff0c;但是比较繁琐。需要细…

在Linux中进行Redis的yum安装与配置

redis安装在IP为x.x.x.x的服务器上 redis是使用内存作为主存&#xff0c;使用硬盘来实现数据持久化&#xff0c;而且redis是周期性的将数据写到硬盘上。这就意味着一旦服务器出现断电、重启之类的情况&#xff0c;很可能会出现数据丢失的情况&#xff0c;因此不建议使用redis来…

全能型施耐德可编程控制器M241介绍

施耐德M241是一款通信强大、定位控制、丰富扩展于一身的全能型可编程控制器&#xff0c;适用于具有速度控制和位置控制功能的高性能一体型设备。其内置以太网通信端口&#xff0c;可以提供FTP和网络服务器功能&#xff0c;能够更为便捷地整合到控制系统架构中&#xff0c;通过智…

vue -ant -design 卡片是布局 实现动态计算 当前的 左右间距 实现居中

是这样的一个样式 我们使用display :flex 布局的时候 我们全部剧中 display: flex;align-items: center;justify-content: center; 如果是上述的代码来说的话 总是最后的一个也是会居中的 这样就比较丑 我们好像就没有什么好的办法了 我们这自己写的 肯定没有组件牛 如果有…

JVM 类加载器的工作原理

JVM 类加载器的工作原理 Java 虚拟机&#xff08;JVM&#xff09;的类加载器是 JVM 体系结构中的一个重要组件&#xff0c;它负责动态加载 Java 类到内存中。类加载器的工作原理涉及几个关键步骤和概念。本文将详细介绍 JVM 类加载器的工作原理。 1. 类加载器的概念 类加载器…

4-1RT-Thread信号量

4-1RT-Thread信号量 在实时系统中&#xff0c;一项工作往往需要多个线程共同完成。而线程对CPU的使用权由其优先级来确定。如果线程的功能是独立的&#xff0c;如控制LED灯周期性闪烁&#xff0c;那么我们只需要关注线程具体功能的实现即可。但在线程之间需要配合完成某些功能时…

家用路由器究竟有多费电?小白实测

小白最近听到了个笑话&#xff1a; 有个奶奶跟朋友说家里上不了网&#xff0c;让他去看看。朋友过去之后看到路由器被拔掉了&#xff0c;就问奶奶&#xff1a;“怎么把路由器拔掉了呀&#xff1f;”奶奶说&#xff1a;“那个东西的灯一闪一闪的&#xff0c;太费电&#xff0c;…

达内Angular学习

课程地址:1.1-环境搭建~1_哔哩哔哩_bilibili 一、环境搭建 安装前,确保node.js和npm包已经安装,并符合版本要求。 C:\Users\liutong>node -v v20.10.0C:\Users\liutong>npm -v 10.2.3 正式安装前,检查镜像是否为境内的镜像: C:\Users\liutong>npm config get…

Java MyBatis实战:QueryWrapper中的and和or拼接技巧

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 一、引言 在Java Web开发中&#xff0c;MyBatis是一个非常流行的持久层框架。它通过XML或注解的方式将Java对象与数据库表进行映射&#xff0c;从而实现数据的增删改查操作。在使用MyBatis的过程中&#xff0c;经常…

学习了解 JSON Schema

在数字时代&#xff0c;数据的快速增长要求开发者掌握有效的管理和验证技术。JSON&#xff08;JavaScript Object Notation&#xff09; 是一种流行的轻量级数据交换格式&#xff0c;在网络编程中有广泛应用。为了应对复杂数据的挑战&#xff0c;JSON Schema 诞生&#xff0c;提…