一.概述

  1. 使用CDN的好处
  2. 缓解服务器的压力,将首屏加载时的请求分摊给其它的服务器
  3. 优化打包后verdor.js过大问题
  4. 加快首屏加载速度
  5. 加快打包速度
  6. 尤其是Vue3新的Tree-Shaking技术,只打包需加载的模块module,搭配CDN后如虎添翼!

二.CDN网站分享

根据需要自行切换相关CDN
依赖引用并非全部可用,有的js会不兼容, 自行尝试通过可用后在进行引用操作!

  1. 国内
    BootCdn网站 https://www.bootcdn.cn/
    七牛云 http://staticfile.org/

  2. 国外
    unpkg网站 https://unpkg.com
    cdnjs网站 https://cdnjs.com/
    jsdelivr网站 https://www.jsdelivr.com/

vite-plugin-cdn-import:cdn的引入插件

npm i vite-plugin-cdn-import
or
pnpm i vite-plugin-cdn-import

vite.config.js

// import { autoComplete, Plugin as importToCDN } from 'vite-plugin-cdn-import'// 引入cdn
import { Plugin as importToCDN } from 'vite-plugin-cdn-import'

plugins: [
  vue(),
  eslint({
    // 配置项
    // include: ['src/**/*.js', 'src/**/*.vue', 'src/**/*.jsx', 'src/**/*.ts'],
    // exclude: ['./node_modules/**'],
    cache: false // 禁用eslint缓存
  }),
  // 自动导入 element-plus
  // AutoImport({
  //   resolvers: [ElementPlusResolver()]
  // }),
  // Components({
  //   resolvers: [ElementPlusResolver()]
  // }),
  // build生成分析工具
  visualizer({
    emitFile: true, // 打包后的分析文件会出现在打包好的文件包下
    filename: 'state.html', // 分析图生成的文件名
    open: true // 如果存在本地服务端口,将在打包后自动展示
    // sourcemap: true// 使用sourcemap计算大小
  }),
  // 第三方库CDN引入
  importToCDN({
    prodUrl: 'https://unpkg.com/{name}@{path}',
    modules: [
      // autoComplete('vue'),
      // autoComplete('axios'),
      // {
      //   name: 'vue',
      //   var: 'Vue',
      //   path: 'https://unpkg.com/vue@3.3.4'
      // },
      {
        name: 'vue',
        var: 'Vue',
        path: '3.3.4'
      },
      {
        name: 'vue-demi', // vue版本选好 不然会报错
        var: 'VueDemi',
        path: '0.14.5'
      },
      {
        name: 'vue-router',
        var: 'VueRouter',
        path: '4.2.2'
      },
      {
        name: 'element-plus',
        var: 'ElementPlus',
        path: '2.3.6',
        css: '2.3.6/dist/index.css'
      },
      {
        name: '@element-plus/icons-vue',
        var: 'ElementPlusIconsVue', // 根据main.js中定义的来
        path: '2.1.0'
      },
      {
        name: 'pinia',
        var: 'Pinia',
        path: '2.1.3'
      }
    ]
  })
],

使用cdn 引入 element-plus 一定也要用cdn 引入 vue、vue-demi 并且引入顺序不能出错,

  1. 如果不引入vue-demi,可以理解为vue和vue-demi 是互相引用的关系
    在这里插入图片描述

  2. 注意使用vite-plugin-cdn-import插件 不能按需引入element、直接在main.ts中使用全局引入的方式,打包后会自动按照cdn引入

main.ts

// import { App, createApp } from 'vue'
import { createApp } from 'vue'
// import "./style.css";
import AppData from './App.vue'
// routes
import router from './router/index'
import { createPinia } from 'pinia'
// 样式重置
import 'normalize.css'
import '@/assets/styles/index.scss'

import ElementPlus from 'element-plus'
// import * as icons from '@element-plus/icons'
// import 'element-plus/dist/index.css'//cdn 自动载入

import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const pinia = createPinia()
const app = createApp(AppData)
app.use(router)
app.use(ElementPlus)
app.use(pinia)
app.mount('#app')

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

最终打包展示

在这里插入图片描述

完整代码

import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
// import AutoImport from 'unplugin-auto-import/vite'
// import Components from 'unplugin-vue-components/vite'
// import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// import postCssPxToRem from 'postcss-pxtorem'
import eslint from 'vite-plugin-eslint' // 新增

import { resolve } from 'path'
// import path from 'path' // 配置文件路径相关时,需要用到此项  由于node不支持ts,需要安装依赖以便支持 需执行如下命令 npm install @types/node --save-dev
import { visualizer } from 'rollup-plugin-visualizer'// 分析优化
// import { autoComplete, Plugin as importToCDN } from 'vite-plugin-cdn-import'// 引入cdn
import { Plugin as importToCDN } from 'vite-plugin-cdn-import'

// https://vitejs.dev/config/
export default defineConfig(({ command, mode }) => {
  const env = loadEnv(mode, process.cwd()) // 获取.env文件里定义的环境变量
  console.log('command', command, 'mode', mode, 'env', env)
  // ****打包文件名称****
  let fileName = 'dist'
  // 兼容性,以防打包崩溃
  fileName = env.VITE_APP_NAME

  return {
    base: env.VITE_ENV === 'production' ? './' : './', // 静态路径访问地址
    build: {
      outDir: fileName,
      assetsDir: 'static', // 指定生成静态资源的存放路径
      emptyOutDir: true, // 清除输出目录
      // 设置为 false 可以禁用最小化混淆,或是用来指定使用哪种混淆器。默认为 Esbuild,它比 terser 快 20-40 倍,压缩率只差 1%-2%
      // npm add -D terser
      minify: 'terser', // boolean | 'terser' | 'esbuild',混淆:terser,false是否压缩代码
      sourcemap: true, // 构建后是否生成 source map 文件
      target: 'esnext',
      terserOptions: {
        compress: {
          // drop_console: true, // 生产环境去掉控制台 console
          // drop_debugger: true, // 生产环境去掉控制台 debugger 默认就是true
          // dead_code: true // 删除无法访问的代码 默认就是true
        }
      },
      // 文件超过500Kb解决办法
      chunkSizeWarningLimit: 1024 * 50,
      rollupOptions: {
        output: {
          // 最小化拆分包
          manualChunks (id) {
            if (id.includes('node_modules')) {
              return id.toString().split('node_modules/')[1].split('/')[0].toString()
            }
          },
          // dist下面的assets文件下,里面既有js、css等等。因此,可以将不同的文件放在不同的文件下,这样比较好。
          // 拆分js到模块文件夹
          chunkFileNames: (chunkInfo) => {
            const facadeModuleId = chunkInfo.facadeModuleId
              ? chunkInfo.facadeModuleId.split('/')
              : []
            const fileName1 = facadeModuleId[facadeModuleId.length - 2] || '[name]'
            return `js/${fileName1}/[name].[hash].js`
          },
          // 用于从入口点创建的块的打包输出格式[name]表示文件名,[hash]表示该文件内容hash值
          entryFileNames: 'js/[name].[hash].js',
          // 用于输出静态资源的命名,[ext]表示文件扩展名
          assetFileNames: '[ext]/[name].[hash:4].[ext]'
        }
      }
    },
    plugins: [
      vue(),
      eslint({
        // 配置项
        // include: ['src/**/*.js', 'src/**/*.vue', 'src/**/*.jsx', 'src/**/*.ts'],
        // exclude: ['./node_modules/**'],
        cache: false // 禁用eslint缓存
      }),
      // 自动导入 element-plus
      // AutoImport({
      //   resolvers: [ElementPlusResolver()]
      // }),
      // Components({
      //   resolvers: [ElementPlusResolver()]
      // }),
      // build生成分析工具
      visualizer({
        emitFile: true, // 打包后的分析文件会出现在打包好的文件包下
        filename: 'state.html', // 分析图生成的文件名
        open: true // 如果存在本地服务端口,将在打包后自动展示
        // sourcemap: true// 使用sourcemap计算大小
      }),
      // 第三方库CDN引入
      importToCDN({
        prodUrl: 'https://unpkg.com/{name}@{path}',
        modules: [
          // autoComplete('vue'),
          // autoComplete('axios'),
          // {
          //   name: 'vue',
          //   var: 'Vue',
          //   path: 'https://unpkg.com/vue@3.3.4'
          // },
          {
            name: 'vue',
            var: 'Vue',
            path: '3.3.4'
          },
          {
            name: 'vue-demi', // vue版本选好 不然会报错
            var: 'VueDemi',
            path: '0.14.5'
          },
          {
            name: 'vue-router',
            var: 'VueRouter',
            path: '4.2.2'
          },
          {
            name: 'element-plus',
            var: 'ElementPlus',
            path: '2.3.6',
            css: '2.3.6/dist/index.css'
          },
          {
            name: '@element-plus/icons-vue',
            var: 'ElementPlusIconsVue', // 根据main.js中定义的来
            path: '2.1.0'
          },
          {
            name: 'pinia',
            var: 'Pinia',
            path: '2.1.3'
          }
        ]
      })
    ],
    resolve: {
      // 配置路径别名
      alias: {
        '@': resolve(__dirname, './src')
        // '@': path.resolve(__dirname, 'src') // 用 @ 符号替换 src 文件路径
      }
    },
    css: {
      // 此代码为适配移动端px2rem
      // postcss: {
      //   plugins: [
      //     postCssPxToRem({
      //       rootValue: 37.5, // 1rem的大小(控制1rem的大小  点位:px)
      //       propList: ["*"], // 需要转换的属性,这里选择全部都进行转换
      //     }),
      //   ],
      // },
    },
    server: {
      host: '0.0.0.0',
      port: 3001, // 端口号
      open: false, // 是否自动打开浏览器
      // 跨域代理
      proxy: {
        // 字符串简写写法
        '/foo': 'http://localhost:4567',
        // 选项写法
        '/api': {
          target: 'http://jsonplaceholder.typicode.com',
          changeOrigin: true,
          rewrite: (path) => path.replace(/^\/api/, '')
        }
        // // 正则表达式写法
        // '^/fallback/.*': {
        //   target: 'http://jsonplaceholder.typicode.com',
        //   changeOrigin: true,
        //   rewrite: (path) => path.replace(/^\/fallback/, '')
        // },
        // // 使用 proxy 实例
        // '/api': {
        //   target: 'http://jsonplaceholder.typicode.com',
        //   changeOrigin: true,
        //   configure: (proxy, options) => {
        //     // proxy 是 'http-proxy' 的实例
        //   }
        // }
      }
    }
  }
})

Logo

前往低代码交流专区

更多推荐