2 Star 28 Fork 10

kevin / 中后台管理系统

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
49打包生产环境配置.md 12.45 KB
一键复制 编辑 原始数据 按行查看 历史

生产环境配置

项目打包报错问题

项目配置相关的功能都完成以后,目前项目已经可以作为一个脚手架去使用了,这里先看一下打包生产环境是否有问题,在执行打包生产环境时,目前项目会有报错出现,其主要是src/router/index.ts文件中,导入路由模块时,await不是单独使用,需配合async使用,这里需要修改一下:

// 自动导入modules文件夹下的所有路由模块
const modules = import.meta.globEager("./modules/*.ts");
const routes:any = [];
for(const path in modules){
  modules[path].default.forEach(function(item: any){
    routes.push(item);
  });
}

这里换一种写法即可,此时再次打包生产环境代码,就不会再有报错问题出现了。

打包分析文件生成路径修改

默认的打包分析文件report.html是放在了根目录,这里修改一下生成到生产环境的打包目录根路径内,修改vite.config.ts文件:

plugins: [
  
  ...

  // 打包分析
  lifecycle === "report"
  ? visualizer({ open: true, brotliSize: true, filename: VITE_OUTDIR+"/report.html" })
  : null
]

生产环境使用mock数据

修改src/mockProdServer.ts文件:

import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'

const modules = import.meta.globEager('../mock/*.ts')

const mockModules: any[] = []
Object.keys(modules).forEach((key) => {
  modules[key].default.forEach((item) => {
    mockModules.push(item)
  })
})
export function setupProdMockServer() {
  createProdMockServer(mockModules)
}

这里批量将mock文件夹下得模拟数据导入,用于生产环境使用。

修改tsconfig.json文件:

  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue","vite.config.ts","build/*.ts", "types/*.d.ts", "mock/*.ts"],

以上修改后,生产环境使用mock模拟数据的配置是完成了,但如果直接本地起服务运行打包后的生产环境代码,mock模拟数据依然无法使用。需要修改配置文件vite.config.ts:

viteMockServe({
  mockPath: './mock', // 模拟接口api文件存放的文件夹
  watchFiles: true, // 将监视文件夹中的文件更改。 并实时同步到请求结果
  localEnabled: command === 'serve' // ,设置是否启用本地 xxx.ts 文件,不要在生产环境中打开它.设置为 false 将禁用 mock 功能
}),

这里将之前配置的生产环境启用mock相关代码移除,配置在这里不生效,目前暂未发现为何如此,除了配置在这里外,还可以直接配置到src/main.ts文件中:

import { setupProdMockServer } from './mockProdServer'
// production mock server
if (process.env.NODE_ENV === 'production') {
  setupProdMockServer()
}

然后修改.env相关文件,增加NODE_ENV变量配置,各环境变量文件各自增加该变量,值为对应环境名即可。

此时再重新生成生产环境代码,启动本地服务,mock功能就可以正常使用了。

生产环境打包有些文件太大的问题

打包后的文件有些太大,大文件需要再次拆分,拆分的原理就是项目在打包时,将很多插件都打包到了一个文件内,这里需要做的是将那些大插件单独进行打包,小插件可以合并打包到一个文件。

修改vite.config.ts文件:

// 生产环境配置
build:{
  outDir:VITE_OUTDIR,
  assetsDir:"assets",
  sourcemap:false,
  brotliSize:false,
  reportCompressedSize:false,
  // 消除打包大小超过500kb警告
  chunkSizeWarningLimit:1024,
  minify: 'terser',
  target: 'esnext', 
  rollupOptions:{
    output:{
      manualChunks(id){
        if (id.includes('node_modules')) {
          const currentPlugin = id.toString().split('node_modules/')[1].split('/')[0].toString();
          if(currentPlugin=="element-plus"||currentPlugin=="@element-plus"||currentPlugin=="lodash-es"||currentPlugin=="@vue"||currentPlugin=="china-area-data"){
            return currentPlugin;
          }else if(currentPlugin=="@iconify"){
            const iconType = id.toString().split('node_modules/')[1].split('/')[3].split('.')[0].toString()
            return currentPlugin+'_'+iconType;
          }else{
            return '_vendor';
          }
        }
      }
    }
  }
},

这里主要是对打包过程进行了判断,将资源比较大的插件,进行了单独打包,特别是@iconify插件,本身项目引入了其中的5个图标集,每个图标集的json文件都非常大,这里针对该文件也做了特定的逻辑判断,将5个图标集都分别打包成一个文件,此时再打包项目,资源除了gif图片还是太大外,其它资源文件就只有element-plus以及@iconify的每个图标集文件还是太大,这个是资源本身就多,已无法再次拆分

生产环境打包移除console

项目在之前配置了vite-plugin-remove-console插件用来移除consolevite本身是可以通过配置实现移除console的,这里删除vite-plugin-remove-console相关代码,修改vite.config.ts文件:

// 生产环境配置
build:{
  ...

  // 清除console和debugger
  terserOptions: {
    compress: {
      drop_console: true,
      drop_debugger: true,
    },
  },

  ...
},

生产环境打包压缩图片

npm i vite-plugin-imagemin -D

修改vite.config.ts文件:

import viteImagemin from 'vite-plugin-imagemin'

plugins:[

  ...

  viteImagemin({
    gifsicle: {
      optimizationLevel: 7,
      interlaced: false,
    },
    optipng: {
      optimizationLevel: 7,
    },
    webp: {
      quality: 75,
    },
    mozjpeg: {
      quality: 65,
    },
    pngquant: {
      quality: [0.65, 0.9],
      speed: 4,
    },
    svgo: {
      plugins: [
        {
          removeViewBox: false,
        },
        {
          removeEmptyAttrs: false,
        },
      ],
    },
  })
]

该配置完成后在打包线上环境的代码,图片资源就会被自动压缩(gif压缩有可能压缩后会变更大)

需要注意该插件的安装会比较麻烦,如下载不成功可按插件官方指明的方式进行安装。

开启GZIP压缩

前端开启gzip压缩,后端需要做相应的配置,开启gzip压缩后,可以减少对服务端内存的使用,从而提升浏览器加载速度,提升优化用户性能体验。gzip压缩后,打包的文件中,被gizp压缩的文件会被打包为.gz格式的文件,在将打包后的文件部署到服务器后,服务端通过配置开启gzip功能,虽然资源格式是.gz后缀的文件,但客户端浏览器也依然能成功读取文件内容。

gzip压缩主要是为了将大的资源压缩成.gz格式的压缩包,资源整体变小,减少服务端的内存占用,在浏览器下载资源时,也会更快一些,浏览器在下载.gz格式资源后,再进行解压,解压后的文件与源文件的大小没有变化,这个过程主要是减少服务端内存占用,以及加快浏览器下载速度。

npm i vite-plugin-compression -D

修改vite.config.ts文件:

import viteCompression from 'vite-plugin-compression'


plugins:[

  ...

  viteCompression({
    verbose: true,
    disable: false, // 不禁用压缩
    deleteOriginFile: false, // 压缩后是否删除原文件
    threshold: 10240, // 压缩前最小文件大小
    algorithm: 'gzip', // 压缩算法
    ext: '.gz', // 文件类型
  })
]

gzip需要配合服务端启用,在服务端成功开启gzip功能后,可以在chromenetwork中查看资源的下载,在size列中,如果一个资源有两个不一样大小的体积显示,则代表gzip已成功开启。

浏览器是配合服务器启用gzip,需要在资源请求的时候,在header里面带上accept-encoding:gzip参数,服务端接收到header,发现里面有该配置后,则发送gzip之后的文件,如果没有,则发送源文件。浏览器则根据response header来处理要不要针对返回的文件进行解压,然后展示。

生产环境打包资源未分类问题,文件名自定义

现在的所有资源都是统一放在assets文件夹下,这里进行一些配置,让各类型的文件分别放在不同的文件夹内。并对文件名进行一定的修改。

修改vite.config.ts文件:

// 生产环境配置
build:{
  outDir:VITE_OUTDIR,
  assetsDir:"assets/images",
  sourcemap:false,
  brotliSize:false,
  reportCompressedSize:false,
  // 消除打包大小超过500kb警告
  chunkSizeWarningLimit:1024,
  minify: 'terser',
  target: 'esnext', 
  // 清除console和debugger
  terserOptions: {
    compress: {
      drop_console: true,
      drop_debugger: true,
    },
  },
  rollupOptions:{
    output:{
      chunkFileNames: (chunkInfo) => {
        const facadeModuleId = chunkInfo.facadeModuleId ? chunkInfo.facadeModuleId.split('/') : [];
        let fileName = ''
        if(facadeModuleId.length>0&&facadeModuleId[facadeModuleId.length-1]==='index.vue'){
          const index = facadeModuleId.indexOf('views');
          const idx = facadeModuleId.indexOf('src');
          if(idx>0){
            if(index>0){
              fileName = 'vk_'+facadeModuleId.slice(index+1,facadeModuleId.length-1).join('_');
            }else{
              fileName = 'vk_'+facadeModuleId.slice(idx+1,facadeModuleId.length-1).join('_');
            }
          }else{
            fileName = 'vk_[name]';
          }
        }else{
          fileName = 'vk_[name]';
        }
        return `assets/js/${fileName}-[hash].js`;
      },
      entryFileNames: (chunkInfo) => {
        return 'assets/js/vk_[name]-[hash].js'
      },
      assetFileNames: (assetInfo)=>{
        return 'assets/[ext]/vk_[name]-[hash].[ext]';
      },
      manualChunks(id){
        if (id.includes('node_modules')) {
          const currentPlugin = id.toString().split('node_modules/')[1].split('/')[0].toString();
          if(currentPlugin=="element-plus"||currentPlugin=="@element-plus"||currentPlugin=="lodash-es"||currentPlugin=="@vue"||currentPlugin=="china-area-data"||currentPlugin=="jsencrypt"||currentPlugin=="crypto-js"){
            return currentPlugin;
          }else if(currentPlugin=="@iconify"){
            const iconType = id.toString().split('node_modules/')[1].split('/')[3].split('.')[0].toString()
            return currentPlugin+'_'+iconType;
          }else{
            return '_vendor';
          }
        }
      }
    }
  }
},

这里修改了assetsDir的默认值,将资源默认打包到assets/images文件夹内,并通过修改chunkFileNames,将拆分的js文件,打包到assets/js文件夹内,并通过获取拆分的js的文件路径拼接命名;作为单页面应用的入口文件,通过修改entryFileNames,可以修改其打包位置及文件名;assetFileNames可以将css文件打包到css文件夹内,这里因为该插件assetInfo参数并未返回css文件的路径,无法根据路径修改文件。

以上修改后,再次打包,各类型文件就生成到了各自类型的文件夹中了。而且js文件也根据其具体拆分文件的路径进行了命名。

关于@vitejs/plugin-legacy

该插件是用来做低版本浏览器兼容性支持的,它会额外生成一套代码,因为该插件也会有自己的入口文件,如果开启了该插件的支持,会发现在assets/images中也会生成一个legacy后缀的.js文件,这是由于该插件的入口文件并未走entryFileNames;目前除了关闭该功能外,尚未找到能修改其生成路径的办法。另外该插件虽然可以做低版本浏览的兼容性支持,但需要对应的前端框架语言能支持对应浏览器的低版本才能生效,vue3因已经放弃了对ie11的支持,所以在vue3项目中想通过该插件实现对ie11的支持是办不到的。

相关配置:

plugins:[

  ...

  // 是否为打包后的文件提供传统浏览器兼容性支持(vue3本身不支持ie11,所以vite虽然能为支持ie11的语言做兼容性支持,但不能为vue3做兼容性支持)
  VITE_LEGACY
  ? legacy({
      targets: ['defaults', 'not IE 11'], // 这里可以设置多个浏览器内核版本,使用vue3的情况下,设置ie11的兼容性也不会起作用。
      // targets: ['ie >= 11','chrome >= 52'], // 这里可以设置多个浏览器内核版本,使用vue3的情况下,设置ie11的兼容性也不会起作用。
      // additionalLegacyPolyfills: ["regenerator-runtime/runtime"] // 面向ie11时需要此插件
    })
  : null,

  ...

]

以上是打包过程中的一些操作修改。

马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/ctokevin/vue-admin-system.git
git@gitee.com:ctokevin/vue-admin-system.git
ctokevin
vue-admin-system
中后台管理系统
main

搜索帮助

344bd9b3 5694891 D2dac590 5694891