我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Vite3迁移Webpack5的实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Vite3迁移Webpack5的实现

为什么要做迁移

现有问题

1、按需加载页面的时候加载速度慢。

2、热更新时常失效,手动刷新加载速度也慢。

性能提升

1、旧框架启动约13秒,但启动后每个页面切换加载都得等待5-10s,开发体验较差。新框架项目启动加所有页面加载约65秒。利用webpack5缓存的新特性,启动速度变快的同时,带来更好的开发体验。

2、旧框架在jenkins打包需要2分52秒,新框架打包仅需1分48秒,速度提升了37%。

webpack5为什么快

webpack5 较于 webpack4,新增了持久化缓存、改进缓存算法等优化,通过配置webpack 持久化缓存,来缓存生成的 webpack 模块和 chunk,改善下一次打包的构建速度,可提速 90% 左右

安装依赖

    "vue": "^3.2.37",
    "webpack": "5.64.4",
    "webpack-bundle-analyzer": "4.5.0",
    "webpack-cli": "4.10.0",
    "webpack-dev-server": "4.6.0",
    "webpack-merge": "5.8.0"
    "babel-loader": "8.2.3",
    "@babel/plugin-transform-runtime": "7.16.4",
    "clean-webpack-plugin": "4.0.0",
    "css-loader": "6.5.1",
    "css-minimizer-webpack-plugin": "3.2.0",// 对CSS文件进行压缩
    "mini-css-extract-plugin": "2.4.5",// 将CSS文件抽取出来配置, 防止将样式打包在 js 中文件过大和因为文件大网络请求超时的情况。
    "postcss-loader": "6.2.1",
    "postcss-preset-env": "7.0.1",
    "vue-style-loader": "4.1.3",
    "style-loader": "^3.3.2",
    "less-loader": "^11.1.0",
    "friendly-errors-webpack-plugin": "1.7.0",
    "html-webpack-plugin": "5.5.0",
    "progress-bar-webpack-plugin": "2.1.0",
    "vue-loader": "^17.0.1",    
    "eslint-webpack-plugin": "^4.0.0",
    "stylelint-webpack-plugin": "^4.1.0",
    "copy-webpack-plugin": "^11.0.0",
    "cross-env": "^7.0.3",
    "@babel/runtime-corejs3": "7.16.3"// 安装到dependencies

webpack5配置

为了区分开发环境和打包环境,分了3个js文件(base、dev、prod),通过webpack-merge这个插件,进行合并操作。

webpack.base.conf.js

const { resolve, babelLoaderConf } = require('./utils.js')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader/dist/index')
// const StylelintPlugin = require('stylelint-webpack-plugin')
const ESLintPlugin = require('eslint-webpack-plugin')
const { YouibotPlusResolver } = require('youibot-plus')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将CSS文件抽取出来配置, 防止将样式打包在 js 中文件过大和因为文件大网络请求超时的情况。
const { AntDesignVueResolver } = require('unplugin-vue-components/resolvers')
const isDev = process.env.NODE_ENV === 'development' // 是否是开发模式
module.exports = {
  entry: {
    app: resolve('class="lazy" data-src/main.ts')
  },
  resolve: {
    //引入模块时不带扩展名,会按照配置的数组从左到右的顺序去尝试解析模块
    extensions: ['.ts', '.tsx', '.js', '.vue', '.json'],
    alias: {
      '@': resolve('class="lazy" data-src')
    }
  },
  module: {
    noParse: /^(vue|vue-router|youibot-plus|echarts)$/, // 不解析库
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'vue-loader'
          }
        ],
        include: /(class="lazy" data-src)/
      },
      //babel7之后已经有了解析 typescript 的能力,也就不再需要 ts-loader
      {
        test: /\.(ts|js)x?$/,
        use: [
          {
            loader: 'thread-loader', // 开启多进程打包
            options: {
              worker: 3
            }
          },
          babelLoaderConf
        ],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: [
          // 开发环境使用style-looader(通过动态添加 style 标签的方式,将样式引入页面),打包模式抽离css
          isDev ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: false
            }
          }
        ]
      },
      {
        test: /\.less$/,
        use: [
          isDev ? 'vue-style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              sourceMap: false
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                // postcss-preset-env 内部集成了 autoprefixer 添加css第三方前缀
                plugins: ['postcss-preset-env']
              }
            }
          },
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                javascriptEnabled: true
              },
              additionalData: '@import "@/styles/variables.less";'
            }
          }
        ]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            // 文件小于 10k 会转换为 base64,大于则拷贝文件
            maxSize: 10 * 1024
          }
        },
        generator: {
          filename: 'images/[base]'
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        type: 'asset',
        generator: {
          filename: 'files/[base]'
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        type: 'asset',
        generator: {
          filename: 'media/[base]'
        }
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    //将打包后的文件自动引入到index.html里面
    new HtmlWebpackPlugin({
      template: resolve('public/index.html'),
      favicon: resolve('public/logo.ico')
    }),
    require('unplugin-vue-components/webpack')({
      resolvers: [
        AntDesignVueResolver({
          importStyle: false
        }),
        YouibotPlusResolver()
      ],
      dts: true,
      dirs: ['class="lazy" data-src/components', 'class="lazy" data-src/pages'] // 按需加载的文件夹
    }),
    require('unplugin-auto-import/webpack')({
      imports: ['vue', 'vue-router', 'pinia'],
      resolvers: [AntDesignVueResolver()],
      eslintrc: {
        enabled: true,
        filepath: '../.eslintrc-auto-import.json',
        globalsPropValue: true
      },
      dts: 'class="lazy" data-src/types/auto-imports.d.ts'
    }),
    // new StylelintPlugin(),
    new ESLintPlugin()
  ]
}

webpack.dev.js

const { merge } = require('webpack-merge')
const webpack = require('webpack')
const { getNetworkIp, resolve } = require('./utils.js')
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin')
const common = require('./webpack.base.conf')
const chalk = require('chalk')
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
const devWebpackConfig = merge(common, {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map',
  output: {
    path: resolve('dist'),
    filename: 'js/[name].[hash].js',
    chunkFilename: 'js/[name].[hash].js',
    publicPath: '/'
  },
  // 日志打印只打印错误和警告
  stats: 'errors-warnings',
  devServer: {
    host: getNetworkIp(),
    port: 8094, // 端口号
    open: true, // 自动打开
    hot: true, // 热更新
    allowedHosts: 'all',
    client: {
      progress: false, // 将运行进度输出到控制台。
      overlay: { warnings: false, errors: true } // 全屏显示错误信息
    }
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('development'),
      __VUE_OPTIONS_API__: true, //控制台警告处理
      __VUE_PROD_DEVTOOLS__: true //控制台警告处理
    })
  ],
  // 缓存
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename] // 针对构建的额外代码依赖的数组对象。webpack 将使用这些项和所有依赖项的哈希值来使文件系统缓存失效。
    },
    cacheDirectory: resolve('temp_cache'),
    name: 'scf-cache', // 路径temp_cache/scf-cache
    compression: 'gzip'
  }
})
devWebpackConfig.plugins.push(
  // 进度条
  new ProgressBarPlugin({
    format: `  :msg [:bar] ${chalk.green.bold(':percent')} (:elapsed s)`,
    clear: true
  }),
  // 错误提示
  new FriendlyErrorsWebpackPlugin({
    // 成功的时候输出
    compilationSuccessInfo: {
      messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${devWebpackConfig.devServer.port}`]
    },
    // 是否每次都清空控制台
    clearConsole: true
  })
)
module.exports = devWebpackConfig

webpack.prod.js

const path = require('path')
const { merge } = require('webpack-merge')
const webpack = require('webpack')
const { resolve } = require('./utils.js')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将CSS文件抽取出来配置, 防止将样式打包在 js 中文件过大和因为文件大网络请求超时的情况。
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin') // 对CSS文件进行压缩
const TerserPlugin = require('terser-webpack-plugin')
const common = require('./webpack.base.conf')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
module.exports = () => {
  const analyzerPlugins = process.env.NODE_ENV === 'analyzer' ? [new BundleAnalyzerPlugin()] : []
  return merge(common, {
    mode: 'production',
    optimization: {
      // chunk拆分,提升首屏加载速度
      splitChunks: {
        cacheGroups: {
          vendors: {
            // 提取node_modules代码
            test: /node_modules/, // 只匹配node_modules里面的模块
            name: 'vendors', // 提取文件命名为vendors,js后缀和chunkhash会自动加
            minChunks: 1, // 只要使用一次就提取出来
            chunks: 'initial', // 只提取初始化就能获取到的模块,不管异步的
            minSize: 0, // 提取代码体积大于0就提取出来
            priority: 1 // 提取优先级为1
          },
          commons: {
            // 提取页面公共代码
            name: 'commons', // 提取文件命名为commons
            minChunks: 2, // 只要使用两次就提取出来
            chunks: 'initial', // 只提取初始化就能获取到的模块,不管异步的
            minSize: 0 // 提取代码体积大于0就提取出来
          }
        }
      },
      // 压缩
      minimize: true,
      minimizer: [
        new TerserPlugin({
          parallel: true, // 开启多线程压缩
          terserOptions: {
            compress: {
              pure_funcs: ['console.log'] // 删除console.log
            }
          }
        }),
        new CssMinimizerPlugin()
      ],
      // tree shaking
      usedExports: true
    },
    performance: {
      hints: false
    },
    // devtool: 'source-map', //如果配置source-map的话,生产环境下也可以定位到具体代码,但是相应的打包文件也会变大(map文件体积,4m变成17m),而且会有代码暴露的风险。
    plugins: [
      // 清空dist
      new CleanWebpackPlugin(),
      new CopyPlugin({
        patterns: [
          {
            from: path.resolve(__dirname, '../public'), // 复制public下文件
            to: path.resolve(__dirname, '../dist'), // 复制到dist目录中
            filter: source => !source.includes('index.html') // 忽略index.html
          }
        ]
      }),
      // css抽离
      new MiniCssExtractPlugin({
        filename: 'css/[name].[contenthash].css',
        chunkFilename: 'css/[name].[contenthash].css'
      }),
      // css压缩
      new CssMinimizerPlugin(),
      new webpack.DefinePlugin({
        //在业务代码中也可以访问process变量区分环境
        'process.env.NODE_ENV': JSON.stringify('production'),
        __VUE_OPTIONS_API__: true, //控制台警告处理
        __VUE_PROD_DEVTOOLS__: false //控制台警告处理
      }),
      ...analyzerPlugins
    ],
    output: {
      path: resolve('dist'),
      filename: 'js/[name].[hash].js',
      chunkFilename: 'js/[name].[hash].js'
    }
  })
}

utils.js

const path = require('path')
const os = require('os')
exports.getNetworkIp = function () {
  let needHost = '' // 打开的host
  try {
    // 获得网络接口列表
    let network = os.networkInterfaces()
    for (let dev in network) {
      let iface = network[dev]
      for (let i = 0; i < iface.length; i++) {
        let alias = iface[i]
        if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
          needHost = alias.address
        }
      }
    }
  } catch (e) {
    needHost = 'localhost'
  }
  return needHost
}
exports.resolve = function (dir) {
  return path.join(__dirname, '..', dir)
}
// babel-loader配置
exports.babelLoaderConf = {
  loader: 'babel-loader',
  options: {
    presets: [
      [
        '@babel/preset-env',
        {
          targets: {
            browsers: ['ie>=8', 'chrome>=62'],
            node: '8.9.0'
          },
          debug: false,
          useBuiltIns: 'usage',
          corejs: '3.0'
        }
      ],
      [
        '@babel/preset-typescript',
        {
          allExtensions: true // 支持所有文件扩展名,否则在vue文件中使用ts会报错
        }
      ]
    ],
    plugins: [
      [
        //js文件在babel转码后会生成很多helper函数(可能有大量重复),polyfill会在全局变量上挂载目标浏览器缺失的功能,这个插件的作用是将 helper 和 polyfill 都改为从一个统一的地方引入,并且引入的对象和全局变量是完全隔离的
        //Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API(polify实现)
        '@babel/plugin-transform-runtime',
        {
          corejs: 3
        }
      ]
    ]
  }
}

知识点

环境区分

 // package.json 命令行
 "build:dev": "cross-env NODE_ENV=development webpack serve --config build/webpack.dev.js",
 "build:prod": "cross-env NODE_ENV=production webpack --config build/webpack.prod.js",
 "build:analyzer": "cross-env NODE_ENV=analyzer webpack serve --config build/webpack.prod.js",

在window环境下需要cross-env这个依赖帮助我们node环境下做变量标识,通过NODE_ENV进行声明即可。

//webpack.dev.js
new webpack.DefinePlugin({
   'process.env.NODE_ENV': JSON.stringify('development'),
   __VUE_OPTIONS_API__: true, //控制台警告处理
   __VUE_PROD_DEVTOOLS__: true //控制台警告处理
 })
//webpack.prod.js
new webpack.DefinePlugin({
     'process.env.NODE_ENV': JSON.stringify('production'),
     __VUE_OPTIONS_API__: true, //控制台警告处理
     __VUE_PROD_DEVTOOLS__: false //控制台警告处理
   }),

在代码中,通过definePlugin定义变量后,通过process.env.NODE_ENV来获取当前是开发环境还是生产环境。

css-loader和style-loader

css-loader的作用是将css文件转换成webpack能够处理的资源,而style-loader就是帮我们直接将css-loader解析后的内容挂载到html页面当中

asset资源模块

webpack5 新增资源模块(asset module),允许使用资源文件(字体,图标等)而无需配置额外的 loader。

{
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      type: 'asset',
      parser: {
        dataUrlCondition: {
          // 文件小于 10k 会转换为 base64,大于则拷贝文件
          maxSize: 10 * 1024
        }
      },
      generator: {
        filename: 'images/[base]'
      }
    },
    {
      test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
      type: 'asset',
      generator: {
        filename: 'files/[base]'
      }
    },
    {
      test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
      type: 'asset',
      generator: {
        filename: 'media/[base]'
      }
    }

性能优化

按需引入

echarts打包后占用体积过大

import * as echarts from 'echarts'//全局引入echarts
//按需引入echarts
import * as echarts from 'echarts/core'
import { BarChart } from 'echarts/charts'
import { LegendComponent, TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent } from 'echarts/components'
import { LabelLayout, UniversalTransition } from 'echarts/features'
import { CanvasRenderer } from 'echarts/renderers'
import { setTimeSecond, setTimeStr } from '@/utils/index'
import useStore from '@/stores'
// 注册必须的组件
echarts.use([
  LegendComponent,
  TitleComponent,
  TooltipComponent,
  GridComponent,
  DatasetComponent,
  TransformComponent,
  BarChart,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer
])

image.png

image.png

可以看到echarts如果是全局引用的情况下,打包体积有3.67m,但按需引入后就只有1.36m了。

组件库的按需引入

通过unplugin-vue-components/webpack插件,不会全局引入ant-design,会按需引入。

require('unplugin-vue-components/webpack')({
      resolvers: [
        AntDesignVueResolver({
          importStyle: false
        }),
        YouibotPlusResolver()
      ],
      dts: true,
      dirs: ['class="lazy" data-src/components', 'class="lazy" data-src/pages'] // 按需加载的文件夹
}),

分包策略

// chunk拆分,提升首屏加载速度
  splitChunks: {
    cacheGroups: {
      vendors: {
        // 提取node_modules代码
        test: /node_modules/, // 只匹配node_modules里面的模块
        name: 'vendors', // 提取文件命名为vendors,js后缀和chunkhash会自动加
        minChunks: 1, // 只要使用一次就提取出来
        chunks: 'initial', // 只提取初始化就能获取到的模块,不管异步的
        minSize: 0, // 提取代码体积大于0就提取出来
        priority: 1 // 提取优先级为1
      },
      commons: {
        // 提取页面公共代码
        name: 'commons', // 提取文件命名为commons
        minChunks: 2, // 只要使用两次就提取出来
        chunks: 'initial', // 只提取初始化就能获取到的模块,不管异步的
        minSize: 0 // 提取代码体积大于0就提取出来
      }
    }
  },

image.png

//index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/logo.ico" rel="external nofollow"  />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <script class="lazy" data-src="/config.js"></script>
    <title>YOUIFLEET</title>
    <link rel="icon" href="logo.ico" rel="external nofollow"  />
    <script defer="defer" class="lazy" data-src="js/vendors.cb5671c1aeb89321634e.js"></script>
    <script defer="defer" class="lazy" data-src="js/app.cb5671c1aeb89321634e.js"></script>
    <link href="css/vendors.acd8e0885f2241c62cf1.css" rel="external nofollow"  rel="stylesheet" />
    <link href="css/app.63706e02f684f71c27bd.css" rel="external nofollow"  rel="stylesheet" />
  </head>
  <body>
    <div id="app"></div>
    <link rel="stylesheet/less" href="/color.less" rel="external nofollow"  />
    <script class="lazy" data-src="/less-2.7.2.min.js"></script>
  </body>
</html>

这里可以看到通过分包策略后,打出了两个js文件,可以看到是defer异步执行,不阻塞html的渲染(async也是异步的,但是并行加载,js加载好了就会执行,如果js前后有依赖性,可能会出错)。

多线程打包

 {
        test: /\.(ts|js)x?$/,
        use: [
          {
            loader: 'thread-loader', // 开启多进程打包
            options: {
              worker: 3
            }
          },
          babelLoaderConf
        ],
        exclude: /node_modules/
      },

由于运行在 Node.js 之上的 webpack 是单线程模型的,我们需要 webpack 能同一时间处理多个任务,发挥多核 CPU 电脑的威力。

thread-loader 就能实现多线程打包,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程,来提升打包速度。

优化策略远不止这几项,还有路由懒加载组件懒加载gzip压缩cdn引入第三方依赖DllPlugin 动态链接库Web Worker骨架屏...通过打包后的结果进行对应分析即可。

踩坑记录

Stylelint报错

image.png

该问题需要通过husky配置lint-staged处理,但由于我们项目前后端代码放在一个大文件夹下内分单独文件夹管理,配置不了husky,所以只能暂时将stylelint-webpack-plugin给注释掉,如果大佬有解决方案可以在评论区提一下感谢。

Vue动态路由配置component

// 生成路由数据
const generateRoute = (list: Array<IRouteData>): RouterType[] => {
  const routerList: RouterType[] = []
  const modules = require.context('../pages', true, /\.vue$/).keys()
  
  function generateRouter(routers: Array<IRouteData>, routerData: RouterType[] = []): void {
    routers.forEach(routerItem => {
      const { url, name, icon, children } = routerItem
      //判断是否存在子路由
      const isRouteChildren = children && children.length && children[0].type === 0
      const redirect = isRouteChildren ? children[0].url : undefined
      const component =
        modules.indexOf(`.${url}/index.vue`) !== -1 ? () => import( `@/pages${url}/index.vue`) : null
      const routerItemData: RouterType = {
        path: url,
        redirect,
        name,
        component,
        meta: {
          title: name,
          icon: icon,
          attribution: name
        },
        children: []
      }
      if (isRouteChildren) {
        generateRouter(children, routerItemData.children)
      }
      routerData.push(routerItemData)
    })
  }
  generateRouter(list, routerList)
  return routerList
}

这个component配置包含了血泪史,因为之前一开始component配置的时候找不到父路由的时候,我给配了子路由的component,导致后面component加载重复一直切换报错,其实配置一个null就可以。

附录

感谢以下大佬的文章分享

# 透过分析 webpack 面试题,构建 webpack5.x 知识体系

# 前端性能优化——包体积压缩82%、打包速度提升65%

# 前端性能优化——首页资源压缩63%、白屏时间缩短86%

#【脚手架】从0到1搭建React18+TS4.x+Webpack5项目(一)项目初始化

到此这篇关于Vite3迁移Webpack5的实现的文章就介绍到这了,更多相关Vite3迁移Webpack5内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Vite3迁移Webpack5的实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Vite3迁移Webpack5的实现

本文主要介绍了Vite3迁移Webpack5的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-18

MySQL5.6迁移到DM8的实现示例

目录迁移前准备源库数据库信息迁移对象统计目标库DM 目的端信息初始化参数设置兼容性参数设置创建实例迁移过程创建迁移连接数据库连接源端 mysql 数据库连接目的端 DM 数据库配置迁移对象及策略数据类型映射开始迁移检查迁移任务查看迁移进度迁
MySQL5.6迁移到DM8的实现示例
2024-08-31

Python虚拟环境迁移的实现

本文主要介绍了Python虚拟环境迁移的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-03-06

mysql8.0.11数据目录迁移的实现

mysql的存储目录默认是在/var/lib/mysql/,下面将修改默认存储目录. 本文使用mysql8.0.11版本,与mysql8.0.20版本不同,8.0.20版本的数据迁移请看另一篇博客 : mysql8.0.20数据迁移1.先停
2022-05-25

docker容器热迁移如何实现

Docker容器热迁移可以通过以下步骤实现:使用Docker Swarm或Kubernetes等容器编排工具来管理容器,以确保容器在不同主机上运行。在需要迁移的容器上运行容器检查点工具,例如CRIU(Checkpoint and Resto
2023-10-27

如何实现迁移图片目录的bat

这篇文章给大家分享的是有关如何实现迁移图片目录的bat的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码如下:@echo off setlocal enabledelayedexpansion ::开启变量延迟,
2023-06-08

阿里云服务器能迁移:如何轻松实现数据迁移

简介阿里云服务器是一种强大的云计算服务,为用户提供了高性能、高可靠性的计算资源。在使用阿里云服务器的过程中,有时候我们需要将数据从一台服务器迁移到另一台服务器上。本文将介绍如何轻松实现阿里云服务器的数据迁移。数据迁移的步骤步骤一:备份数据在进行数据迁移之前,首先需要对要迁移的数据进行备份。可以使用阿里云提供的备份工具或
阿里云服务器能迁移:如何轻松实现数据迁移
2024-01-30

快速实现wordpress迁移到RadonDB上

作者: 吴炳锡,知数堂联合创始人及MySQL高级讲师,3306π社区联合创始人,腾讯TVP成员。本文大概5500字,阅读大概需要15分钟,建议电脑前阅读。大纲如下:概述使用Radon attache功能的好处基本环境描述把wordpress库加入到Radon中
快速实现wordpress迁移到RadonDB上
2017-06-30

docker容器热迁移怎么实现

Docker容器热迁移是指在不停止容器的情况下将容器从一个主机迁移到另一个主机。以下是一种实现热迁移的方法:使用Docker Swarm或Kubernetes进行容器编排和管理。这些工具可以自动管理容器的调度和迁移。确保主机之间的网络连接。
2023-10-23

Python虚拟环境迁移如何实现

本篇内容介绍了“Python虚拟环境迁移如何实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!使用python开发脚本使用的时候难免会遇到需
2023-07-05

编程热搜

目录