前端实现发布版本,浏览器自动刷新

220 阅读2分钟

versionUpdatePlugin.js


// versionUpdatePlugin.js
const fs = require('fs')
const path = require('path')
 
const writeVersion = (versionFile, content) => {
  // 写入文件
  fs.writeFile(versionFile, content, (err) => {
    if (err) throw err
  })
}
 
export default (options) => {
  let config
 
  return {
    name: 'version-update',
 
    configResolved(resolvedConfig) {
      // 存储最终解析的配置
      config = resolvedConfig
    },
 
    buildStart() {
      // 生成版本信息文件路径
      const file = config.publicDir + path.sep + 'version.json'
      // 这里使用编译时间作为版本信息
      const content = JSON.stringify({ version: options.version })
 
      if (fs.existsSync(config.publicDir)) {
        writeVersion(file, content)
      } else {
        fs.mkdir(config.publicDir, (err) => {
          if (err) throw err
          writeVersion(file, content)
        })
      }
    },
  }
}

配置vite


import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import svgLoader from "vite-svg-loader";
import vue from "@vitejs/plugin-vue";
import viteCompression from 'vite-plugin-compression'
import versionUpdatePlugin from './versionUpdatePlugin.js'
import { createSvgIconsPlugin } from "vite-plugin-svg-icons"; // ==================这行 2
const path = require("path");
// console.log(process.env.NODE_ENV, 'process.env.NODE_ENV')
// import { visualizer } from 'rollup-plugin-visualizer';  // 体积分析工具
// import { visualizer } from 'rollup-plugin-visualizer';
// https://vitejs.sit/config/

const version = new Date().getTime() //使用时间戳当作版本号
export default defineConfig(
  ({mode})=>{
    return   {
      define: {
        // 定义全局变量
        __APP_VERSION__: version,
      },
      esbuild: {  
        drop: ["console", "debugger"],  
      },
      plugins: [
        vue(),
        svgLoader(),
        createSvgIconsPlugin({
          // 指定需要缓存的图标文件夹
          iconDirs: [path.resolve(process.cwd(), "src/assets/icons")],
          // 指定symbolId格式
          symbolId: "icon-[name]",
        }),
        // 静态资源压缩
        viteCompression({
          verbose: true, // 默认即可
          disable: false, // 开启压缩(不禁用),默认即可
          deleteOriginFile: false, // 删除源文件
          threshold: 5120, // 压缩前最小文件大小
          algorithm: 'gzip', // 压缩算法
          ext: '.gz' // 文件类型
        }),
        versionUpdatePlugin({
          version: version
        }),
        // 将 visualizer 插件放到最后
        // visualizer({ open: true })
      ],
      resolve: {
        alias: {
          "@": fileURLToPath(new URL("./src", import.meta.url)),
        },
      },
      base: "/",
      server: {
        host: "0.0.0.0",
        strictPort: false,
        port: 6173,
        proxy: {
          "/base_api": {
            // target: 'https://sit-aws-sport.exchangs.top',
            target: "https://sit-co-server.exchangs.top",
            // target: 'http://192.168.1.175:8088/',
            // target: 'http://192.168.1.70:8088/', // wj
            // target: 'http://192.168.1.224:8088/',
            // target: 'http://192.168.1.200:8088/',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/base_api/, ""),
          },
          "/report_api": {
            // sit-report-server.exchangs.top/v1/order/list
            target: 'https://uat-report-server.exchangs.top',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/push_api/, ""),
          },
          "/push_api": {
            // target: "https://sit-push.exchangs.top/",
            target: 'https://sit-push-server.exchangs.top',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/push_api/, ""),
          },
          "/order_api": {
            target: "https://sit-settle-center.exchangs.top",
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/order_api/, ""),
          },
          "/orderbus_api": {
            // target: "https://sit-push.exchangs.top/",
            target: 'https://sit-order-bus.exchangs.top',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/orderbus_api/, ""),
          },
          "/advance_api": {
            // target: "https://sit-push.exchangs.top/",
            target: 'https://sit-advance-settle.exchangs.top',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/advance_api/, ""),
          },
          "/cojob_api": {
            // target: "https://sit-push.exchangs.top/",
            target: 'https://sit-co-jobs.exchangs.top',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/cojob_api/, ""),
          },
          "/market_api": {
            // target: "https://sit-push.exchangs.top/",
            target: 'https://sit-market-server.exchangs.top/',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/market_api/, ""),
          },
        },
      },
      build: {
        sourcemap: !mode === 'production',  // 关闭生成map文件 可以达到缩小打包体积
        minify: true, // 开启压缩
        reportCompressedSize: false, // 关闭文件计算
        cssCodeSplit: true, // 开启css拆分
        rollupOptions: {
          output: {
            chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
            entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
            assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
            // 大文件拆分
            manualChunks(id) {
              if (id.includes("node_modules")) {
                  //把 vue-router 
                if (id.includes('vue-router')) {
                  return 'vue';
                }
                else{
                  //最小化拆分包
                  return id
                    .toString()
                    .split("node_modules/")[1]
                    .split("/")[0]
                    .toString();
                }
              }
            },
          }
        }
      }
    }
  }

);

路由配置生效

const debounceVersionUpdate = _.debounce(()=>{
  showUpdateInfo()
},1000,{
  leading: true,
})
const showUpdateInfo = ()=>{
    console.log('showUpdateInfo')
    const info = window.localStorage.getItem('lang') === 'zhHK' ? '发现新版本,自动更新中...' : 'Discovering new version, automatically updating...'
    //正式环境并且版本号校验未通过
    message.info(`${info}`,2).then(()=>{
      window.location.reload(true);
  })
}



router.beforeEach(async (to, from, next) => {
  let  response = null
  response = await axios.get(`/version.json`,{
    headers: {
      'Cache-Control': 'no-cache'
    }
  })
  // if(process.env.NODE_ENV !== "development"){
  //   response = await axios.get('/version.json')
  // }

  // console.log('response.version',response.data.version)
  // console.log('__APP_VERSION__',__APP_VERSION__)
  // console.log('process.env.NODE_ENV',process.env.NODE_ENV)
  if (process.env.NODE_ENV === "development"||(process.env.NODE_ENV !== "development"&&__APP_VERSION__ == response.data.version)) {
    // response.data.version  = response.data.version + 1  
    // if (__APP_VERSION__ == response.data.version) {
    //处理正常路由跳转逻辑
    if (to.path !== '/Login' && !localStorage.getItem('token')) {
      next({path: '/Login', replace: true})
    } else {
      if (to.path !== from.path) {
        resetTableData()
        resetPage()
      }
      if (to.path !== '/' && to.path !== '/Login') {
        // 缓存权限
        useIsPermission()
        const { addTab } = useNavTab()
        const systemStore = useSystemStore()
        const { routeData, menuMap } = storeToRefs(systemStore)
        // console.log(menuMap, 'menuMap')
        // 添加子菜单
        for (const key in  menuMap) {
            const element = menuMap[key];
            if (element&&element.children&&element.children.length>0) {
               element.children.forEach(child=>{
                 menuMap[child.path] = child
               })
            }
        }
        const { initRouteData } = systemStore
        if (!routeData.value || routeData.value.length === 0) {
          await initRouteData()
          next({path: to.path, query: to.query, replace: true})
        } else {
          // debugger
          next()
        }
        addTab({
          name: (menuMap[to.path] || {}).title,
          path: to.path,
          query: to.query,
          fixed: false
        })
      } else {
        // debugger
        next()
      }
    }
  }else{
    debounceVersionUpdate()
    console.log('debounceVersionUpdate')
    // debugger
    next()
  }
})


export default router